-
-
Notifications
You must be signed in to change notification settings - Fork 233
Description
Hi - and thanks for this amazing project!
I am working my way through the docs and noticed that this example
https://huma.rocks/features/middleware/#router-agnostic
Implemented in a minimal example using the greetings tutorial code (with Chi replaced by the standard library router) does not actually set a response header:
package main
import (
"context"
"fmt"
"net/http"
"github.com/danielgtaylor/huma/v2"
"github.com/danielgtaylor/huma/v2/adapters/humago"
)
// GreetingOutput represents the greeting operation response.
type GreetingOutput struct {
Body struct {
Message string `json:"message" example:"Hello, world!" doc:"Greeting message"`
}
}
func MyMiddleware(ctx huma.Context, next func(huma.Context)) {
next(ctx)
ctx.SetHeader("My-Custom-Header", "Hello, world!")
}
func main() {
// Create a new router & API.
router := http.NewServeMux()
api := humago.New(router, huma.DefaultConfig("My API", "1.0.0"))
api.UseMiddleware(MyMiddleware)
// Register GET /greeting/{name} handler.
huma.Get(api, "/greeting/{name}", func(ctx context.Context, input *struct {
Name string `path:"name" maxLength:"30" example:"world" doc:"Name to greet"`
}) (*GreetingOutput, error) {
resp := &GreetingOutput{}
resp.Body.Message = fmt.Sprintf("Hello, %s!", input.Name)
return resp, nil
})
// Start the server!
http.ListenAndServe("127.0.0.1:8888", router)
}curl http://localhost:8888/greeting/world -v 2>&1 | grep "My-Custom-Header"
[ blank ]However, when I moveSetHeader before calling next() it appears to work as intended:
func MyMiddleware(ctx huma.Context, next func(huma.Context)) {
ctx.SetHeader("My-Custom-Header", "Hello, world!")
next(ctx)
}curl http://localhost:8888/greeting/world -v 2>&1 | grep "My-Custom-Header"
< My-Custom-Header: Hello, world!However that seems to defeat the purpose of the example.. I am not sure if this is the intended behavior or the docs are incorrect?
It appears this functionality is meant to mimic FastAPI/Starlette middleware such as this one where response = await call_next(request) continues the request and the header data is set after the other middlewares and route handler have returned.