mizuoai

package module
v0.0.0-...-ccf362c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 19, 2025 License: MIT Imports: 24 Imported by: 0

README

mizuoai - OpenAPI Integration

Type-safe OpenAPI documentation and request/response handling for Mizu.

Philosophy

Compile-Time Safety for HTTP APIs

Mizuoai shifts serialization type analysis to compile time using Go's type system:

// Traditional approach - runtime reflection
func HandleUser(w http.ResponseWriter, r *http.Request) {
    var input CreateUserRequest
    json.NewDecoder(r.Body).Decode(&input) // Runtime errors possible
    // Manual validation required
}

// Mizuoai approach - compile-time type safety
func HandleUser(tx mizuoai.Tx[CreateUserResponse], rx mizuoai.Rx[CreateUserRequest]) {
    input, err := rx.MizuRead() // Type-safe, validated at compile time
    // Handle error, input is guaranteed to match CreateUserRequest
}
How Compile-Time Serde Works

The magic happens in serde.go through generic type instantiation:

  1. Type Analysis at Initialization: When you call mizuoai.Post[I, O](), the generic types I (input) and O (output) are analyzed using reflection

  2. Code Generation via Function Composition: The newDecoder[I]() and newEncoder[O]() functions create specialized parsing/encoding functions for your specific types

This approach means zero type analyzing during request handling - all type analysis happens at compile-time.

Tag-Based Parameter Binding

Mizuoai uses struct tags to declaratively define API contracts:

type CreateOrderRequest struct {
    Path struct {
        UserID string `path:"user_id" required:"true"`
    } `mizu:"path"`

    Query struct {
        Currency string `query:"currency" default:"USD"`
    } `mizu:"query"`

    Header struct {
        Auth string `header:"Authorization"`
    } `mizu:"header"`

    Body struct {
        Items []Item `json:"items"`
    } `mizu:"body" required:"true"`
}

The tag values drive both runtime parsing and OpenAPI spec generation.

Features

  • Compile-time Analysis: No type analysis during request handling
  • Type-safe handlers with generic Tx[O] and Rx[I] types
  • Built-in documentation UI using Stoplight Elements
  • Support for all parameter locations: path, query, header, body, form
  • Automatic OpenAPI 3.0 spec generation from your Go types (and OpenAPI 3.1 compatibility)

Quick Start

package main

import (
    "log"
    "net/http"
    "github.com/humbornjo/mizu"
    "github.com/humbornjo/mizu/mizuoai"
)

// Define your request/response types
type CreateUserRequest struct {
    Body struct {
        Name  string `json:"name" required:"true"`
        Email string `json:"email" required:"true"`
    } `mizu:"body"`
}

type CreateUserResponse struct {
    ID    string `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

// Handler with type-safe Tx/Rx
createUserHandler := func(tx mizuoai.Tx[CreateUserResponse], rx mizuoai.Rx[CreateUserRequest]) {
    input, err := rx.MizuRead()
    if err != nil {
        tx.WriteHeader(http.StatusBadRequest)
        tx.Write([]byte(err.Error()))
        return
    }

    // input.Body is guaranteed to be populated and validated
    response := CreateUserResponse{
        ID:    "user-123",
        Name:  input.Body.Name,
        Email: input.Body.Email,
    }

    tx.MizuWrite(&response)
}

func main() {
    server := mizu.NewServer("my-api")

    // Initialize OpenAPI with documentation UI
    mizuoai.Initialize(server, "User API",
        mizuoai.WithOaiDocumentation(),
        mizuoai.WithOaiDescription("API for managing users"),
    )

    // Register type-safe handler
    mizuoai.Post(server, "/users", createUserHandler,
        mizuoai.WithOperationSummary("Create a new user"),
        mizuoai.WithOperationTags("users"),
    )

    server.Serve(":8080")
}

Parameter Binding

Path Parameters
type GetUserRequest struct {
    Path struct {
        UserID string `path:"user_id" required:"true" desc:"User identifier"`
    } `mizu:"path"`
}

mizuoai.Get(server, "/users/{user_id}", getUserHandler)
Query Parameters
type ListUsersRequest struct {
    Query struct {
        Page    int    `query:"page" default:"1"`
        Limit   int    `query:"limit" default:"10"`
        Search  string `query:"search"`
    } `mizu:"query"`
}
Headers
type AuthenticatedRequest struct {
    Header struct {
        Auth     string `header:"Authorization"`
        ClientID string `header:"X-Client-ID"`
    } `mizu:"header"`
}
Request Body (JSON)
type UpdateUserRequest struct {
    Body struct {
        Name     string   `json:"name"`
        Email    string   `json:"email"`
        Tags     []string `json:"tags"`
    } `mizu:"body" required:"true"`
}
Form Data
type UploadRequest struct {
    Form struct {
        Filename string `form:"filename"`
        File     []byte `form:"file"`
    } `mizu:"form"`
}

Type Support

Mizuoai handles various Go types automatically:

Supported Types
  • Primitives: string, int, int8-64, uint, uint8-64, float32/64, bool
  • Structs: Nested structs with json tags
  • Slices: Arrays of any supported type
  • Pointers: Automatically dereferenced
Response Type Detection

The encoder automatically chooses content type based on the response type:

// JSON response (default for structs)
type UserResponse struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

// Plain text response (for string types)
type MessageResponse string

// Handler will set Content-Type: text/plain
func handleMessage(tx mizuoai.Tx[MessageResponse], rx mizuoai.Rx[any]) {
    tx.MizuWrite(MessageResponse("Hello, World!"))
}

OpenAPI Configuration

Initialize with Options
mizuoai.Initialize(server, "My API",
    // Enable JSON format (default: YAML)
    mizuoai.WithOaiRenderJson(),

    // Enable documentation UI
    mizuoai.WithOaiDocumentation(),

    // Custom serve path (default: "/")
    mizuoai.WithOaiServePath("/docs"),
)
Operation Configuration
mizuoai.Post(server, "/users", createUserHandler,
    // Operation metadata
    mizuoai.WithOperationSummary("Create user"),
    mizuoai.WithOperationDescription("Creates a new user account"),
    mizuoai.WithOperationOperationId("createUser"),
    mizuoai.WithOperationTags("users", "admin"),

    // Deprecation
    mizuoai.WithOperationDeprecated(),
)
Path Configuration
// Add path-level configuration
mizuoai.Path(server, "/admin/{resource}",
    mizuoai.WithPathDescription("Administrative endpoints"),
    mizuoai.WithPathServer("https://admin.example.com", "Admin server", nil),
)

Performance Considerations

Benchmark Results

The benchmark here merely says that mizuoai does not has a performance issue compare to fuego, not a strict prove that mizuoai is much faster than fuego

goos: darwin
goarch: arm64
pkg: github.com/humbornjo/mizu/mizuoai
cpu: Apple M2 Pro
BenchmarkMizuOai_Small_Input
BenchmarkMizuOai_Small_Input/Mizu
BenchmarkMizuOai_Small_Input/Mizu-10         	   90024	     13663 ns/op	   29809 B/op	      34 allocs/op
BenchmarkMizuOai_Small_Input/Fuego
BenchmarkMizuOai_Small_Input/Fuego-10        	   56632	     21544 ns/op	   24550 B/op	      22 allocs/op
BenchmarkMizuOai_Large_Input
BenchmarkMizuOai_Large_Input/Mizu
BenchmarkMizuOai_Large_Input/Mizu-10         	     188	   6257025 ns/op	25876087 B/op	     600 allocs/op
BenchmarkMizuOai_Large_Input/Fuego
BenchmarkMizuOai_Large_Input/Fuego-10        	      80	  14643984 ns/op	42898211 B/op	     506 allocs/op
Fieldlet Optimization

Parameter parsing uses sorted slices instead of maps for better performance on small n:

// Map-based approach (typical)
field := fieldMap[paramName]
// O(1) but higher constant factors

// Slice-based approach (mizuoai)
idx, found := slices.BinarySearchFunc(fields, paramName, compare)
// O(log n) per lookup, but better cache locality and
// lower overhead for n < 100 fields

// The implementation chooses slice when struct fields are small (<100),
// as contiguous memory access and avoiding hash computation
// outperforms map lookups in practice.

References

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Delete

func Delete[I any, O any](srv *mizu.Server, pattern string, oaiHandler func(Tx[O], Rx[I]), opts ...OperationOption,
) *v3.Operation

Delete registers a generic handler for DELETE requests. It uses reflection to parse request data into the input type `I` and generate OpenAPI documentation.

func Get

func Get[I any, O any](srv *mizu.Server, pattern string, oaiHandler func(Tx[O], Rx[I]), opts ...OperationOption,
) *v3.Operation

Get registers a generic handler for GET requests. It uses reflection to parse request data into the input type `I` and generate OpenAPI documentation.

func Head[I any, O any](srv *mizu.Server, pattern string, oaiHandler func(Tx[O], Rx[I]), opts ...OperationOption,
) *v3.Operation

Head registers a generic handler for HEAD requests. It uses reflection to parse request data into the input type `I` and generate OpenAPI documentation.

func Initialize

func Initialize(srv *mizu.Server, title string, opts ...OaiOption) error

Initialize inject OpenAPI config into mizu.Server with the given path and options. openapi.json will be served at /{path}/openapi.json. HTML will be served at /{path}/openapi if enabled. {path} can be set using WithOaiServePath

func Options

func Options[I any, O any](srv *mizu.Server, pattern string, oaiHandler func(Tx[O], Rx[I]), opts ...OperationOption,
) *v3.Operation

Options registers a generic handler for OPTIONS requests. It uses reflection to parse request data into the input type `I` and generate OpenAPI documentation.

func Patch

func Patch[I any, O any](srv *mizu.Server, pattern string, oaiHandler func(Tx[O], Rx[I]), opts ...OperationOption,
) *v3.Operation

Patch registers a generic handler for PATCH requests. It uses reflection to parse request data into the input type `I` and generate OpenAPI documentation.

func Path

func Path(server *mizu.Server, pattern string, opts ...PathOption)

Path registers a new path in the OpenAPI spec. It can be used to set the path field that can't be accessed via Get, Post, etc.

See: https://spec.openapis.org/oas/v3.0.4.html#path-item-object

func Post

func Post[I any, O any](srv *mizu.Server, pattern string, oaiHandler func(Tx[O], Rx[I]), opts ...OperationOption,
) *v3.Operation

POST registers a generic handler for POST requests. It uses reflection to parse request data into the input type `I` and generate OpenAPI documentation.

func Put

func Put[I any, O any](srv *mizu.Server, pattern string, oaiHandler func(Tx[O], Rx[I]), opts ...OperationOption,
) *v3.Operation

Put registers a generic handler for PUT requests. It uses reflection to parse request data into the input type `I` and generate OpenAPI documentation.

func Trace

func Trace[I any, O any](srv *mizu.Server, pattern string, oaiHandler func(Tx[O], Rx[I]), opts ...OperationOption,
) *v3.Operation

Trace registers a generic handler for TRACE requests. It uses reflection to parse request data into the input type `I` and generate OpenAPI documentation.

Types

type OaiOption

type OaiOption func(*oaiConfig)

func WithOaiContact

func WithOaiContact(name string, url string, email string, extensions ...map[string]any) OaiOption

WithOaiContact provides contact information for the exposed API.

- https://spec.openapis.org/oas/v3.0.4.html#contact-object

func WithOaiDescription

func WithOaiDescription(description string) OaiOption

WithOaiDescription provides a verbose description of the API. CommonMark syntax MAY be used for rich text representation.

- https://spec.openapis.org/oas/v3.0.4.html#info-object

func WithOaiDocumentation

func WithOaiDocumentation() OaiOption

WithOaiDocumentation enables documentation generation.

func WithOaiExtensions

func WithOaiExtensions(extensions map[string]any) OaiOption

WithOaiExtensions adds extensions to the operation.

- https://spec.openapis.org/oas/v3.0.4.html#openapi-object

func WithOaiExternalDocs

func WithOaiExternalDocs(url string, description string, extensions ...map[string]any) OaiOption

WithOaiExternalDocs provides a reference to an external resource for extended documentation.

- https://spec.openapis.org/oas/v3.0.4.html#external-documentation-object

func WithOaiLicense

func WithOaiLicense(name string, url string, extensions ...map[string]any) OaiOption

WithOaiLicense provides the license information for the exposed API.

- https://spec.openapis.org/oas/v3.0.4.html#license-object

func WithOaiPreLoad

func WithOaiPreLoad(data []byte) OaiOption

WithOaiPreLoad loads an OpenAPI document from data.

func WithOaiRenderJson

func WithOaiRenderJson() OaiOption

WithOaiRenderJson use JSON rendering.

func WithOaiSecurity

func WithOaiSecurity(requirement map[string][]string) OaiOption

WithOaiSecurity adds a security requirement to the operation. Each name MUST correspond to a security scheme which is declared in the Security Schemes under the Components Object.

- https://spec.openapis.org/oas/v3.0.4.html#security-requirement-object

func WithOaiServePath

func WithOaiServePath(path string) OaiOption

WithOaiServePath sets the path to serve openapi.json.

func WithOaiServer

func WithOaiServer(url string, desc string, variables map[string]*v3.ServerVariable, extensions ...map[string]any,
) OaiOption

WithOaiServers adds an array of Server Objects, which provide connectivity information to a target server. If the servers field is not provided, or is an empty array, the default value would be a Server Object with a url value of /.

- https://spec.openapis.org/oas/v3.0.4.html#server-object

func WithOaiTag

func WithOaiTag(name string, desc string, externalDocs *base.ExternalDoc, extensions ...map[string]any) OaiOption

WithOaiTags adds tags to the operation.

- https://spec.openapis.org/oas/v3.0.4.html#tag-object

func WithOaiTermsOfService

func WithOaiTermsOfService(url string) OaiOption

WithOaiTermsOfService provides a URL to the Terms of Service for the API. Must be in the form of URI.

- https://spec.openapis.org/oas/v3.0.4.html#info-object

type OperationOption

type OperationOption func(*operationConfig)

func WithOperationCallback

func WithOperationCallback(key string, value *v3.Callback) OperationOption

WithOperationCallback adds a callback to the operation. A possible out-of band callbacks related to the parent operation. The key is a unique identifier for the Callback Object. Value is a Callback Object that describes a request that may be initiated by the API provider and the expected responses.

- https://spec.openapis.org/oas/v3.0.4.html#operation-object

func WithOperationDeprecated

func WithOperationDeprecated() OperationOption

WithOperationDeprecated marks the operation as deprecated.

- https://spec.openapis.org/oas/v3.0.4.html#operation-object

func WithOperationDescription

func WithOperationDescription(description string) OperationOption

WithOperationDescription provides a verbose explanation of the operation behavior. CommonMark syntax MAY be used for rich text representation.

- https://spec.openapis.org/oas/v3.0.4.html#operation-object

func WithOperationExternalDocs

func WithOperationExternalDocs(url string, description string, extensions ...map[string]any) OperationOption

WithOperationExternalDocs provides a reference to an external resource for extended documentation.

- https://spec.openapis.org/oas/v3.0.4.html#external-documentation-object

func WithOperationOperationId

func WithOperationOperationId(operationId string) OperationOption

WithOperationOperationId provides a unique string used to identify the operation. Unique string used to identify the operation. The id MUST be unique among all operations described in the API. The operationId value is case-sensitive.

- https://spec.openapis.org/oas/v3.0.4.html#operation-object

func WithOperationParameters

func WithOperationParameters(parameters ...*v3.Parameter) OperationOption

WithOperationParameters adds parameters to the operation. A list of parameters that are applicable for this operation. If a parameter is already defined in the Path Item, the new definition will override it but can never remove it. The list MUST NOT include duplicated parameters. A unique parameter is defined by a combination of a name and location. The list can use the Reference Object to link to parameters that are defined in the OpenAPI Object’s

- https://spec.openapis.org/oas/v3.0.4.html#path-item-object

func WithOperationSecurity

func WithOperationSecurity(requirement map[string][]string) OperationOption

WithOperationSecurity adds security requirements to the operation. Each name MUST correspond to a security scheme which is declared in the Security Schemes under the Components Object.

- https://spec.openapis.org/oas/v3.0.4.html#security-requirement-object

func WithOperationServer

func WithOperationServer(url string, desc string, variables map[string]*v3.ServerVariable,
	extensions ...map[string]any,
) OperationOption

WithOperationServer adds an Server Objects to the operation. An alternative servers array to service this operation. If a servers array is specified at the Path Item Object or OpenAPI Object level, it will be overridden by this value.

- https://spec.openapis.org/oas/v3.0.4.html#server-object

func WithOperationSummary

func WithOperationSummary(summary string) OperationOption

WithOperationSummary provides a summary of what the operation does.

- https://spec.openapis.org/oas/v3.0.4.html#operation-object

func WithOperationTags

func WithOperationTags(tags ...string) OperationOption

WithOperationTags adds tags to the operation, for logical grouping of operations.

- https://spec.openapis.org/oas/v3.0.4.html#operation-object

func WithResponseOverride

func WithResponseOverride(code int, links map[string]*v3.Link, headers map[string]*v3.Header) OperationOption

WithResponseOverride overrides the default response for the operation. Links and headers can be added if needed.

type PathOption

type PathOption func(*pathConfig)

func WithPathDescription

func WithPathDescription(desc string) PathOption

WithPathDescription adds a description for the path. An optional string summary, intended to apply to all operations in this path.

- https://spec.openapis.org/oas/v3.0.4.html#path-item-object

func WithPathExtensions

func WithPathExtensions(extensions ...map[string]any) PathOption

WithPathExtensions adds extensions to the operation.

- https://spec.openapis.org/oas/v3.0.4.html#path-item-object

func WithPathParameters

func WithPathParameters(parameters ...*v3.Parameter) PathOption

WithPathParameters adds parameters to the path. A list of parameters that are applicable for all the operations described under this path. These parameters can be overridden at the operation level, but cannot be removed there. The list MUST NOT include duplicated parameters. A unique parameter is defined by a combination of a name and location. The list can use the Reference Object to link to parameters that are defined in the OpenAPI Object’s components.parameters.

- https://spec.openapis.org/oas/v3.0.4.html#path-item-object

func WithPathServer

func WithPathServer(url string, desc string, variables map[string]*v3.ServerVariable, extensions ...map[string]any,
) PathOption

WithPathServers adds an Server Objects in Path Item Object, which provide connectivity information to a target server. If the servers field is not provided, or is an empty array, the default value would be a Server Object with a url value of /.

- https://spec.openapis.org/oas/v3.0.4.html#server-object

func WithPathSummary

func WithPathSummary(summary string) PathOption

WithPathSummary adds a summary for the path. An optional. An optional string summary, intended to apply to all operations in this path.

- https://spec.openapis.org/oas/v3.0.4.html#path-item-object

type Rx

type Rx[T any] struct {
	*http.Request
	// contains filtered or unexported fields
}

Rx represents the request side of an API endpoint. It provides access to the parsed request data and the original request context.

func (Rx[T]) MizuRead

func (rx Rx[T]) MizuRead() (T, error)

Read returns the parsed input from the request. The parsing logic is generated based on the struct tags of the input type.

type Tx

type Tx[T any] struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

Tx represents the response side of an API endpoint. It provides methods to write the response.

func (Tx[T]) MizuWrite

func (tx Tx[T]) MizuWrite(data *T) error

Write writes the JSON-encoded output to the response writer. It also sets the Content-Type header to "application/json".

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL