Home > OS >  How to propagate value from child middleware to parent?
How to propagate value from child middleware to parent?

Time:05-29

I am trying to customize request pipeline through middleware pattern, the code as follow:

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)
    }

}

and the output is :

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

According to the output, the value could pass from parent to the child , while, if the child add something to the context, it is invisible to the parent

How can I propagate value from child middleware to parent?

CodePudding user response:

What you're doing is creating a new pointer to the modified http.Request via WithContext method. So if you're passing it to next middleware in the chain everything works as expected since you're passing this new pointer as an argument. If you want to modify the request and make it visible for those who hold the pointer to it, you need to dereference the pointer and set the modified value.

So in your 'child' middleware instead of:

r = r.WithContext(ctx)

Just do the following:

*r = *r.WithContext(ctx)
  •  Tags:  
  • go
  • Related