Need help implementing middleware usage in my router

blov · · 440 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>guys i am working on coding a router called <a href="https://github.com/emostaf/garson">Garson</a> , and i am trying to implement methods on my router that makes it easy to hook middlewares</p> <p>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.</p> <p>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.</p> <p>here is my <a href="https://github.com/emostafa/garson/blob/middleware/router.go#L149">ServeHTTP() method</a></p> <p>here is example of usage, where middleware package is from github.com/emostafa/garson/middleware</p> <pre><code>func main() { router := garson.New() router.Before(middleware.Logger) router.After(someCustomMiddlewareOfYours) router.Get(&#34;/hello&#34;, hello) http.ListenAndServe(&#34;:3000&#34;, router) } </code></pre> <hr/>**评论:**<br/><br/>R2A2: <pre><p>Why not this?</p> <pre><code>func main() { router := garson.New() router.Get(&#34;/hello&#34;, anotherCustomMiddleware(hello)) http.ListenAndServe(&#34;:3000&#34;, someCustomMiddleware(middleware.Logger(router))) } </code></pre> <p>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.</p> <p>BTW I think you&#39;re totally on the right track with plain http.Handlers and with <code>func(http.Handler) http.Handler</code> - this makes your work more flexible than other routers &amp; middlewares (negroni/httprouter/etc etc), which use their own custom parameter specs. Not a criticism of their authors - they were working in a pre-<code>r.Context()</code> world, which forced their hands a little. Good for you.</p> <p>Edit: sorry I forgot to include an example which does middleware-type stuff before/after running the inner handler/router/middleware.</p> <p>See below:</p> <p><a href="https://github.com/laher/context-example/blob/master/main.go#L124" rel="nofollow">https://github.com/laher/context-example/blob/master/main.go#L124</a></p> <p>That repo is just some code samples I made for a meetup talk. See readme for more notes.</p> <p>Does that answer your question?</p></pre>emostafa: <pre><p>@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:</p> <pre><code> router.Get(&#34;/hello&#34;, anotherCustomMiddleware(hello)) </code></pre> <p>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 ?</p> <pre><code>router.Get(&#34;/hello&#34;, middleware1(middleware2(middleware3(hello)))) </code></pre> <p>my idea that it could look like this</p> <pre><code>router.Get(&#34;/hello&#34;, hello).Before(middleware1, middleware2, middleware3).After(middleware4) </code></pre> <p>of Use() of the whole concept of Before() and After() is wrong: router.Use(LoggerMiddleware) router.Get(&#34;/hello&#34;, hello).Use(middleware1, middleware2, middleware3, middleware4)</p> <p>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.</p></pre>R2A2: <pre><p>Here&#39;s a logging example (not storing but hopefully it illustrates the idea):</p> <pre><code>func anotherCustomMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println(&#34;start&#34;, time.Now(), r.Method, &#34;-&#34;, r.RequestURI) next.ServeHTTP(w, r) log.Println(&#34;finish&#34;, time.Now(), r.Method, &#34;-&#34;, r.RequestURI, w.Status) }) } </code></pre> <p>Sorry I don&#39;t really value the Before/After/Use thing that much. I think you&#39;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&#39;re getting more complex than that I&#39;d recommend nesting routers instead. I think Use() just adds an unnecessary layer. But, up to you.</p></pre>

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

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