Need help implementing middleware usage in my router

blov · 2017-04-02 02:00:13 · 649 次点击    
这是一个分享于 2017-04-02 02:00:13 的资源,其中的信息可能已经有所发展或是发生改变。

guys i am working on coding a router called Garson , and i am trying to implement methods on my router that makes it easy to hook middlewares

i have 2 methods for that, one is called Before() and the other is called After() , the idea is, Before() calles middlewares before each request, and After() executes middlewares after each request.

in my ServeHTTP method, i am trying to execute each handler, my problem is when i execute the handler of the requested route, i am not able to execute the handler of the next middleware - which would be the first middleware of the middlewares registered with After()-, i have tried to call handler.ServeHTTP() and then next.ServeHTTP() but this only executes the first middleware registered with After() and ignores the others.

here is my ServeHTTP() method

here is example of usage, where middleware package is from github.com/emostafa/garson/middleware

func main() {
    router := garson.New()
    router.Before(middleware.Logger)
    router.After(someCustomMiddlewareOfYours)
    router.Get("/hello", hello) 
    http.ListenAndServe(":3000", router)
}

**评论:**

R2A2:

Why not this?

func main() {
    router := garson.New()
    router.Get("/hello", anotherCustomMiddleware(hello)) 
    http.ListenAndServe(":3000", someCustomMiddleware(middleware.Logger(router)))
}

In this way a middleware can act on individual routes, or the whole router. No need to have before/after - just wrap at whichever level.

BTW I think you're totally on the right track with plain http.Handlers and with func(http.Handler) http.Handler - this makes your work more flexible than other routers & middlewares (negroni/httprouter/etc etc), which use their own custom parameter specs. Not a criticism of their authors - they were working in a pre-r.Context() world, which forced their hands a little. Good for you.

Edit: sorry I forgot to include an example which does middleware-type stuff before/after running the inner handler/router/middleware.

See below:

https://github.com/laher/context-example/blob/master/main.go#L124

That repo is just some code samples I made for a meetup talk. See readme for more notes.

Does that answer your question?

emostafa:

@R2A2 my idea was that, you might need to execute some code after each response, for example, if you want to store some logs, how would you do that using:

 router.Get("/hello", anotherCustomMiddleware(hello))

another thing that i have in mind, is if i have like 3 or 4 middlewares that i want to execute before the request, that would be something like this ?

router.Get("/hello", middleware1(middleware2(middleware3(hello))))

my idea that it could look like this

router.Get("/hello", hello).Before(middleware1, middleware2, middleware3).After(middleware4)

of Use() of the whole concept of Before() and After() is wrong: router.Use(LoggerMiddleware) router.Get("/hello", hello).Use(middleware1, middleware2, middleware3, middleware4)

glad you liked the idea of going with plain http.Handler, this way my router could be flexible and to be used with any other libraries. I am glad that i am did something good :D thanks for your motiviation.

R2A2:

Here's a logging example (not storing but hopefully it illustrates the idea):

func anotherCustomMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    log.Println("start", time.Now(), r.Method, "-", r.RequestURI)
    next.ServeHTTP(w, r)
    log.Println("finish", time.Now(), r.Method, "-", r.RequestURI, w.Status)
})
}

Sorry I don't really value the Before/After/Use thing that much. I think you'd typically have most middlewares wrapped around a single router, and then maybe zero/one/2 middlewares around the individual routes, so not very troublesome. If you're getting more complex than that I'd recommend nesting routers instead. I think Use() just adds an unnecessary layer. But, up to you.


入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

649 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传