Huma
repository·main·Indexed 26 days ago
https://github.com/danielgtaylor/humaA modern, fast, and flexible micro framework for building HTTP REST/RPC APIs in Go. Backed by OpenAPI 3.1 and JSON Schema, Huma provides automatic documentation, request validation, and high-quality developer tooling. It supports multiple router adapters (such as Chi, Gin, Fiber, and the Go standard library) and includes built-in documentation renderers like Scalar, Stoplight Elements, and SwaggerUI.
What's inside Huma
- Huma is a modern, simple, fast, and flexible micro framework for building HTTP REST/RPC APIs in Golang. It is backed by OpenAPI 3 and JSON Schema, ensuring that your API documentation and validation are always in sync with your implementation.
Overview of Huma features
mainHuma is a micro framework for building HTTP REST/RPC APIs in Go, designed to be backed by OpenAPI 3.1 and JSON Schema. It is built to allow incremental adoption by letting you bring your own router, middleware, and logging/metrics.
Key capabilities include:
- Declarative API Definition: Define operations, models, request parameters (path, query, header), request bodies, responses (including errors), and response headers.
- Automatic Documentation: Generates OpenAPI specifications and JSON Schemas from annotated Go types, ensuring documentation stays in sync with code.
- Validation & Typing: Provides static typing for parameters and automatic input model validation with error handling.
- Content Negotiation: Supports JSON (RFC 8259) and optional CBOR (RFC 7049) via the
Acceptheader. - Standardized Errors: Uses RFC 9457 JSON Errors (
application/problem+json) by default. - Advanced HTTP Support: Includes conditional request utilities (e.g.,
If-Match) and per-operation request size limits.
Overview of Huma features and capabilities
mainHuma is a production-ready Go micro-framework designed to accelerate API development with fewer bugs. Key features include:
- Standards-Based: Built on OpenAPI and JSON Schema for automatic documentation and tool compatibility.
- Extensibility: Supports both router-specific and router-agnostic middleware, custom request validation via resolvers, and customizable OpenAPI/JSON Schema generation.
- Guardrails: Provides strongly-typed models with compile-time checks, automatic input validation, and automatic response serialization based on content-negotiation.
- Automation: Enables automatic generation of CLI tools and SDKs from your API definitions.
Core Goals of Huma
mainHuma is designed with the following objectives:
- Modern API Backend: Provides a framework for Go developers focused on OpenAPI 3.1 and JSON Schema.
- Incremental Adoption: Allows teams to bring their own router, middleware, and logging/metrics. It includes an extensible OpenAPI & JSON Schema layer to document existing routes without a full rewrite.
- Guard Rails: Designed to prevent common API development mistakes.
- Self-Documenting: Ensures documentation stays up to date with the code.
- Developer Tooling: Provides high-quality generated tooling for developers.
Understand the Huma request flow
mainA request follows these steps before reaching your handler and being returned as a response:
- Unmarshal: Reads raw request body bytes into a Go structure.
- Validate: Checks input constraints (e.g.,
minimum,maxLength). - Resolve: Runs custom validation code.
- Operation: Your handler function executes business logic.
- Transform: Modifies structured response data before marshaling.
- Marshal: Converts structured response data into bytes (e.g., JSON).
Huma Overview and Key Features
mainHuma is a modern, high-performance micro-framework for building HTTP REST/RPC APIs in Go, powered by OpenAPI 3 and JSON Schema.
Key features include:
- Declarative Interface: Define operations, models, and request parameters (path, query, header, cookie, body) using Go types and annotations.
- Automatic Documentation: Generates OpenAPI 3.1 specifications and interactive documentation (e.g., via Stoplight Elements).
- Automatic Validation: Validates input models and handles errors automatically.
- Content Negotiation: Supports JSON (RFC 8259) and optionally CBOR (RFC 7049) via the
Acceptheader. - Standard Compliance: JSON errors follow RFC 9457 (
application/problem+json). - Extensibility: Works with any router (e.g.,
chi,std/net/http) and supports middleware/logging integration.
Implement Huma Auth Middleware for JWT Validation
mainIf you are not using an API Gateway to handle authentication, you can implement custom middleware within Huma to validate incoming JWTs.
Typical implementation steps:
- Fetch JWKS: Use a library like
github.com/lestrrat-go/jwx/v2/jwkto create a cached, auto-refreshing key set from your issuer's JWKS URL. - Check Operation Security: In the middleware, inspect
ctx.Operation().Securityto determine if the current endpoint requires authorization. - Validate Token: Extract the Bearer token from the
Authorizationheader and validate it using the JWKS, issuer, and audience. - Verify Scopes: Extract the
scopesclaim from the parsed JWT and ensure it contains the scopes required by the operation. - Register Middleware: Attach the middleware to your API using
api.UseMiddleware().
- Fetch JWKS: Use a library like
Group operations with huma.NewGroup
mainYou can group operations under common route prefixes and share middleware, operation modifiers, and response transformers using
huma.NewGroup. A group wraps ahuma.APIinstance and can be passed tohuma.Registeror convenience wrappers likehuma.Getandhuma.Post.Note: Groups assume that
huma.Registeror its convenience wrappers are used. If you are registering operations manually, you must callgroup.DocumentOperation(*huma.Operation)to ensure they are included in the documentation.grp := huma.NewGroup(api, "/v1") grp.UseMiddleware(authMiddleware) huma.Get(grp, "/users", func(ctx context.Context, input *struct{}) (*UsersResponse, error) { // ... })Control field requirement (Optional vs Required)
mainHuma determines if a field is required or optional based on the following priority logic:
- Default Behavior:
- Path parameters are always required.
- Cookie, header, and query parameters are optional by default.
- All other fields (request bodies, multipart forms) are required by default.
- Overriding to Optional: A field becomes optional if it has:
omitemptyin thejsontag.omitzeroin thejsontag.required:"false"tag.
- Overriding to Required: A field is required if it has
required:"true".
Global Configuration: To make all fields optional by default (overriding the default requirement for bodies), set
FieldsOptionalByDefaultin yourhuma.Config.config := huma.DefaultConfig("My API", "1.0.0") config.FieldsOptionalByDefault = true- Default Behavior:
Install Restish for API testing
mainHuma does not include a built-in CLI client, but you can use Restish to interact with your API. Restish provides a high-level interface that converts OpenAPI operations into command-line arguments and generates help documentation.
Installation by Platform
macOS
# Homebrew brew install restish # Go go install github.com/rest-sh/restish/v2/cmd/restish@latestLinux
# Go go install github.com/rest-sh/restish/v2/cmd/restish@latest # Homebrew for Linux brew install restishWindows
# Go go install github.com/rest-sh/restish/v2/cmd/restish@latest# Homebrew $ brew install restish # Go $ go install github.com/rest-sh/restish/v2/cmd/restish@latestSet a dynamic HTTP status code in a response
mainIf the status code depends on the logic within your handler, include a field named
Statusof typeintin your response struct. Note that usingDefaultStatusinhuma.Operationis generally preferred unless the status must change per request.type ThingResponse struct { Status int } huma.Register(api, huma.Operation{ OperationID: "get-thing", Method: http.MethodGet, Path: "/things/{thing-id}", Summary: "Get a thing by ID", }, func(ctx context.Context, input *ThingRequest) (*ThingResponse, error) { // Create a response and set the dynamic status resp := &ThingResponse{} if input.ID < 500 { resp.Status = 200 } else { // This is a made-up status code used for newer things. resp.Status = 250 } return resp, nil })Disable built-in API documentation
mainTo disable the built-in documentation, setconfig.DocsPathto an empty string"". You can then manually register your own routes on the underlying router to serve documentation or the OpenAPI spec.