为了账号安全,请及时绑定邮箱和手机立即绑定

Go httprouter 自定义中间件

Go httprouter 自定义中间件

Go
犯罪嫌疑人X 2022-04-25 17:21:02
作为一名 Go 程序员,我相对较新,我正在尝试为我的服务器构建一个自定义中间件。问题是它的行为不像我预期的那样。有人可以解释为什么我的上下文没有设置为ME吗?package mainimport (    "context"    "log"    "net/http"    "github.com/julienschmidt/httprouter")func main() {    router := httprouter.New()    router.GET("/test", middlewareChain(contentType, name))    log.Print("App running on 8080")    log.Fatal(http.ListenAndServe(":8080", router))}func middlewareChain(h ...httprouter.Handle) httprouter.Handle {    return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {        r = r.WithContext(context.WithValue(r.Context(), "test", "You"))        log.Print("Set context to YOU")        for _, handler := range h {            handler(w, r, p)        }    }}func contentType(w http.ResponseWriter, r *http.Request, p httprouter.Params) {    r = r.WithContext(context.WithValue(r.Context(), "test", "Me"))    log.Print("Set context to ME")    header := w.Header()    header.Set("Content-type", "application/json")}func name(w http.ResponseWriter, r *http.Request, p httprouter.Params) {    log.Printf("Context: %s", r.Context().Value("test"))}
查看完整描述

1 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

如果中间件与下一个相关联,我发现它们最有用。堆栈中稍后的中间件可以依赖先前设置的值,因此它们是顺序相关的。有时,他们可以决定在某种条件下停止堆栈。


像这样把它们锁起来怎么样?


func main() {

    router := httprouter.New()

    router.GET("/test", setTestYou(contentType(name)))

    log.Print("App running on 8080")

    log.Fatal(http.ListenAndServe(":8080", router))

}


func setTestYou(next httprouter.Handle) httprouter.Handle {

    return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {

        r = r.WithContext(context.WithValue(r.Context(), "test", "You"))

        log.Print("Set context to YOU")


        if next != nil {

            next(w, r, p)

        }

    }

}


func contentType(next httprouter.Handle) httprouter.Handle {

    return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {

        if r.Header.Get("Content-type") != "application/json" {

            // break here instead of continuing the chain

            w.Status = 400

            return

        }


        r = r.WithContext(context.WithValue(r.Context(), "test", "Me"))

        log.Print("Set context to ME")

        header := w.Header()

        header.Set("Content-type", "application/json")


        if next != nil {

            next(w, r, p)

        }

    }

}


func name(w http.ResponseWriter, r *http.Request, p httprouter.Params) {

    log.Printf("Context: %s", r.Context().Value("test"))

}

由于他们将请求/上下文传递到下一个,因此更改将保持不变。


查看完整回答
反对 回复 2022-04-25
  • 1 回答
  • 0 关注
  • 137 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信