apirouter

package module
v0.5.28 Latest Latest
Warning

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

Go to latest
Published: Dec 11, 2025 License: MIT Imports: 36 Imported by: 1

README

GoDoc

API Router

A Go package providing a sophisticated REST/RPC API routing framework with support for multiple transport protocols (HTTP, WebSocket, UNIX sockets) and content types (JSON, CBOR).

Features

  • Multi-Protocol Support: HTTP, WebSocket, and UNIX socket transports
  • Multiple Serialization Formats: JSON (primary), CBOR (binary), URL-encoded, multipart form
  • Path-Based Routing: Routes requests via the pobj object registry framework
  • Type-Safe Parameters: Generic functions for parameter extraction with automatic type conversion
  • Hook System: Request and response hooks for middleware-like behavior
  • WebSocket Broadcasting: Real-time event distribution with channel subscriptions
  • GORM Integration: Built-in pagination scope for database queries
  • CORS Support: Automatic CORS header handling
  • Protected Fields: Context-aware JSON marshaling to hide sensitive fields

Installation

go get github.com/KarpelesLab/apirouter

Quick Start

HTTP Handler
package main

import (
    "net/http"
    "github.com/KarpelesLab/apirouter"
)

func main() {
    http.Handle("/_api/", http.StripPrefix("/_api", apirouter.HTTP))
    http.ListenAndServe(":8080", nil)
}
With Middleware
// Add objects to context for all requests
http.Handle("/_api/", apirouter.WithObject(apirouter.HTTP, "db", dbInstance))

// Add context values
http.Handle("/_api/", apirouter.WithValue(apirouter.HTTP, "config", configInstance))

Request Routing

Requests are routed using a path format: Object/id:method

  • Object: Navigate the pobj object hierarchy (uppercase first letter)
  • id: Load a specific object instance by ID
  • :method: Call a static method on the object
HTTP Method Mapping
HTTP Method Action Description
GET/HEAD Fetch/List Retrieve object(s)
POST Create Create new object
PATCH Update Update existing object (requires Updatable interface)
DELETE Delete Remove object (requires Deletable interface)
OPTIONS CORS Preflight request handling
Examples
GET  /User              → List users
GET  /User/123          → Fetch user with ID 123
POST /User              → Create new user
PATCH /User/123         → Update user 123
DELETE /User/123        → Delete user 123
GET  /User:search       → Call User.search() static method
POST /User:authenticate → Call User.authenticate() static method

Parameter Handling

Accessing Parameters
func MyHandler(ctx context.Context) (any, error) {
    // Type-safe parameter retrieval
    id, ok := apirouter.GetParam[string](ctx, "id")

    // With default value
    limit := apirouter.GetParamDefault[int](ctx, "limit", 25)

    // Nested parameters using dot notation
    city, _ := apirouter.GetParam[string](ctx, "address.city")

    return result, nil
}
Parameter Sources
  • GET requests: Query string parameters, or JSON in _ parameter
  • POST/PATCH/PUT: Request body (JSON, CBOR, URL-encoded, or multipart)
  • URL-encoded/Multipart: Can include JSON in _ parameter to override
Request Size Limits
Content Type Max Size
JSON 10 MB
URL-encoded 1 MB
Multipart 256 MB

Request Hooks

Hooks allow intercepting requests for authentication, validation, etc.

// Authentication hook
apirouter.RequestHooks = append(apirouter.RequestHooks, func(c *apirouter.Context) error {
    token := apirouter.GetHeader(c, "Authorization")
    user, err := validateToken(token)
    if err != nil {
        return apirouter.ErrAccessDenied
    }
    c.SetUser(user)
    return nil
})
CSRF Validation
// Mark request as CSRF-validated (typically in a hook)
c.SetCsrfValidated(true)

// Check CSRF status in handlers
if apirouter.SecurePost(ctx) {
    // Request is POST with valid CSRF
}

Response Hooks

apirouter.ResponseHooks = append(apirouter.ResponseHooks, func(r *apirouter.Response) error {
    // Add audit logging, modify response, etc.
    return nil
})

User Management

// In request hook
c.SetUser(userObject)

// In handler
user := apirouter.GetUser[*MyUser](ctx)

Returning Errors

Use the Error struct for structured error responses:

// Predefined errors
return nil, apirouter.ErrNotFound
return nil, apirouter.ErrAccessDenied

// Custom errors
return nil, apirouter.ErrBadRequest("invalid_email", "Email format is invalid")
return nil, apirouter.ErrForbidden("quota_exceeded", "User %s has exceeded quota", username)

// Full error control
return nil, &apirouter.Error{
    Message: "Custom error",
    Code:    400,
    Token:   "custom_error_token",
    Info:    map[string]any{"field": "email"},
}
Available Error Helpers
  • ErrBadRequest(token, msg, args...) - 400
  • ErrForbidden(token, msg, args...) - 403
  • ErrMethodNotAllowed(token, msg, args...) - 405
  • ErrInternalServerError(token, msg, args...) - 500
  • ErrNotImplemented(token, msg, args...) - 501
  • ErrServiceUnavailable(token, msg, args...) - 503
Predefined Error Variables
  • ErrNotFound - 404 Not Found
  • ErrAccessDenied - 403 Forbidden
  • ErrInternal - 500 Internal Server Error
  • ErrInsecureRequest - 400 Bad Request (missing CSRF)
  • ErrLengthRequired - 411 Length Required
  • ErrRequestEntityTooLarge - 413 Payload Too Large

WebSocket Support

Connecting

Clients connect to /_websocket and send JSON/CBOR messages:

{"path": "User:list", "verb": "GET", "params": {"limit": 10}}
Event Subscription
// Subscribe to events (in handler)
c.SetListen("user_updates", true)

// Broadcast to all clients listening
apirouter.BroadcastWS(ctx, map[string]any{
    "result": "event",
    "type": "user_updated",
    "data": userData,
})

// Send to specific channel
apirouter.SendWS(ctx, "user_updates", eventData)
Progress Updates

Send intermediate progress during long operations:

func LongOperation(ctx context.Context) (any, error) {
    for i := 0; i < 100; i++ {
        apirouter.Progress(ctx, map[string]any{
            "percent": i,
            "status": "processing",
        })
        // ... do work ...
    }
    return result, nil
}

UNIX Socket RPC

For local IPC communication:

// Server
err := apirouter.MakeJsonUnixListener("/tmp/api.sock", map[string]any{
    "version": "1.0",
})

// Client sends JSON:
// {"path": "User:list", "params": {"limit": 10}}

GORM Pagination

Built-in pagination scope for GORM queries:

func ListUsers(ctx context.Context) (any, error) {
    var c *apirouter.Context
    ctx.Value(&c)

    var users []User
    // Uses page_no and results_per_page params (max 100)
    err := db.Scopes(c.Paginate(25)).Find(&users).Error
    return users, err
}

Response Format

Standard JSON response envelope:

{
    "result": "success",
    "data": { ... },
    "time": 0.042,
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
}

Error response:

{
    "result": "error",
    "error": "Not found",
    "code": 404,
    "token": "error_not_found",
    "time": 0.001,
    "request_id": "550e8400-e29b-41d4-a716-446655440000"
}
Raw Response Mode

Add ?raw to bypass the response envelope and return data directly.

Pretty Printing

Add ?pretty for indented JSON output.

Extra Response Data

Add metadata to responses (pagination info, audit trails, etc.):

c.SetExtraResponse("total_count", 1000)
c.SetExtraResponse("page", 1)

// Or from context
apirouter.SetExtraResponse(ctx, "cursor", nextCursor)

Caching

// Enable caching for this response
c.SetCache(time.Hour)

Interfaces

Updatable

Implement for PATCH support:

type Updatable interface {
    ApiUpdate(ctx context.Context) error
}
Deletable

Implement for DELETE support:

type Deletable interface {
    ApiDelete(ctx context.Context) error
}

Context Values

Access special values from context:

var c *apirouter.Context
ctx.Value(&c)

// Available string keys:
ctx.Value("input_json")    // Raw input JSON
ctx.Value("http_request")  // *http.Request
ctx.Value("domain")        // Request domain
ctx.Value("user_object")   // User object
ctx.Value("request_id")    // Request UUID

Dependencies

License

See LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	// MaxJsonDataLength is the maximum size for JSON request bodies (10MB).
	MaxJsonDataLength = int64(10<<20) + 1

	// MaxUrlEncodedDataLength is the maximum size for URL-encoded request bodies (1MB).
	MaxUrlEncodedDataLength = int64(1<<20) + 1

	// MaxMultipartFormLength is the maximum size for multipart form data (256MB).
	MaxMultipartFormLength = int64(1<<28) + 1
)

Request body size limits for different content types.

Variables

View Source
var (
	// ErrTargetMissing indicates a required target URL is missing.
	ErrTargetMissing = errors.New("missing target")

	// ErrNotFound indicates the requested resource was not found (404).
	ErrNotFound = &Error{Message: "Not found", Token: "error_not_found", Code: http.StatusNotFound, parent: fs.ErrNotExist}

	// ErrAccessDenied indicates the request was forbidden (403).
	ErrAccessDenied = &Error{Message: "Access denied", Token: "error_access_denied", Code: http.StatusForbidden}

	// ErrInternal indicates an internal server error occurred (500).
	ErrInternal = &Error{Message: "An internal error occurred", Token: "error_internal", Code: http.StatusInternalServerError}

	// ErrInsecureRequest indicates the request lacks required security tokens (400).
	ErrInsecureRequest = &Error{Message: "Request must use POST and have the appropriate tokens", Token: "error_insecure_request", Code: http.StatusBadRequest}

	// ErrTeapot is an easter egg error (418).
	ErrTeapot = &Error{Message: "A teapot has appeared", Token: "error_teapot", Code: http.StatusTeapot}

	// ErrLengthRequired indicates Content-Length header is required (411).
	ErrLengthRequired = &Error{Message: "Content-Length header is required for this request", Token: "error_length_required", Code: http.StatusLengthRequired}

	// ErrRequestEntityTooLarge indicates the request body exceeds size limits (413).
	ErrRequestEntityTooLarge = &Error{Message: "Request body is too large", Token: "error_request_entity_too_large", Code: http.StatusRequestEntityTooLarge}
)

Common error values that can be returned from API handlers.

View Source
var (
	// RequestHooks is a slice of hooks that will be executed before each request.
	// Hooks are executed in order; if any hook returns an error, subsequent hooks
	// are skipped and an error response is returned.
	RequestHooks []RequestHook

	// ResponseHooks is a slice of hooks that will be executed after generating a response.
	// Hooks are executed in order for all responses including error responses.
	ResponseHooks []ResponseHook
)
View Source
var HTTP = http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
	ctx, err := NewHttp(rw, req)
	if err != nil {
		res := ctx.errorResponse(err)
		res.ServeHTTP(rw, req)
		return
	}
	res, _ := ctx.Response()
	res.ServeHTTP(rw, req)
})

HTTP is the main HTTP handler for the API router. It can be used directly as an http.Handler or http.HandlerFunc. The handler parses incoming requests, routes them to the appropriate API endpoint via the pobj framework, and returns JSON or CBOR responses.

Example usage:

http.Handle("/_api/", http.StripPrefix("/_api", apirouter.HTTP))

Functions

func BroadcastJson added in v0.5.8

func BroadcastJson(ctx context.Context, data any) error

BroadcastJson sends a message to all clients connected via JSON UNIX sockets. The data should typically be a map with "result" and "data" keys, e.g.:

apirouter.BroadcastJson(ctx, map[string]any{"result": "event", "type": "update", "data": payload})

Messages are sent asynchronously to all connected clients.

func BroadcastWS added in v0.4.4

func BroadcastWS(ctx context.Context, data any) error

BroadcastWS sends a message to all WebSocket clients subscribed to the "*" (wildcard) channel. The data should typically be a map with "result" and "data" keys, e.g.:

apirouter.BroadcastWS(ctx, map[string]any{"result": "event", "type": "update", "data": payload})

Messages are queued in a ring buffer and delivered asynchronously to all connected clients.

func CSRFHeaderHook added in v0.1.8

func CSRFHeaderHook(c *Context) error

CSRFHeaderHook is a sample hook for checking a specific middleware header for CSRF validation. It checks for the "Sec-Csrf-Token" header with value "valid" and marks the request as CSRF-validated. This is provided as an example; production applications should implement proper CSRF token validation.

func GetDomainForRequest added in v0.2.14

func GetDomainForRequest(req *http.Request) string

GetDomainForRequest returns the domain name for an HTTP request. It checks the Sec-Original-Host header first (for proxy scenarios), then falls back to the Host header, stripping any port number. Returns "_default" if no domain can be determined.

func GetHeader added in v0.0.15

func GetHeader(ctx context.Context, hdr string) string

GetHeader returns the requested header or an empty string if not found

func GetInputJSON added in v0.1.11

func GetInputJSON[T ~[]byte](ctx context.Context) T

GetInputJSON returns the raw JSON input for the current request. The type parameter T must be a byte slice type (e.g., []byte or json.RawMessage). Returns nil if no context is available or if there is no input data.

func GetObject added in v0.1.6

func GetObject[T any](ctx context.Context, typ string) *T

GetObject fetches an object associated with the context and casts it

func GetParam added in v0.1.8

func GetParam[T any](ctx context.Context, v string) (T, bool)

GetParam returns the parameter specified, and a boolean representing whether the value could be found and was of the right type

func GetParamDefault added in v0.5.20

func GetParamDefault[T any](ctx context.Context, v string, def T) T

GetParamDefault works the same as GetParam, except def will be returned if the value is not specified or fails to be converted to the needed type.

func GetPrefixForRequest added in v0.2.14

func GetPrefixForRequest(req *http.Request) *url.URL

GetPrefixForRequest returns a URL that can be used to address the server directly. It constructs the URL from the request's scheme, domain, and any path prefix. It handles Sec-Original-Host and Sec-Access-Prefix headers for proxy scenarios.

func GetRequestBody added in v0.0.15

func GetRequestBody(ctx context.Context) (io.ReadCloser, error)

GetRequestBody returns the current request's body if any, or an error

func GetUser added in v0.1.8

func GetUser[T any](ctx context.Context) *T

GetUser will return the user object if it matches type T. If there is no user object or it is not of the right type, nil will be returned

func MakeJsonSocketFD added in v0.5.8

func MakeJsonSocketFD(extraObjects map[string]any) (int, error)

MakeJsonSocketFD returns a file descriptor (integer) for a new json socket

func MakeJsonUnixListener added in v0.5.8

func MakeJsonUnixListener(socketName string, extraObjects map[string]any) error

MakeJsonUnixListener creates a UNIX socket at the given path and starts listening for connections. Each connection receives a JSON-RPC style interface where clients send requests like:

{"path": "Object:method", "verb": "GET", "params": {...}}

The extraObjects map allows injecting additional objects into each request's context. If socketName exceeds platform limits (104 chars on Darwin, 108 on Linux), a symlink workaround is automatically applied.

func Progress added in v0.5.6

func Progress(ctx context.Context, data any) error

Progress sends progress through the context response sink

func SecurePost added in v0.1.7

func SecurePost(ctx context.Context) error

SecurePost ensures request was a POST request and has the required headers

func SendWS added in v0.5.23

func SendWS(ctx context.Context, channel string, data any) error

SendWS sends a message to all WebSocket clients subscribed to the specified channel. Only clients that have called SetListen(channel, true) will receive the message. The data should typically be a map with "result" and "data" keys.

func SetExtraResponse added in v0.5.14

func SetExtraResponse(ctx context.Context, k string, v any) bool

SetExtraResponse adds response data to be added in the final response as meta-data, such as for paging, audit trails, etc. Returns false if the context cannot be retrieved.

func WithObject added in v0.5.13

func WithObject(h http.Handler, typ string, obj any) http.HandlerFunc

WithObject can be used to add an object to the generated context, that can then be obtained via apirouter.GetObject(ctx, ...).

func WithValue added in v0.5.13

func WithValue(h http.Handler, key, val any) http.HandlerFunc

WithValue is a method that can be used to add a value to the context of all requests going through a handler. This will automatically call context.WithValue on all incoming requests.

Types

type Context

type Context struct {
	context.Context
	// contains filtered or unexported fields
}

Context represents the context for an API request. It embeds context.Context and provides access to request parameters, user information, response metadata, and WebSocket event subscriptions. Context is safe for concurrent use after initialization.

func New

func New(ctx context.Context, path, verb string) *Context

New instantiates a new Context with the given path and verb

func NewChild added in v0.4.0

func NewChild(parent *Context, req []byte, contentType string) (*Context, error)

NewChild instantiates a new Context for a given child request. req will be a json or cbor object containing: path, verb (default=GET), params

func NewHttp

func NewHttp(rw http.ResponseWriter, req *http.Request) (*Context, error)

NewHttp creates a new Context from an HTTP request. It parses the request body based on Content-Type and extracts parameters. Returns an error if the request body cannot be parsed.

func (*Context) Call

func (c *Context) Call() (any, error)

func (*Context) CallSpecial

func (c *Context) CallSpecial() (any, error)

func (*Context) GetDomain added in v0.0.10

func (c *Context) GetDomain() string

GetDomain returns the domain on which the request was issued

func (*Context) GetExtraResponse added in v0.0.6

func (c *Context) GetExtraResponse(k string) any

GetExtraResponse returns the extra response data that was previously set

func (*Context) GetListen added in v0.5.21

func (c *Context) GetListen() []string

GetListen returns a sorted list of all event channels this context is subscribed to.

func (*Context) GetObject added in v0.0.3

func (c *Context) GetObject(typ string) any

GetObject fetches an object associated with the current request

func (*Context) GetParam

func (c *Context) GetParam(v string) any

GetParam returns one individual value from the current parameters, and can lookup valuyes in submaps/etc by adding a dot between values.

func (*Context) GetParamTo

func (c *Context) GetParamTo(v string, obj any) error

GetParamTo assigns the given GET param to an object, converting the type if needed

func (*Context) GetParams

func (c *Context) GetParams() map[string]any

GetParams returns all the parameters associated with this request

func (*Context) GetPath

func (c *Context) GetPath() string

GetPath returns the API path that was requested

func (*Context) GetQuery added in v0.0.5

func (c *Context) GetQuery(v string) any

GetQuery returns a value from the GET parameters passed to the API

func (*Context) GetQueryFull added in v0.0.8

func (c *Context) GetQueryFull() map[string]any

GetQueryFull returns the whole query string as a map

func (*Context) ListensFor added in v0.5.16

func (c *Context) ListensFor(ev string) bool

ListensFor returns true if this context is subscribed to the given event channel. The special value "*" always returns true (wildcard subscription).

func (*Context) NewRequest

func (c *Context) NewRequest(target string) (*http.Request, error)

NewRequest returns a http request for this context (for example for forwarding, etc)

func (*Context) Paginate added in v0.5.7

func (ctx *Context) Paginate(resultsPerPage int) func(tx *gorm.DB) *gorm.DB

Paginate returns a GORM scope function that applies pagination to database queries. It reads "page_no" and "results_per_page" from the request parameters.

Parameters:

  • page_no: The page number (1-indexed, defaults to 1)
  • results_per_page: Number of results per page (defaults to resultsPerPage argument, max 100)

The resultsPerPage argument sets the default page size when not specified in the request. If resultsPerPage <= 0, it defaults to 25.

Example usage:

var users []User
db.Scopes(ctx.Paginate(25)).Find(&users)

func (*Context) RemoteAddr added in v0.3.7

func (c *Context) RemoteAddr() string

RemoteAddr returns the remote address that made the request, if any is found

func (*Context) RequestId added in v0.0.20

func (c *Context) RequestId() string

RequestId returns the current request's ID, typically a uuid

func (*Context) Response

func (c *Context) Response() (res *Response, err error)

Response executes the request and generates a response object

func (*Context) ServeHTTP

func (c *Context) ServeHTTP(rw http.ResponseWriter, req *http.Request)

ServeHTTP implements http.Handler, allowing a Context to be used as an HTTP handler. It executes the request and writes the response.

func (*Context) SetBytes added in v0.5.3

func (c *Context) SetBytes(req []byte, contentType string) error

SetBytes configures the Context with the given request sent raw with a content type

func (*Context) SetCache added in v0.5.3

func (c *Context) SetCache(t time.Duration)

SetCache defines this API call can be cached up to the given time. A negative or zero value will disable caching (default)

func (*Context) SetCsrfValidated added in v0.1.8

func (c *Context) SetCsrfValidated(ok bool)

SetCsrfValidated is to be used in request hook to tell apirouter if the request came with a valid and appropriate CSRF token.

func (*Context) SetDecoder added in v0.5.3

func (c *Context) SetDecoder(dec interface{ Decode(any) error }) error

SetDecoder sets Context value based on a standardized encoded object to be decoded via an object similar to encoding/json.Decoder.

func (*Context) SetExtraResponse added in v0.0.6

func (c *Context) SetExtraResponse(k string, v any)

SetExtraResponse adds response data to be added in the final response as meta-data, such as for paging, audit trails, etc

func (*Context) SetFlag added in v0.2.9

func (c *Context) SetFlag(flag string, val bool)

SetFlag sets a flag on the context, and should only be used for very specific cases

func (*Context) SetHttp

func (c *Context) SetHttp(rw http.ResponseWriter, req *http.Request) error

SetHttp configures the Context with the given http request and response writer

func (*Context) SetListen added in v0.5.16

func (c *Context) SetListen(ev string, listen bool)

SetListen subscribes or unsubscribes this context from an event channel. When listen is true, the context will receive broadcasts sent to the channel. When listen is false, the subscription is removed.

func (*Context) SetObject added in v0.5.5

func (c *Context) SetObject(typ string, v any)

SetObject allows setting an object to be associated with the context for this request

func (*Context) SetParam

func (c *Context) SetParam(name string, v any)

SetParam allows setting one individual parameter to the request

func (*Context) SetParams

func (c *Context) SetParams(v map[string]any)

SetParams sets the params passed to the API

func (*Context) SetPath

func (c *Context) SetPath(p string)

func (*Context) SetResponseSink added in v0.5.6

func (c *Context) SetResponseSink(sink ResponseSink)

SetResponseSink sets the context's response sink used to send intermediate progress reports

func (*Context) SetShowProtectedFields added in v0.3.6

func (c *Context) SetShowProtectedFields(p bool)

SetShowProtectedFields allows defining if fields flagged as protected should be shown or not

func (*Context) SetUser added in v0.1.8

func (c *Context) SetUser(user any)

SetUser sets the user object for the associated context, which can be fetched with GetUser[T](ctx). This method will typically be called in a RequestHook.

func (*Context) Value

func (c *Context) Value(v any) any

Value implements context.Context and provides access to context values. It supports type-safe extraction of *Context and *http.Request via double pointers, as well as string keys for "input_json", "http_request", "domain", "user_object", and "request_id".

type Deletable added in v0.0.4

type Deletable interface {
	ApiDelete(ctx *Context) error
}

Deletable is an interface that objects can implement to support DELETE requests. When a DELETE request is made to an object endpoint, ApiDelete will be called with the request context, allowing the object to handle its own deletion.

type EncoderInterface added in v0.5.6

type EncoderInterface interface {
	Encode(obj any) error
}

EncoderInterface defines the interface for encoding response data. Any encoder that implements Encode(obj any) error can be used as a response sink.

type Error added in v0.0.17

type Error struct {
	Message string // error message
	Code    int    // HTTP status code for error
	Token   string // optional error token for programmatic handling
	Info    any    // optional extra information for the error
	// contains filtered or unexported fields
}

Error represents a structured API error with an HTTP status code and optional token. The Token field can be used by clients for programmatic error handling, while Message provides a human-readable description.

func ErrBadRequest added in v0.2.6

func ErrBadRequest(token, msg string, args ...any) *Error

ErrBadRequest creates an error with HTTP status 400 Bad Request.

func ErrForbidden added in v0.2.6

func ErrForbidden(token, msg string, args ...any) *Error

ErrForbidden creates an error with HTTP status 403 Forbidden.

func ErrInternalServerError added in v0.2.6

func ErrInternalServerError(token, msg string, args ...any) *Error

ErrInternalServerError creates an error with HTTP status 500 Internal Server Error.

func ErrMethodNotAllowed added in v0.2.6

func ErrMethodNotAllowed(token, msg string, args ...any) *Error

ErrMethodNotAllowed creates an error with HTTP status 405 Method Not Allowed.

func ErrNotImplemented added in v0.2.6

func ErrNotImplemented(token, msg string, args ...any) *Error

ErrNotImplemented creates an error with HTTP status 501 Not Implemented.

func ErrServiceUnavailable added in v0.2.6

func ErrServiceUnavailable(token, msg string, args ...any) *Error

ErrServiceUnavailable creates an error with HTTP status 503 Service Unavailable.

func NewError added in v0.2.6

func NewError(code int, token, msg string, args ...any) *Error

NewError creates a new Error with the specified HTTP status code, token, and formatted message. The msg parameter supports fmt.Errorf style formatting with args.

func (*Error) Error added in v0.0.17

func (e *Error) Error() string

Error implements the error interface.

func (*Error) HTTPStatus added in v0.0.17

func (e *Error) HTTPStatus() int

HTTPStatus returns the HTTP status code for this error.

func (*Error) Unwrap added in v0.2.6

func (e *Error) Unwrap() error

Unwrap returns the underlying error, if any, for use with errors.Is and errors.As.

type RequestHook added in v0.0.20

type RequestHook func(c *Context) error

RequestHook is a function type for intercepting requests before they are processed. Hooks can be used for authentication, authorization, logging, or request modification. Return an error to abort the request and return an error response to the client.

type Response

type Response struct {
	Result       string  `json:"result"` // error|success|redirect
	Error        string  `json:"error,omitempty"`
	Token        string  `json:"token,omitempty"`
	ErrorInfo    any     `json:"error_info,omitempty"`
	Code         int     `json:"code,omitempty"`
	Debug        string  `json:"debug,omitempty"`
	RequestId    string  `json:"request_id,omitempty"`
	Time         float64 `json:"time"`
	Data         any     `json:"data"`
	RedirectURL  string  `json:"redirect_url,omitempty"`
	RedirectCode int     `json:"redirect_code,omitempty"`
	QueryId      any     `json:"query_id,omitempty"`
	// contains filtered or unexported fields
}

Response represents an API response with metadata and payload. It can represent success, error, redirect, or progress responses.

func (*Response) GetContext added in v0.1.13

func (r *Response) GetContext() *Context

GetContext returns the Context associated with this response.

func (*Response) MarshalContextJSON added in v0.5.4

func (r *Response) MarshalContextJSON(ctx context.Context) ([]byte, error)

MarshalContextJSON marshals the response to JSON with the given context. The context can be used to control field visibility and other marshaling options.

func (*Response) MarshalJSON added in v0.5.4

func (r *Response) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for Response. It marshals the response data including any extra context data.

func (*Response) ServeHTTP

func (r *Response) ServeHTTP(rw http.ResponseWriter, req *http.Request)

ServeHTTP implements http.Handler for Response, allowing it to be used directly as an HTTP handler. It writes the response with appropriate headers for CORS, caching, and content negotiation (JSON or CBOR based on Accept header).

type ResponseHook added in v0.0.20

type ResponseHook func(r *Response) error

ResponseHook is a function type for intercepting responses before they are sent. Hooks can be used for logging, response modification, or adding extra data. Return an error to replace the response with an error response.

type ResponseSink added in v0.5.6

type ResponseSink interface {
	// SendResponse sends the response to the underlying backend.
	SendResponse(*Response) error
}

ResponseSink is an interface for sending API responses to different backends. Implementations can send responses to HTTP response writers, WebSocket connections, encoders, or any other output destination.

func EncoderSink added in v0.5.6

func EncoderSink(enc EncoderInterface) ResponseSink

EncoderSink wraps an encoder implementing EncoderInterface as a ResponseSink. This allows using any compatible encoder (such as json.Encoder or cbor.Encoder) to receive API responses.

type Updatable added in v0.0.4

type Updatable interface {
	ApiUpdate(ctx *Context) error
}

Updatable is an interface that objects can implement to support PATCH requests. When a PATCH request is made to an object endpoint, ApiUpdate will be called with the request context, allowing the object to update itself based on the request parameters.

Jump to

Keyboard shortcuts

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