Response Transformers#
Response Transformers#
Router middleware operates on router-specific request & response objects whose bodies are []byte
slices or streams. Huma operations operate on specific struct instances. Sometimes there is a need to generically operate on structured response data after the operation handler has run but before the response is serialized to bytes. This is where response transformers come in.
flowchart LR
Request --> Middleware
Middleware --> Unmarshal
subgraph Huma
Unmarshal --> Handler
Handler --> Transformer
Transformer --> Marshal
end
Marshal --> Response
style Transformer stroke:#f9f,stroke-width:2px,stroke-dasharray: 5 5
Response transformers enable you to modify the response on the fly. For example, you could add a Link
header to the response to indicate that the response body is described by a JSON Schema. This is done by implementing the huma.Transformer
interface and registering it with the API.
A simple for-fun example might look something like this:
// FieldSelectTransform is an example of a transform that can use an input
// header value to modify the response on the server, providing a GraphQL-like
// way to send only the fields that the client wants over the wire.
func FieldSelectTransform(ctx Context, status string, v any) (any, error) {
if fields := ctx.Header("Fields"); fields != "" {
// Ugh this is inefficient... consider other ways of doing this :-(
var tmp any
b, _ := json.Marshal(v)
json.Unmarshal(b, &tmp)
result, _, err := shorthand.GetPath(fields, tmp, shorthand.GetOptions{})
return result, err
}
return v, nil
}
This could be used like so:
See the huma.SchemaLinkTransformer
for a more real-world in-depth example.
Dive Deeper#
- Reference
huma.Transformer
response transformershuma.Config
the API config