在我的日志记录中间件(链中的第一个)中,我需要访问一些上下文,这些上下文是在链下的某些 auth 中间件中编写的,并且仅在执行处理程序本身之后。
旁注:需要首先调用日志记录中间件,因为我需要记录请求的持续时间,包括在中间件中花费的时间。此外,当权限不足时,auth 中间件能够中止请求。在那种情况下,我还需要记录失败的请求。
我的问题是从指针读取上下文http.Request不会返回我期望它具有的身份验证数据。请参阅下面的示例:
package main
import (
"context"
"fmt"
"net/http"
"time"
)
const (
contextKeyUsername = "username"
)
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ctx = context.WithValue(ctx, contextKeyUsername, "user123")
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func logMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func(start time.Time) {
ctx := r.Context()
username := ctx.Value(contextKeyUsername)
if username != nil {
fmt.Printf("user %s has accessed %s, took %d\n", username,
r.URL.Path, time.Since(start).Milliseconds())
} else {
fmt.Printf("annonyous has accessed %s, took %d\n",
r.URL.Path, time.Since(start).Milliseconds())
}
}(time.Now())
next.ServeHTTP(w, r)
})
}
func welcome(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
username := ctx.Value(contextKeyUsername)
if username != nil {
fmt.Fprintf(w, fmt.Sprintf("hello %s", username.(string)))
} else {
fmt.Fprintf(w, "hello")
}
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/welcome", welcome)
chain := logMiddleware(authMiddleware(mux))
http.ListenAndServe(":5050", chain)
}
虽然 get 请求127.0.0.1:5050/welcome确实返回了预期的字符串hello user123,但日志的输出是:
annonyous has accessed /welcome, took 0
由于请求是作为指针传递的,我预计在执行延迟时,上下文将包含预期username值。
我在这里错过了什么?
慕尼黑8549860
相关分类