danielgtaylor / huma

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

Error handling with Server Sent Events #206

Closed JanRuettinger closed 8 months ago

JanRuettinger commented 8 months ago

It is not clear to me how to indicate errors to the client when dealing with server sent events.

According to the documentation, you can only define what data to send but the status code will always be 200.

How can we indicate the client receiving the events that something went wrong? Maybe an additional function called send.Error(msg, statusCode)?

For example something like this:

// Register using sse.Register instead of huma.Register
sse.Register(api, huma.Operation{
    OperationID: "sse",
    Method:      http.MethodGet,
    Path:        "/sse",
    Summary:     "Server sent events example",
}, map[string]any{
    // Mapping of event type name to Go struct for that event.
    "message":      DefaultMessage{},
    "userCreate":   UserCreatedEvent{},
    "mailRecieved": MailReceivedEvent{},
}, func(ctx context.Context, input *struct{}, send sse.Sender) {
    // Send an event every second for 10 seconds.

       // if db connection failed
      send.Error("db connection failed", 500)
})
danielgtaylor commented 8 months ago

@JanRuettinger what would your send.Error(msg, statusCode) func do? The problem I see is that by the time your handler is called the success status code and text/event-stream content type have already been sent to the client, and potentially some messages too.

For errors during the processing of messages that may occur anytime, a custom error message that is sent in the SSE stream might be the way to go, and clients would need to handle that message type as an error. You could map an event named error to MyCustomError type (or re-use the Huma RFC7807 error model that's built-in).

For errors before you send any messages (i.e. setup code) you may need to drop down and use huma.StreamResponse directly instead of the sse convenience package. The package really isn't doing a ton, see https://github.com/danielgtaylor/huma/blob/main/sse/sse.go#L113-L118.