Conditional Requests#
Conditional Requests#
There are built-in utilities for handling conditional requests, which serve two broad purposes:
- Sparing bandwidth on reading a document that has not changed, i.e. "only send if the version is different from what I already have".
- Preventing multiple writers from clobbering each other's changes, i.e. "only save if the version on the server matches what I saw last".
Adding support for handling conditional requests requires four steps:
- Import the
github.com/danielgtaylor/huma/v2/conditional
package. - (optional) Add the response definition (
304 Not Modified
for reads or412 Precondition Failed
for writes) - Add
conditional.Params
to your input struct. - Check if conditional params were passed and handle them. The
HasConditionalParams()
andPreconditionFailed(...)
methods can help with this.
Example#
Implementing a conditional read might look like:
huma.Register(api, huma.Operation{
OperationID: "get-resource",
Method: http.MethodGet,
Path: "/resource",
Summary: "Get a resource",
}, func(ctx context.Context, input struct {
conditional.Params
}) (*YourOutput, error) {
if input.HasConditionalParams() {
// TODO: Get the ETag and last modified time from the resource.
etag := ""
modified := time.Time{}
// If preconditions fail, abort the request processing. Response status
// codes are already set for you, but you can optionally provide a body.
// Returns an HTTP 304 not modified.
if err := input.PreconditionFailed(etag, modified); err != nil {
return err
}
// Otherwise do the normal request processing here...
// ...
}
})
Conditional Request Efficiency
Note that it is more efficient to construct custom DB queries to handle conditional requests, however Huma is not aware of your database. The built-in conditional utilities are designed to be generic and work with any data source, and are a quick and easy way to get started with conditional request handling.
Dive Deeper#
- Reference
conditional
packageconditional.Params
- External Links