http中间件中的Go和指针

Go and Pointers in http middleware

我试图在我的网络服务器上记录一些数据,所以我创建了一个 loggingMiddleware 服务于下一个请求,然后记录数据,我想这样我会在里面有所有必要的数据r *http.Request 指针

return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // call next handler
        next.ServeHTTP(o, r)

        // get requestID
        reqID := middleware.GetReqID(r.Context())

        log.WithFields(
            log.Fields{
                "request_id":     reqID,           // drops requestID
                "method":         r.Method,        // http method
                "remote_address": r.RemoteAddr,    // remote address
                "url":            r.URL.String(),  // url used by the client to access the service
                "referer":        r.Referer(),     // Referer header if present
                "user_agent":     r.UserAgent(),   // User-Agent header
                "content_length": r.ContentLength, // Content-Length header if present"
            },
        ).Info()
    })

然而,对于 RequestID,只有在 RequestID 中间件安装在 loggingMiddleware

之前,这才是正确的

不工作

...
    // get a new chi rotuter
    router = chi.NewRouter()

    // MIDDLEWARES

    // log
    // use logrus to log requests
    router.Use(LoggingMiddleware)

    // requestID
    // Generate a unique id for every request
    // ids are grouped based on client hostname
    router.Use(middleware.RequestID)
...

工作

...
    // get a new chi rotuter
    router = chi.NewRouter()

    // MIDDLEWARES

    // requestID
    // Generate a unique id for every request
    // ids are grouped based on client hostname
    router.Use(middleware.RequestID)

    // log
    // use logrus to log requests
    router.Use(LoggingMiddleware)
...

这是预期的行为吗? r *http.Request 指针是否应该指向请求的“更新”版本?有办法解决这个问题吗? 因为如果我想要,例如,从 JWT 令牌中提取用户名并将其放入 r.Context() 以便我稍后可以记录它,这将需要在 loggingMiddleware 之前安装一个单独的中间件。

抱歉我的英语不好,有什么不清楚的请问。

谢谢

middleware.RequestID 使用 http.Request.WithContext:

将请求 ID 添加到请求上下文中
ctx = context.WithValue(ctx, RequestIDKey, requestID)
next.ServeHTTP(w, r.WithContext(ctx))

根据文档:

WithContext returns a shallow copy of r with its context changed to ctx. The provided ctx must be non-nil.

因此,因为它是“returns r 的浅拷贝”,并且它是(指向)它传递给 next.ServeHTTP 的浅拷贝,如果 middleware.RequestID 是第二个挂载,然后 LoggingMiddleware 中的 r 指向与包含修改后的上下文的 *http.Request 不同的 *http.Request,因此其上下文将不包含请求 ID。另一方面,如果先挂载 middleware.RequestID,则 LoggingMiddleware 将收到指向 r.WithContext 返回的浅表副本的指针,一切都会按预期工作。