doulvyi2172 2017-11-07 06:11
浏览 201
已采纳

httprouter传递了许多中间件功能

I'm coming from node express, and I was able to pass in as many middleware as possible, for example: routes.use('/*', ensureAuth, logImportant, ... n);

How can I do something similar when using r.GET("/", HomeIndex)?

Am I forced to do something like EnsureAuth(HomeIndex)? Because I can get that to work. Unfortunately, I'm not sure what would be a good way to add as many middlewares as I want without chaining functions together.

Is there a more elegant way so I could somehow use variadic type function to do r.GET("/", applyMiddleware(HomeIndex, m1, m2, m3, m4)? I'm trying that out right now, but I feel like there's a better way to do this.

I've looked at the httprouter issues page, can't find anything :(

Thanks!

  • 写回答

1条回答 默认 最新

  • dongyou5068 2017-11-07 07:20
    关注

    Here is an example how I did it:

    package main
    
    import (
        "context"
        "fmt"
        "log"
        "net/http"
    
        "github.com/julienschmidt/httprouter"
        "github.com/justinas/alice"
    )
    
    // m1 is middleware 1
    func m1(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            //do something with m1
            log.Println("m1 start here")
            next.ServeHTTP(w, r)
            log.Println("m1 end here")
        })
    }
    
    // m2 is middleware 2
    func m2(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            //do something with m2
            log.Println("m2 start here")
            next.ServeHTTP(w, r)
            log.Println("m2 end here")
        })
    }
    
    func index(w http.ResponseWriter, r *http.Request) {
        // get httprouter.Params from request context
        ps := r.Context().Value("params").(httprouter.Params)
        fmt.Fprintf(w, "Hello, %s", ps.ByName("name"))
    }
    
    // wrapper wraps http.Handler and returns httprouter.Handle
    func wrapper(next http.Handler) httprouter.Handle {
        return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
            //pass httprouter.Params to request context
            ctx := context.WithValue(r.Context(), "params", ps)
            //call next middleware with new context
            next.ServeHTTP(w, r.WithContext(ctx))
        }
    }
    
    func main() {
        router := httprouter.New()
    
        chain := alice.New(m1, m2)
    
        //need to wrap http.Handler to be compatible with httprouter.Handle
        router.GET("/user/:name", wrapper(chain.ThenFunc(index)))
    
        log.Fatal(http.ListenAndServe(":9000", router))
    }
    

    Link to code (you can't run it from play.golang.org though): https://play.golang.org/p/BOCt97xcoY

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)