【问题标题】:How to propagate value from child middleware to parent?如何将值从子中间件传播到父中间件?
【发布时间】:2023-02-19 07:45:10
【问题描述】:

我正在尝试通过中间件模式自定义请求管道,代码如下:

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Hello, middleware!")
}
func middleware1(next http.HandlerFunc) func(w http.ResponseWriter, r *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("[START] middleware1")
        ctx := r.Context()
        ctx = context.WithValue(ctx, middleware1Key, middleware1Value)
        r = r.WithContext(ctx)
        next(w, r)
        fmt.Println("[END] middleware1")
        ctx = r.Context()
        if val, ok := ctx.Value(middleware2Key).(string); ok {
            fmt.Printf("Value from middleware2 %s \n", val)
        }

    }
}
func middleware2(next http.HandlerFunc) func(w http.ResponseWriter, r *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("[START] middleware2")
        ctx := r.Context()
        if val, ok := ctx.Value(middleware1Key).(string); ok {
            fmt.Printf("Value from middleware1 %s \n", val)
        }
        ctx = context.WithValue(ctx, middleware2Key, middleware2Value)
        r = r.WithContext(ctx)
        next(w, r)
        fmt.Println("[END] middleware2")

    }
}
func main() {
    mux := http.NewServeMux()
    middlewares := newMws(middleware1, middleware2)
    mux.HandleFunc("/hello", middlewares.then(helloHandler))
    if err := http.ListenAndServe(":8080", mux); err != nil {
        panic(err)
    }

}

输出是:

[START] middleware1
[START] middleware2
Value from middleware1 middleware1Value
Hello, middleware!
[END] middleware2
[END] middleware1

根据输出,值可以从 parent 传递给 child ,而如果 child 添加一些东西到 context ,它对 parent 是不可见的

如何将价值从子中间件传播到父中间件?

【问题讨论】:

    标签: go


    【解决方案1】:

    您正在做的是通过 WithContext 方法创建一个指向修改后的 http.Request 的新指针。因此,如果您将它传递给链中的下一个中间件,一切都会按预期工作,因为您将这个新指针作为参数传递。 如果要修改请求并使其对持有指向它的指针的人可见,则需要取消引用指针并设置修改后的值。

    所以在你的“孩子”中间件而不是:

    r = r.WithContext(ctx)
    

    只需执行以下操作:

    *r = *r.WithContext(ctx)
    

    理解 Go 中的指针的好练习,但你不应该在你的生产代码中做类似的操作。文档对此很清楚。见https://pkg.go.dev/net/http#Handler

    【讨论】:

    猜你喜欢
    • 2018-06-17
    • 2015-03-28
    • 1970-01-01
    • 2021-07-19
    • 2018-08-20
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    相关资源
    最近更新 更多