-
-
Couldn't load subscription status.
- Fork 229
Description
Motivation
There is a pattern I often want to do that I find difficult with Huma. Specifically, I want to extract an error message / description to be logged from middleware (huma or router). Currently there is no easy way to do this and not easy place in Huma to tie in to add this. After reviewing the problem I believe it makes the most sense to add to the framework itself.
The only workaround I have now, is to duplicate the entire request body, attempt to parse the Huma error out of it, then get the error message from that. This is a problem due to the memory overhead, also I don't care about the message in cases where the request is successful.
Example
When I return an error from a Huma handler, Its very difficult to retrieve, both from huma middleware as well as the router middleware. This is an example of what I would like to be able to do.
package main
import (
"context"
"fmt"
"net/http"
"github.com/danielgtaylor/huma/v2"
"github.com/danielgtaylor/huma/v2/adapters/humachi"
"github.com/go-chi/chi/v5"
)
// GreetingOutput represents the greeting operation response.
type GreetingOutput struct {
Body struct {
Message string `json:"message" example:"Hello, world!" doc:"Greeting message"`
}
}
// Middleware wants to print the error message
func MyMiddleware(ctx huma.Context, next func(huma.Context)) {
// Call the next middleware in the chain. This eventually calls the
// operation handler as well.
next(ctx)
if ctx.Status() == 500 {
fmt.Printf("error was: %s", ctx.ErrorMessage()) // Want to print "error was: don't say hello to ben)
}
}
func main() {
// Create a new router & API.
router := chi.NewMux()
api := humachi.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) {
if input.Name == "ben" {
// throw an error
reutrn nil, huma.Error500InternalServerError("don't say hello to ben")
}
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)
}