Documentation
¶
Index ¶
- Constants
- Variables
- func BroadcastJson(ctx context.Context, data any) error
- func BroadcastWS(ctx context.Context, data any) error
- func CSRFHeaderHook(c *Context) error
- func GetDomainForRequest(req *http.Request) string
- func GetHeader(ctx context.Context, hdr string) string
- func GetInputJSON[T ~[]byte](ctx context.Context) T
- func GetObject[T any](ctx context.Context, typ string) *T
- func GetParam[T any](ctx context.Context, v string) (T, bool)
- func GetParamDefault[T any](ctx context.Context, v string, def T) T
- func GetPrefixForRequest(req *http.Request) *url.URL
- func GetRequestBody(ctx context.Context) (io.ReadCloser, error)
- func GetUser[T any](ctx context.Context) *T
- func MakeJsonSocketFD(extraObjects map[string]any) (int, error)
- func MakeJsonUnixListener(socketName string, extraObjects map[string]any) error
- func Progress(ctx context.Context, data any) error
- func SecurePost(ctx context.Context) error
- func SendWS(ctx context.Context, channel string, data any) error
- func SetExtraResponse(ctx context.Context, k string, v any) bool
- func WithObject(h http.Handler, typ string, obj any) http.HandlerFunc
- func WithValue(h http.Handler, key, val any) http.HandlerFunc
- type Context
- func (c *Context) Call() (any, error)
- func (c *Context) CallSpecial() (any, error)
- func (c *Context) GetDomain() string
- func (c *Context) GetExtraResponse(k string) any
- func (c *Context) GetListen() []string
- func (c *Context) GetObject(typ string) any
- func (c *Context) GetParam(v string) any
- func (c *Context) GetParamTo(v string, obj any) error
- func (c *Context) GetParams() map[string]any
- func (c *Context) GetPath() string
- func (c *Context) GetQuery(v string) any
- func (c *Context) GetQueryFull() map[string]any
- func (c *Context) ListensFor(ev string) bool
- func (c *Context) NewRequest(target string) (*http.Request, error)
- func (ctx *Context) Paginate(resultsPerPage int) func(tx *gorm.DB) *gorm.DB
- func (c *Context) RemoteAddr() string
- func (c *Context) RequestId() string
- func (c *Context) Response() (res *Response, err error)
- func (c *Context) ServeHTTP(rw http.ResponseWriter, req *http.Request)
- func (c *Context) SetBytes(req []byte, contentType string) error
- func (c *Context) SetCache(t time.Duration)
- func (c *Context) SetCsrfValidated(ok bool)
- func (c *Context) SetDecoder(dec interface{ ... }) error
- func (c *Context) SetExtraResponse(k string, v any)
- func (c *Context) SetFlag(flag string, val bool)
- func (c *Context) SetHttp(rw http.ResponseWriter, req *http.Request) error
- func (c *Context) SetListen(ev string, listen bool)
- func (c *Context) SetObject(typ string, v any)
- func (c *Context) SetParam(name string, v any)
- func (c *Context) SetParams(v map[string]any)
- func (c *Context) SetPath(p string)
- func (c *Context) SetResponseSink(sink ResponseSink)
- func (c *Context) SetShowProtectedFields(p bool)
- func (c *Context) SetUser(user any)
- func (c *Context) Value(v any) any
- type Deletable
- type EncoderInterface
- type Error
- func ErrBadRequest(token, msg string, args ...any) *Error
- func ErrForbidden(token, msg string, args ...any) *Error
- func ErrInternalServerError(token, msg string, args ...any) *Error
- func ErrMethodNotAllowed(token, msg string, args ...any) *Error
- func ErrNotImplemented(token, msg string, args ...any) *Error
- func ErrServiceUnavailable(token, msg string, args ...any) *Error
- func NewError(code int, token, msg string, args ...any) *Error
- type RequestHook
- type Response
- type ResponseHook
- type ResponseSink
- type Updatable
Constants ¶
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 ¶
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.
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 )
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
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
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
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
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
GetHeader returns the requested header or an empty string if not found
func GetInputJSON ¶ added in v0.1.11
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
GetObject fetches an object associated with the context and casts it
func GetParam ¶ added in v0.1.8
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
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
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
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
MakeJsonSocketFD returns a file descriptor (integer) for a new json socket
func MakeJsonUnixListener ¶ added in v0.5.8
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 SecurePost ¶ added in v0.1.7
SecurePost ensures request was a POST request and has the required headers
func SendWS ¶ added in v0.5.23
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
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
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 ¶
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 NewChild ¶ added in v0.4.0
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 ¶
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) CallSpecial ¶
func (*Context) GetDomain ¶ added in v0.0.10
GetDomain returns the domain on which the request was issued
func (*Context) GetExtraResponse ¶ added in v0.0.6
GetExtraResponse returns the extra response data that was previously set
func (*Context) GetListen ¶ added in v0.5.21
GetListen returns a sorted list of all event channels this context is subscribed to.
func (*Context) GetObject ¶ added in v0.0.3
GetObject fetches an object associated with the current request
func (*Context) GetParam ¶
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 ¶
GetParamTo assigns the given GET param to an object, converting the type if needed
func (*Context) GetQuery ¶ added in v0.0.5
GetQuery returns a value from the GET parameters passed to the API
func (*Context) GetQueryFull ¶ added in v0.0.8
GetQueryFull returns the whole query string as a map
func (*Context) ListensFor ¶ added in v0.5.16
ListensFor returns true if this context is subscribed to the given event channel. The special value "*" always returns true (wildcard subscription).
func (*Context) NewRequest ¶
NewRequest returns a http request for this context (for example for forwarding, etc)
func (*Context) Paginate ¶ added in v0.5.7
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
RemoteAddr returns the remote address that made the request, if any is found
func (*Context) RequestId ¶ added in v0.0.20
RequestId returns the current request's ID, typically a uuid
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
SetBytes configures the Context with the given request sent raw with a content type
func (*Context) SetCache ¶ added in v0.5.3
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
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
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
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
SetFlag sets a flag on the context, and should only be used for very specific cases
func (*Context) SetHttp ¶
SetHttp configures the Context with the given http request and response writer
func (*Context) SetListen ¶ added in v0.5.16
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
SetObject allows setting an object to be associated with the context for this request
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
SetShowProtectedFields allows defining if fields flagged as protected should be shown or not
func (*Context) SetUser ¶ added in v0.1.8
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.
type Deletable ¶ added in v0.0.4
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
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
ErrBadRequest creates an error with HTTP status 400 Bad Request.
func ErrForbidden ¶ added in v0.2.6
ErrForbidden creates an error with HTTP status 403 Forbidden.
func ErrInternalServerError ¶ added in v0.2.6
ErrInternalServerError creates an error with HTTP status 500 Internal Server Error.
func ErrMethodNotAllowed ¶ added in v0.2.6
ErrMethodNotAllowed creates an error with HTTP status 405 Method Not Allowed.
func ErrNotImplemented ¶ added in v0.2.6
ErrNotImplemented creates an error with HTTP status 501 Not Implemented.
func ErrServiceUnavailable ¶ added in v0.2.6
ErrServiceUnavailable creates an error with HTTP status 503 Service Unavailable.
func NewError ¶ added in v0.2.6
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) HTTPStatus ¶ added in v0.0.17
HTTPStatus returns the HTTP status code for this error.
type RequestHook ¶ added in v0.0.20
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
GetContext returns the Context associated with this response.
func (*Response) MarshalContextJSON ¶ added in v0.5.4
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
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
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.