Documentation
¶
Overview ¶
Package humanats provides a Huma adapter for NATS microservices. It enables defining APIs using Huma's powerful schema validation and OpenAPI generation capabilities while using NATS request/response as the transport layer.
Package humanats provides a Huma adapter for NATS microservices.
This package enables building APIs using Huma's powerful schema validation and OpenAPI generation capabilities while using NATS request/response as the transport layer instead of HTTP.
Overview ¶
The adapter translates HTTP-style operations defined with Huma into NATS subjects and handlers. This allows you to:
- Define APIs using Huma's familiar struct tags and validation
- Generate OpenAPI documentation for your NATS services
- Use NATS request/response for communication between microservices
- Leverage NATS micro's built-in service discovery and monitoring
Subject Mapping ¶
HTTP paths are mapped to NATS subjects with the method at the end, following NATS subject naming conventions:
GET /users/{id} -> users.*.GET
POST /users -> users.POST
PUT /users/{id} -> users.*.PUT
DELETE /users/{id} -> users.*.DELETE
With an optional prefix (e.g., "api"):
GET /users/{id} -> api.users.*.GET
Headers ¶
HTTP semantics are preserved using NATS headers:
- Query parameters: Sent in the "X-Query" header as URL-encoded string
- Response status: Returned in the "X-Status" header
Example Usage ¶
package main
import (
"context"
"log"
"github.com/danielgtaylor/huma/v2"
"github.com/nats-io/nats.go"
"github.com/sandrolain/huma-nats/src/humanats"
)
type GreetingInput struct {
Name string `path:"name" doc:"Name to greet"`
}
type GreetingOutput struct {
Body struct {
Message string `json:"message"`
}
}
func main() {
nc, err := nats.Connect(nats.DefaultURL)
if err != nil {
log.Fatal(err)
}
defer nc.Close()
api := humanats.New(nc, huma.DefaultConfig("Greeting Service", "1.0.0"),
humanats.WithServiceName("GreetingService"),
)
huma.Get(api, "/hello/{name}", func(ctx context.Context, input *GreetingInput) (*GreetingOutput, error) {
return &GreetingOutput{
Body: struct{ Message string }{
Message: "Hello, " + input.Name + "!",
},
}, nil
})
adapter := api.Adapter().(*humanats.NATSAdapter)
if err := adapter.Start(); err != nil {
log.Fatal(err)
}
defer adapter.Stop()
// Keep running
select {}
}
Index ¶
- Constants
- Variables
- func New(nc *nats.Conn, humaConfig huma.Config, opts ...Option) huma.API
- func PathToSubjectPattern(method, path, prefix string) string
- type AdapterConfig
- type DefaultSubjectMapper
- type EndpointInfo
- type HeaderConfig
- type NATSAdapter
- func (a *NATSAdapter) Config() AdapterConfig
- func (a *NATSAdapter) Endpoints() []EndpointInfo
- func (a *NATSAdapter) GetSubject(method, path string) string
- func (a *NATSAdapter) Handle(op *huma.Operation, handler func(huma.Context))
- func (a *NATSAdapter) Info() micro.Info
- func (a *NATSAdapter) ServeHTTP(w http.ResponseWriter, _ *http.Request)
- func (a *NATSAdapter) Service() micro.Service
- func (a *NATSAdapter) Start() error
- func (a *NATSAdapter) Started() bool
- func (a *NATSAdapter) Stats() micro.Stats
- func (a *NATSAdapter) Stop() error
- type Option
- func WithPrefix(prefix string) Option
- func WithQueryHeader(header string) Option
- func WithQueueGroup(queueGroup string) Option
- func WithServiceName(name string) Option
- func WithServiceVersion(version string) Option
- func WithStatusHeader(header string) Option
- func WithSubjectMapper(mapper SubjectMapper) Option
- type SubjectMapper
Constants ¶
const DefaultQueryHeader = "X-Query"
DefaultQueryHeader is the default header name for query parameters.
const DefaultStatusHeader = "X-Status"
DefaultStatusHeader is the default header name for HTTP status codes.
Variables ¶
var ( // ErrServiceNotStarted is returned when trying to use the adapter before starting. ErrServiceNotStarted = errors.New("humanats: service not started") // ErrServiceAlreadyStarted is returned when trying to start an already running service. ErrServiceAlreadyStarted = errors.New("humanats: service already started") // ErrNilConnection is returned when a nil NATS connection is provided. ErrNilConnection = errors.New("humanats: nil NATS connection") // ErrEmptyServiceName is returned when an empty service name is provided. ErrEmptyServiceName = errors.New("humanats: empty service name") // ErrEmptyServiceVersion is returned when an empty service version is provided. ErrEmptyServiceVersion = errors.New("humanats: empty service version") // ErrMultipartNotSupported is returned when multipart forms are requested over NATS. ErrMultipartNotSupported = errors.New("humanats: multipart forms not supported over NATS") // ErrEndpointRegistration is returned when an endpoint fails to register. ErrEndpointRegistration = errors.New("humanats: failed to register endpoint") )
Package errors
Functions ¶
func New ¶
New creates a new Huma API with the NATS adapter. The service must be started with Start() after registering operations.
func PathToSubjectPattern ¶
PathToSubjectPattern converts a Huma path to a NATS subject subscription pattern. This is useful for understanding what subject pattern will be used.
Types ¶
type AdapterConfig ¶
type AdapterConfig struct {
// ServiceName is the name of the NATS micro service.
ServiceName string
// ServiceVersion is the version of the NATS micro service.
ServiceVersion string
// Prefix is an optional prefix for all NATS subjects.
// Example: "api" results in subjects like "api.GET.users"
Prefix string
// Headers configures the NATS header names.
Headers HeaderConfig
// QueueGroup is the optional queue group for load balancing.
// If empty, the default NATS micro queue group "q" is used.
QueueGroup string
}
AdapterConfig contains the configuration for the NATS adapter.
type DefaultSubjectMapper ¶
type DefaultSubjectMapper struct {
// Prefix is an optional prefix for all subjects.
Prefix string
}
DefaultSubjectMapper implements SubjectMapper with a conservative mapping strategy. The format is: {Prefix}.{path}.{METHOD} where path segments are separated by dots. This follows NATS subject naming conventions where the action (method) comes last.
func (*DefaultSubjectMapper) ExtractParams ¶
func (m *DefaultSubjectMapper) ExtractParams(pathTemplate, subject string) map[string]string
ExtractParams extracts path parameter values from a NATS subject. It matches the subject against the path template and extracts values where wildcards (*) appear in the subject. Subject format: {prefix}.{path}.{method}
func (*DefaultSubjectMapper) ToSubject ¶
func (m *DefaultSubjectMapper) ToSubject(method, path string) string
ToSubject converts an HTTP method and path to a NATS subject. Examples:
- GET, "/users" -> "users.GET" (without prefix)
- GET, "/users" -> "api.users.GET" (with prefix "api")
- GET, "/users/{id}" -> "users.*.GET"
- GET, "/users/{id}/posts/{postId}" -> "users.*.posts.*.GET"
type EndpointInfo ¶
EndpointInfo contains public information about a registered endpoint.
type HeaderConfig ¶
type HeaderConfig struct {
// QueryHeader is the header name for query parameters (URL-encoded).
// Default: "X-Query"
QueryHeader string
// StatusHeader is the header name for HTTP response status codes.
// Default: "X-Status"
StatusHeader string
}
HeaderConfig configures the NATS header names used for HTTP semantics.
func DefaultHeaderConfig ¶
func DefaultHeaderConfig() HeaderConfig
DefaultHeaderConfig returns a HeaderConfig with default values.
type NATSAdapter ¶
type NATSAdapter struct {
// contains filtered or unexported fields
}
NATSAdapter implements huma.Adapter for NATS microservices.
func NewAdapter ¶
func NewAdapter(nc *nats.Conn, opts ...Option) *NATSAdapter
NewAdapter creates a NATSAdapter without creating the Huma API. This is useful for advanced use cases where you need more control.
func (*NATSAdapter) Config ¶
func (a *NATSAdapter) Config() AdapterConfig
Config returns the adapter configuration.
func (*NATSAdapter) Endpoints ¶
func (a *NATSAdapter) Endpoints() []EndpointInfo
Endpoints returns information about registered endpoints. Useful for debugging and documentation.
func (*NATSAdapter) GetSubject ¶
func (a *NATSAdapter) GetSubject(method, path string) string
GetSubject returns the NATS subject for a given HTTP method and path. This is useful for clients that need to know what subject to publish to.
func (*NATSAdapter) Handle ¶
func (a *NATSAdapter) Handle(op *huma.Operation, handler func(huma.Context))
Handle registers a handler for a Huma operation. This is called by Huma when registering operations.
func (*NATSAdapter) Info ¶
func (a *NATSAdapter) Info() micro.Info
Info returns information about the running service. Returns empty values if the service hasn't been started.
func (*NATSAdapter) ServeHTTP ¶
func (a *NATSAdapter) ServeHTTP(w http.ResponseWriter, _ *http.Request)
ServeHTTP implements http.Handler for compatibility. This is a no-op for NATS as we don't serve HTTP directly. Use StartHTTPBridge() if HTTP access is needed.
func (*NATSAdapter) Service ¶
func (a *NATSAdapter) Service() micro.Service
Service returns the underlying NATS micro service. Returns nil if the service hasn't been started.
func (*NATSAdapter) Start ¶
func (a *NATSAdapter) Start() error
Start starts the NATS micro service and registers all endpoints. This must be called after registering all Huma operations.
func (*NATSAdapter) Started ¶
func (a *NATSAdapter) Started() bool
Started returns whether the service is running.
func (*NATSAdapter) Stats ¶
func (a *NATSAdapter) Stats() micro.Stats
Stats returns statistics about the running service. Returns empty values if the service hasn't been started.
type Option ¶
type Option func(*NATSAdapter)
Option is a function that configures the NATSAdapter.
func WithPrefix ¶
WithPrefix sets a prefix for all NATS subjects. Example: WithPrefix("api") results in subjects like "api.users.GET"
func WithQueryHeader ¶
WithQueryHeader sets a custom header name for query parameters.
func WithQueueGroup ¶
WithQueueGroup sets the queue group for load balancing.
func WithServiceName ¶
WithServiceName sets the NATS micro service name.
func WithServiceVersion ¶
WithServiceVersion sets the NATS micro service version.
func WithStatusHeader ¶
WithStatusHeader sets a custom header name for HTTP status codes.
func WithSubjectMapper ¶
func WithSubjectMapper(mapper SubjectMapper) Option
WithSubjectMapper sets a custom subject mapper.
type SubjectMapper ¶
type SubjectMapper interface {
// ToSubject converts an HTTP method and path to a NATS subject.
// Example: GET, "/users/{id}" -> "users.*.GET"
ToSubject(method, path string) string
// ExtractParams extracts path parameter values from a NATS subject
// using the original path template.
// Example: "/users/{id}", "users.123.GET" -> {"id": "123"}
ExtractParams(pathTemplate, subject string) map[string]string
}
SubjectMapper defines the interface for mapping HTTP paths to NATS subjects.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package client provides a convenient HTTP-like client for NATS-based microservices built with huma-nats.
|
Package client provides a convenient HTTP-like client for NATS-based microservices built with huma-nats. |
|
examples
|
|
|
basic
command
Package main demonstrates basic usage of huma-nats adapter.
|
Package main demonstrates basic usage of huma-nats adapter. |
|
basic/client
command
Package main demonstrates a NATS client calling the greeting service.
|
Package main demonstrates a NATS client calling the greeting service. |
|
crud
command
Package main demonstrates CRUD operations with huma-nats adapter.
|
Package main demonstrates CRUD operations with huma-nats adapter. |
|
crud/client
command
Package main demonstrates a NATS client calling the CRUD user service.
|
Package main demonstrates a NATS client calling the CRUD user service. |
|
query-params
command
Package main demonstrates query parameters with huma-nats adapter.
|
Package main demonstrates query parameters with huma-nats adapter. |
|
query-params/client
command
Package main demonstrates a NATS client using query parameters.
|
Package main demonstrates a NATS client using query parameters. |