Releases: danielgtaylor/huma
v2.10.0
Overview
Sponsors
Big shout out to our new sponsors. Thank you so much! ❤️
Better Support For Recursive Structs
Request/response bodies now have better support for recursive data structures, for example:
type Node struct {
Value string `json:"value"`
Left *Node `json:"left,omitempty"`
Right *Node `json:"right,omitempty"`
}
Multipart Form Support
You can now more easily access the incoming request's multipart form via the RawBody
field:
huma.Register(api, huma.Operation{
OperationID: "upload-files",
Method: http.MethodPost,
Path: "/upload",
Summary: "Example to upload a file",
}, func(ctx context.Context, input struct {
RawBody multipart.Form
}) (*struct{}, error) {
// Process multipart form here.
return nil, nil
})
https://huma.rocks/features/request-inputs/#multipart-form-data
Body Fields Can Be Hidden
You can now hide body fields just like you could e.g. query/header params.
type MyObject struct {
Public string `json:"public"`
Private string `json:"private" hidden:"true"`
}
This is useful if you want the field hidden from the docs but still serialized on the wire, so json:"-"
would be inappropriate.
Type Aliases
Besides huma.SchemaProvider
, you can now override schema generation behavior by registering known types with aliases, making it possible to override types used in structs from other packages.
registry := huma.NewMapRegistry("#/components/schemas", huma.DefaultSchemaNamer)
registry.RegisterTypeAlias(reflect.TypeFor[some_external_pkg.OptionalStr](), reflect.TypeFor[string]())
registry.RegisterTypeAlias(reflect.TypeFor[some_external_pkg.OptionalDateTime](), reflect.TypeFor[time.Time]())
What's Changed
- feat: breaks infinite cycle when looking for fields in recursive structures. by @yuridevx in #306
- Multipart Form RawBody Type Support by @jamelt in #324
- feat: hidden body field support by @bekabaz in #328
- fix: allow multipart with body; prevent double status by @danielgtaylor in #329
- Allow specifying type aliases to provide schema definitions by @lsdch in #330
New Contributors
- @yuridevx made their first contribution in #306
- @jamelt made their first contribution in #324
- @bekabaz made their first contribution in #328
- @lsdch made their first contribution in #330
Full Changelog: v2.9.0...v2.10.0
v2.9.0
Overview
String Length Validation
String length now counts the UTF8 runes in a string rather than using len(value)
, making for a more accurate count of the visible characters and being compatible with systems supporting unicode.
Add dependentRequired
Validation
You can now utilize JSON Schema's dependentRequired
validation which marks a field as required conditional on the presence of another field, for example:
type PaymentInfo struct {
Name string `json:"name" doc:"Billing name"`
Card int64 `json:"card,omitempty" doc:"Credit card number" dependentRequired:"address"`
Address string `json:"address,omitempty" doc:"Billing address"`
IBAN string `json:"iban,omitempty" doc:"Bank account ID for transfer"`
}
This requires a name
and then you can pass an iban
for a bank transfer or use a credit card. If the credit card is passed, then validation will fail unless an address is also passed.
Readonly Nested Structs
Nested structs can now utilize the readOnly
/ writeOnly
/ etc validation:
type Example struct {
Field struct {
Value string `json:"value"`
} `readOnly:"true"`
}
Better Pattern Errors
String pattern validation using regular expressions can now provide a user-friendly name so that the error says something like expected string to be alphabetical
instead of expected string to match pattern ^[a-zA-Z]+$
.
type Example struct {
Field string `json:"field" pattern:"^[a-zA-Z]+$" patternDescription:"alphabetical"`
}
Overriding Fields
A bug was fixed in the generated JSON Schema when overriding fields:
type One struct {
A string `json:"a"`
B string `json:"b"`
}
type Two struct {
One
B string `json:"-"`
}
This will result in a JSON Schema for Two
with only one field: a
.
What's Changed
- fix: length validation for utf8 strings by @maximdanilchenko in #298
- fix: issue 299 by @victoraugustolls in #304
- feat: dependent required tag by @victoraugustolls in #303
- chore(deps): bump google.golang.org/protobuf from 1.32.0 to 1.33.0 by @dependabot in #308
- chore(deps): bump google.golang.org/protobuf from 1.32.0 to 1.33.0 in /examples by @dependabot in #309
- fix: make dependent error deterministic by @danielgtaylor in #310
- feat: support dep required for map[any]any by @danielgtaylor in #312
- fix: authorizationUrl is only required for implicit/authcode by @danielgtaylor in #318
- doc: Add sponsor/funding info by @danielgtaylor in #319
- fix: skip param required check if SkipValidateParams is set by @danielgtaylor in #320
- Nested struct visibility by @CptKirk in #314
- feat(validation): flexible validation messages for pattern tag by @purin-dev in #323
New Contributors
- @maximdanilchenko made their first contribution in #298
- @victoraugustolls made their first contribution in #304
- @CptKirk made their first contribution in #314
- @purin-dev made their first contribution in #323
Full Changelog: v2.8.0...v2.9.0
v2.8.0
Overview
CLI Package
The CLI functionality has been moved into its own package humacli
. The existing huma.NewCLI
call continues to work but is marked as deprecated and will be removed in a future release. This will be a small breaking change in the future but is necessary to fix a design mistake that impacts dependencies that cannot otherwise be resolved. Migrating is an easy find/replace:
huma.NewCLI
→humacli.New
huma.CLI
→humacli.CLI
huma.Hooks
→humacli.Hooks
huma.WithOptions
→humacli.WithOptions
If you want to ensure your code doesn't include anything from the existing CLI and Cobra functionality, use the humanewclipackage
build tag, e.g. go build -tags humanewclipackage
. You won't save much space but this can help for package auditing.
Convenience Summary
Convenience functions like huma.Get
, huma.Put
, etc now generate a human-readable summary of the operation using the path. For example, huma.Get(api, "/things/{id}", ...)
would generate a summary of Get things by id
.
Easier Context Values
Router-agnostic middleware has gotten a bit easier to write with the new huma.WithValue
and huma.WithContext
functions to return a wrapped Huma context with its underlying request context.Context
replaced. Use it like:
func MyMiddleware(ctx huma.Context, next func(huma.Context)) {
// Wrap the context to add a value.
ctx = huma.WithValue(ctx, "some-key", "some-value")
// Call the next middleware in the chain. This eventually calls the
// operation handler as well.
next(ctx)
}
What's Changed
- docs: remove experimental flag for Go 1.22+ by @danielgtaylor in #282
- docs: fix broken link by @danielgtaylor in #283
- feat: add convenience functions for summary by @xarunoba in #284
- feat: add WithContext and WithValue for setting context values by @danielgtaylor in #295
- fix: move CLI to its own package, deprecate huma.NewCLI by @danielgtaylor in #291
New Contributors
Full Changelog: v2.7.0...v2.8.0
v2.7.0
New Features
Convenience Functions
Convenience functions are available for common HTTP verbs, e.g. huma.Get
, huma.Post
, huma.Put
, etc. These provide less control over the OpenAPI generation, but are significantly less verbose than huma.Register
and make it easier to get started, provide quick examples/demos, and more.
huma.Get(api, "/demo", func(ctx context.Context, input *Input) (*Output, error) {
// ...
})
The OpenAPI operationId
field is generated from the path. The behavior can be modified by overriding huma.GenerateOperationID
if desired. It's easy to switch to huma.Register
at any time if/when you want to provide more information for the OpenAPI generation.
Custom Input Params
You can now use any type that supports encoding.TextUnmarshaler
as an input param (path/query/header/cookie). Combined with custom field schemas this is very powerful, and it can use custom request resolvers as well enabling better support for exhaustive error responses to clients. For example, the Google UUID library supports TextUnmarshaler
:
import "github.com/google/uuid"
type UUID struct {
uuid.UUID
}
func (UUID) Schema(r huma.Registry) *huma.Schema {
return &huma.Schema{Type: huma.TypeString, Format: "uuid"}
}
huma.Get(api, "/demo", func(ctx context.Context, input *struct{
Example UUID `query:"example"`
}) (*Output, error) {
// Print out the UUID time portion
fmt.Println(input.Example.Time())
})
What's Changed
- fix: set CLI name from executable, add docs for name/version by @danielgtaylor in #265
- fix: Set body height to 100% of the viewport height by @mailbaoer in #271
- feat: support input param types using
TextUnmarshaler
by @danielgtaylor in #276 - fix: allow response types to contain unexported fields by @FlorianLoch in #278
- feat: add convenience methods by @danielgtaylor in #279
- fix: return wrapped errors on transform or write failure by @danielgtaylor in #280
New Contributors
- @mailbaoer made their first contribution in #271
- @FlorianLoch made their first contribution in #278
Full Changelog: v2.6.0...v2.7.0
v2.6.0
What's Changed
- chore(deps): bump github.com/gofiber/fiber/v2 from 2.52.0 to 2.52.1 by @dependabot in #261
- feat: better support for cookies by @danielgtaylor in #258
Full Changelog: v2.5.0...v2.6.0
v2.5.0
What's Changed
- fix: resolver should never be invoked twice by @danielgtaylor in #235
- docs: adds echo router to BYOR page by @certanet in #239
- fix: allow example/enum tags for custom schemas by @danielgtaylor in #242
- docs: README updates & RFC 9457 errors by @danielgtaylor in #244
- feat: support time.Duration options by @danielgtaylor in #245
- fix: do not generate json response for binary outputs by @danielgtaylor in #247
- docs: add doc about middleware errors by @danielgtaylor in #248
- docs: improve docs for unstructured request bodies by @danielgtaylor in #251
- change elements try it credentials policy to same-origin by @paivagustavo in #254
- feat: better control over object additionalProperties by @danielgtaylor in #256
New Contributors
- @certanet made their first contribution in #239
- @paivagustavo made their first contribution in #254
Full Changelog: v2.4.0...v2.5.0
v2.4.0
What's Changed
- Check if err in index exists before adding to details array by @austincollinpena in #222
- feat: significantly reduce dependencies by @danielgtaylor in #223
- Errors in OAuth2 how to examples by @x-user in #225
- chore(deps): bump github.com/graphql-go/graphql from 0.8.0 to 0.8.1 in /examples by @dependabot in #226
New Contributors
- @austincollinpena made their first contribution in #222
Full Changelog: v2.3.0...v2.4.0
v2.3.0
What's Changed
- minor: fix(docs): use right name for writer var by @costela in #201
- feat: experimental Go 1.22 ServeMux support by @danielgtaylor in #203
- docs: Add OAuth 2.0 & JWT how-to by @danielgtaylor in #204
- fix: avoid sending referrer header to unpkg by @costela in #208
- proposal: switch to versioned spotlight and add integrity check by @costela in #209
- fix: SSE oneOf schema contained null entries by @danielgtaylor in #211
- feat: add echo framework adapter by @x-user in #212
- fix: add crossorigin config for sha integrity check by @danielgtaylor in #216
- log accurate error message when there's duplicate registry name by @qdongxu in #217
- feat: make multipart form max memory configurable by @danielgtaylor in #218
New Contributors
Full Changelog: v2.2.0...v2.3.0
v2.2.0
What's Changed
- chore(deps): bump golang.org/x/crypto from 0.14.0 to 0.17.0 by @dependabot in #187
- docs: improved docs; auto light/dark mode by @danielgtaylor in #188
- Support array query parameters of primitives other than string by @ross96D in #192
- chore: trigger CI on pulls and push-on-main by @danielgtaylor in #193
- fix: integer conversion CVE, improved coverage a bit by @danielgtaylor in #194
- fix: schema naming for generics + package types by @danielgtaylor in #195
- fix: better validation of manual schemas by @danielgtaylor in #196
- fix: enhanced generic schema naming by @danielgtaylor in #200
- fix ref name contains recursive brackets '[]' by @qdongxu in #199
New Contributors
Full Changelog: v2.1.0...v2.2.0
v2.1.0
What's Changed
- Add bunrouter adapter by @thesoulless in #183
- fix: document bunrouter support; remove incorrect benchmark by @danielgtaylor in #184
New Contributors
- @thesoulless made their first contribution in #183
Full Changelog: v2.0.1...v2.1.0