danielgtaylor / huma

Huma REST/HTTP API Framework for Golang with OpenAPI 3.1
https://huma.rocks/
MIT License
1.89k stars 138 forks source link

Forwarding headers through the middleware not working #398

Open spa5k opened 4 months ago

spa5k commented 4 months ago

So I have a small middleware that reads the cookie and writes a "User-Id" header through the context, but when I try to read the same header in the handler or in the next middleware, it remains empty

func UserAuthenticationMiddleware(tokenService *token.Manager) func(ctx huma.Context, next func(huma.Context)) {
    return func(ctx huma.Context, next func(huma.Context)) {
        tokenCookie, err := huma.ReadCookie(ctx, "review_hq_token")
        ...
        userId, err := tokenService.VerifyToken(tokenCookie.Value)
        if err != nil {
            ctx.SetStatus(401)
            ctx.BodyWriter().Write([]byte(err.Error()))
            return
        }

        ctx.SetHeader("User-Id", userId)

        ctx = huma.WithValue(ctx, "User-Id", userId)

        next(ctx)
    }
}
huma.Register(api, huma.Operation{
        Path:        path,
        Method:      "POST",
        Tags:        []string{"Review"},
        OperationID: "create-review",
        Middlewares: huma.Middlewares{
            middleware.UserAuthenticationMiddleware(tokenService),
            func(ctx huma.Context, next func(huma.Context)) {
                // This is empty
                println("userid from middleware", ctx.Header("User-Id"))
            },
        },
    }, func(ctx context.Context, i *CreateReviewRequest) (*createReviewResponse, error) {
        // first is empty, second works
        println("reviewUserID", i.UserId)
        println("reviewUserID", ctx.Value("User-Id").(string))

Passing values through context is working as expected.

x-user commented 4 months ago

It's because huma.Context.Header reads request headers, but huma.Context.SetHeader sets response headers.

spa5k commented 4 months ago

So this set header is only for response? I can't update the headers of the request when it reaches Middleware?

x-user commented 4 months ago

Yes. At least for now you can only do this in router own middleware.

danielgtaylor commented 4 months ago

@spa5k if you must override headers in router-agnostic middleware, you can create your own struct which wraps huma.Context and override yourStruct.Header(name string) string to return the values you want. Otherwise, like @x-user says you can do this in the underlying router's own middlewares.

spa5k commented 4 months ago

imo, it should forward the headers naturally, how do other framework/languages handle it?