Overview
This release adds native support for stdlib UUIDs, cuts compile times for large APIs, and brings a big batch of correctness fixes across request limits, defaults, validation, and the Fiber adapter. It also raises the minimum Go version to 1.26 and includes a few intentional breaking changes, so please read the upgrade notes below.
Upgrade Notes
- Minimum Go version is now 1.26. Dependencies have been bumped too, picking up a few vulnerability fixes (#1149)
- Raw bodies now have default limits. Non-multipart
RawBodyoperations (e.g.[]byteuploads) now get the same default 1 MiBMaxBodyBytesand 5sBodyReadTimeoutas regular bodies. Endpoints accepting larger or slower raw uploads should set these explicitly (-1for unlimited) (#1095) - Multipart now honors
MaxBodyBytes. An explicitly setMaxBodyBytesis now enforced on multipart requests. Multipart remains exempt from the defaults, so existing uploads keep working unless you've set a limit (#1094) - Overflowing
defaulttags panic at startup. For example,int8withdefault:"128"previously wrapped silently to-128; it now fails at registration (#1142) - Out-of-range bound tags panic at startup. For example,
int8withmaximum:"500".int8,int16,uint8anduint16fields also now advertiseminimum/maximumfrom their Go type, so generated specs will change (#1143)
Security Fix
A malformed Accept header such as application/json;,b caused a panic during content negotiation. On net/http-based adapters this dropped the request; on Fiber, which doesn't recover handler panics unless the recover middleware is used, it crashed the server process. This affects v2.26.0 onwards, so upgrading is recommended. (#1128)
Native Stdlib UUIDs
On Go 1.27+, fields using the new standard library uuid.UUID type are automatically documented as type: string with format: uuid, with no struct tag needed. (#1051)
Faster Compile Times
huma.Register, sse.Register and the convenience helpers (huma.Get, huma.Post, ...) now keep their generic parts tiny, so Go no longer compiles a full copy of the registration logic for every input/output pair. In a 200-operation benchmark package, build time dropped from 3.38s to 0.64s. There are no API or runtime changes. (#1115, #1117)
New Features
- String SSE event IDs via
sse.Message.IDString, for UUIDs, cursor tokens and other opaque IDs (#1086) Schemacan be unmarshalled from JSON, including$ref,x-extensions and nullable types, and is ready forValidateonce decoded (#1144)
Validation & Defaults Fixes
{"type": "null"}is now validated. Previously it accepted any value, so ananyOfwith a null branch skipped the constraints of its other branches (#1120)- Numeric request parameters which overflow the destination Go type (e.g.
300into anint8) now return422instead of silently wrapping (#1096) defaulttags onencoding.TextUnmarshalertypes (e.g. a duration withdefault:"10s") are now applied viaUnmarshalTextinstead of panicking (#1126)- Defaults are now applied to absent exploded query arrays (#1116) and missing multipart form values (#1150), and array parameters accept JSON array defaults such as
default:"[\"a\",\"b\"]"(#1125) - Value-less query flags followed by other parameters (e.g.
?flag&foo=bar) are now detected correctly (#1097) PathBuffer.Poprestores the exact offset, fixing wrong error locations after discriminator errors (#1136)casing.Camelandcasing.Joinno longer panic or double-apply transforms when a transform removes a part (#1113)
Request Body Fixes
- A body of exactly
MaxBodyBytesis now accepted instead of returning413(#1131) - Multipart file handles are now closed after mime-type validation (#1085)
OpenAPI Fixes
RawBodyalongsideBodyno longer documents an extraapplication/octet-streammedia type (#1134)- The
exampletag on aBodyfield is now set as the media type example, since many tools ignore examples next to a$ref(#1101)
Adapter & Autopatch Fixes
- humafiber: multiple
Set-Cookieheaders are now sent as separate header lines instead of being comma-joined (#1137) - humafiber (v2): autopatch now works, as its internal requests get a default
Host(#1140) - autopatch: PATCH responses are no longer compressed twice (#1130), and
$refs are resolved when making the PUT schema optional (#1080)
Docs UI & Documentation
- Updated Scalar (1.76.0), Stoplight Elements (9.0.29) and SwaggerUI (5.34.0). Scalar no longer needs
'unsafe-eval'in its CSP, and its fonts now load (#1145) - Clarified that router-agnostic middleware runs after route resolution (#1088)
- Documented that humafiber doesn't decode streamed request bodies (#1118)
- Added SwaggerUI
persistAuthorizationto theDocsRendererConfigexample (#1122)
What's Changed
- fix(queryparam): correctly detect flag/bool value which is followed by a non-flag by @leonklingele in #1097
- docs: replace Zuplo sponsorship with SerpApi by @danielgtaylor in #1106
- feat: native support for stdlib UUIDs introduced in Go 1.27 by @leonklingele in #1051
- perf: keep Register's generic part small to cut compile time by @iyuneev in #1115
- fix(casing): stop transforming an index after its part is removed by @youdie006 in #1113
- perf: keep sse.Register and convenience generic parts small by @robtme in #1117
- fix: apply defaults to absent exploded query arrays by @Arvin-Lee in #1116
- docs(humafiber): note streamed request bodies are not decoded by @robtme in #1118
- docs: show SwaggerUI persistAuthorization in DocsRendererConfig example by @ize-302 in #1122
- fix: validate the null type by @jahirulislam-forgent in #1120
- fix: accept request bodies of exactly MaxBodyBytes by @APX403 in #1131
- fix: Allow autopatch to resolve refs, when making the put schema optional by @lucaspopp-wbd in #1080
- fix: don't document application/octet-stream for RawBody alongside Body by @HawkForge in #1134
- fix: restore the exact offset in PathBuffer.Pop by @vyrnsynx in #1136
- fix: apply default tags via TextUnmarshaler by @vulragrag-star in #1126
- fix: reject numeric request parameters which overflow the destination Go type by @leonklingele in #1096
- fix: reject overflowing default tags at registration by @robtme in #1142
- fix: advertise small int bounds and reject out-of-range bound tags by @robtme in #1143
- feat: support unmarshalling JSON into Schema by @robtme in #1144
- chore: update docs renderers to latest versions by @robtme in #1145
- fix(negotiation): don't panic on empty q param in SelectQValueFast by @dannyshafer in #1128
- fix: close multipart file handles after mime-type validation by @stareezy-1 in #1085
- fix: surface Body example tag as the media type example by @SillyZir in #1101
- feat: support string SSE event IDs by @stareezy-1 in #1086
- fix(autopatch): prevent double compression of PATCH responses by @Arvin-Lee in #1130
- fix: accept JSON array defaults on array parameters by @youdie006 in #1125
- chore: bump dependencies and minimum Go to 1.26 by @robtme in #1149
- fix(humafiber): default the Host so autopatch works on Fiber v2 by @APX403 in #1140
- fix(humafiber): keep multiple Set-Cookie headers separate by @APX403 in #1137
- fix(multipart): respect MaxBodyBytes limit by @leonklingele in #1094
- fix: respect MaxBodyBytes limit for raw bodies by @leonklingele in #1095
- docs: clarify router-agnostic middleware runs after route resolution by @stareezy-1 in #1088
- fix: apply the default tag to missing multipart form values by @youdie006 in #1150
New Contributors
- @iyuneev made their first contribution in #1115
- @youdie006 made their first contribution in #1113
- @Arvin-Lee made their first contribution in #1116
- @ize-302 made their first contribution in #1122
- @jahirulislam-forgent made their first contribution in #1120
- @APX403 made their first contribution in #1131
- @HawkForge made their first contribution in #1134
- @vyrnsynx made their first contribution in #1136
- @vulragrag-star made their first contribution in #1126
- @dannyshafer made their first contribution in #1128
- @stareezy-1 made their first contribution in #1085
- @SillyZir made their first contribution in #1101
Full Changelog: v2.39.1...v2.40.0