作为一名Go程序员,我相对较新,并且正在尝试为服务器构建自定义的中间件。问题在于它的行为不像我预期的那样。有人可以解释为什么我的上下文未设置为 ME 吗?
package main
import (
"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"))
}
答案 0 :(得分:1)
我发现如果中间件链接到下一个中间件,那么中间件最有用。堆栈中后面的中间件可以依赖于先前的中间件设置的值,因此它们是顺序相关的。有时,他们可以决定在某种情况下停止堆栈。
如何像这样将它们链接起来?
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"))
}
由于他们将请求/上下文传递到下一个请求,因此更改将保留。