moonapi
API reference

Every public type, function and method

The complete surface of the framework, grouped by package. Signatures come from the compiled interface; descriptions and examples from the source comments. Each item lists its parameters and return type.

@moonapi

The application object, response helpers, and the top-level API you build a service from.

Types

type
pub type ApiHandler = async (@ctx.Context) -> @http.Response
re-export
pub using @openapi {type ApiInfo}
re-export
pub using @security {type ApiKey}
re-export
pub using @security {type ApiKeyIn}
struct
pub struct App { router : @route.Router layers : Array[&@mid.Layer] exception_handlers : Array[(@ctx.Context, Error) -> @http.Response?] security_schemes : Array[@security.DeclaredScheme] enforcers : Map[String, (@ctx.Context, @security.SecurityScopes, Int64) -> Result[@security.AuthenticatedUser, @http.Response]] status_handlers : Map[Int32, (@ctx.Context) -> @http.Response] mounts : Array[(String, Mount)] startup_hooks : Array[async (Map[String, Json]) -> Unit] shutdown_hooks : Array[async (Map[String, Json]) -> Unit] mut info : @openapi.ApiInfo mut clock : () -> Int64 mut deps : @di.Deps? redirect_slashes : Bool webhooks : @route.Router }

A moonapi application: routes and WebSocket routes, the layers around them, exception and per-status handlers, mounts, the security schemes the OpenAPI document surfaces (with their runtime enforcers), lifespan hooks, and the verification clock. Compiles to an ASGI application any server (mooncat) can run.

FieldType
router@route.Router
layersArray[&@mid.Layer]
exception_handlersArray[(@ctx.Context, Error) -> @http.Response?]
security_schemesArray[@security.DeclaredScheme]
enforcersMap[String, (@ctx.Context, @security.SecurityScopes, Int64) -> Result[@security.AuthenticatedUser, @http.Response]]
status_handlersMap[Int32, (@ctx.Context) -> @http.Response]
mountsArray[(String, Mount)]
startup_hooksArray[async (Map[String, Json]) -> Unit]
shutdown_hooksArray[async (Map[String, Json]) -> Unit]
info mut@openapi.ApiInfo
clock mut() -> Int64
deps mut@di.Deps?
redirect_slashesBool
webhooks@route.Router
re-export
pub using @security {type AuthenticatedUser}
re-export
pub using @ctx {type BackgroundTasks}
re-export
pub using @security {type BasicAuth}
re-export
pub using @schema {type Constraint}
re-export
pub using @openapi {type Contact}
re-export
pub using @di {type Container}
re-export
pub using @ctx {type Context}
re-export
pub using @di {type Deps}
re-export
pub using @security {type DigestAuth}
re-export
pub using @socket {type Disconnected}
re-export
pub using @endpoint {type Endpoint}
re-export
pub using @status {type Events}
re-export
pub using @endpoint {type Example}
type
pub type ExceptionHandler = (@ctx.Context, Error) -> @http.Response?
re-export
pub using @openapi {type ExternalDocs}
re-export
pub using @schema {type Field}
type
pub type Hook = async (Map[String, Json]) -> Unit

A lifespan hook: it gets the lifespan state, where what it stores reaches every request as ctx.state().

type
pub type Hoop = async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply
re-export
pub using @ctx {type HttpBasicCredentials}
re-export
pub using @exceptions {type HttpException}
re-export
pub using @openapi {type License}
re-export
pub using @method {type Method}
type
pub type Middleware = async (@http.Request, async (@http.Request) -> @http.Response) -> @http.Response

A request-level middleware : the request and call_next, which runs the rest of the application, in; the response out. The response comes back whole, so a stream behind it is gathered first; a middleware that must keep streams streaming is a @mid.Layer.

re-export
pub using @security {type OAuth2CodeBearer}
re-export
pub using @security {type OAuth2PasswordBearer}
re-export
pub using @ctx {type OAuth2PasswordRequestForm}
re-export
pub using @schema {type ObjectSchema}
re-export
pub using @schema {type OpenApiVersion}
re-export
pub using @endpoint {type Param}
re-export
pub using @endpoint {type ParamLoc}
re-export
pub using @di {type Provider}
re-export
pub using @endpoint {type ResponseSpec}
re-export
pub using @route {type Router}
re-export
pub using @schema {type Schema}
re-export
pub using @di {type Scope}
re-export
pub using @security {type SecurityRequirement}
re-export
pub using @security {type SecurityScheme}
re-export
pub using @security {type SecurityScopes}
re-export
pub using @openapi {type Server}
re-export
pub using @status {type Stream}
type
pub type StreamHandler = async (@ctx.Context) -> @status.Stream
re-export
pub using @openapi {type Tag}
re-export
pub using @openapi {type Ui}
re-export
pub using @schema {type Unresolved}
type
pub type Url = (@route.Router) -> Unit
re-export
pub using @schema {type ValidationError}
re-export
pub using @socket {type WebSocket}
re-export
pub using @status {type Writer}
type
pub type WsHandler = async (@socket.WebSocket) -> Unit
re-export
pub using @socket {type WsMessage}

Constants & values

constant
pub const HTTP_100_CONTINUE : Int32 = 100
constant
pub const HTTP_101_SWITCHING_PROTOCOLS : Int32 = 101
constant
pub const HTTP_102_PROCESSING : Int32 = 102
constant
pub const HTTP_103_EARLY_HINTS : Int32 = 103
constant
pub const HTTP_200_OK : Int32 = 200
constant
pub const HTTP_201_CREATED : Int32 = 201
constant
pub const HTTP_202_ACCEPTED : Int32 = 202
constant
pub const HTTP_203_NON_AUTHORITATIVE_INFORMATION : Int32 = 203
constant
pub const HTTP_204_NO_CONTENT : Int32 = 204
constant
pub const HTTP_205_RESET_CONTENT : Int32 = 205
constant
pub const HTTP_206_PARTIAL_CONTENT : Int32 = 206
constant
pub const HTTP_207_MULTI_STATUS : Int32 = 207
constant
pub const HTTP_208_ALREADY_REPORTED : Int32 = 208
constant
pub const HTTP_226_IM_USED : Int32 = 226
constant
pub const HTTP_300_MULTIPLE_CHOICES : Int32 = 300
constant
pub const HTTP_301_MOVED_PERMANENTLY : Int32 = 301
constant
pub const HTTP_302_FOUND : Int32 = 302
constant
pub const HTTP_303_SEE_OTHER : Int32 = 303
constant
pub const HTTP_304_NOT_MODIFIED : Int32 = 304
constant
pub const HTTP_305_USE_PROXY : Int32 = 305
constant
pub const HTTP_306_RESERVED : Int32 = 306
constant
pub const HTTP_307_TEMPORARY_REDIRECT : Int32 = 307
constant
pub const HTTP_308_PERMANENT_REDIRECT : Int32 = 308
constant
pub const HTTP_400_BAD_REQUEST : Int32 = 400
constant
pub const HTTP_401_UNAUTHORIZED : Int32 = 401
constant
pub const HTTP_402_PAYMENT_REQUIRED : Int32 = 402
constant
pub const HTTP_403_FORBIDDEN : Int32 = 403
constant
pub const HTTP_404_NOT_FOUND : Int32 = 404
constant
pub const HTTP_405_METHOD_NOT_ALLOWED : Int32 = 405
constant
pub const HTTP_406_NOT_ACCEPTABLE : Int32 = 406
constant
pub const HTTP_407_PROXY_AUTHENTICATION_REQUIRED : Int32 = 407
constant
pub const HTTP_408_REQUEST_TIMEOUT : Int32 = 408
constant
pub const HTTP_409_CONFLICT : Int32 = 409
constant
pub const HTTP_410_GONE : Int32 = 410
constant
pub const HTTP_411_LENGTH_REQUIRED : Int32 = 411
constant
pub const HTTP_412_PRECONDITION_FAILED : Int32 = 412
constant
pub const HTTP_413_REQUEST_ENTITY_TOO_LARGE : Int32 = 413
constant
pub const HTTP_414_REQUEST_URI_TOO_LONG : Int32 = 414
constant
pub const HTTP_415_UNSUPPORTED_MEDIA_TYPE : Int32 = 415
constant
pub const HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE : Int32 = 416
constant
pub const HTTP_417_EXPECTATION_FAILED : Int32 = 417
constant
pub const HTTP_418_IM_A_TEAPOT : Int32 = 418
constant
pub const HTTP_421_MISDIRECTED_REQUEST : Int32 = 421
constant
pub const HTTP_422_UNPROCESSABLE_ENTITY : Int32 = 422
constant
pub const HTTP_423_LOCKED : Int32 = 423
constant
pub const HTTP_424_FAILED_DEPENDENCY : Int32 = 424
constant
pub const HTTP_425_TOO_EARLY : Int32 = 425
constant
pub const HTTP_426_UPGRADE_REQUIRED : Int32 = 426
constant
pub const HTTP_428_PRECONDITION_REQUIRED : Int32 = 428
constant
pub const HTTP_429_TOO_MANY_REQUESTS : Int32 = 429
constant
pub const HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE : Int32 = 431
constant
pub const HTTP_500_INTERNAL_SERVER_ERROR : Int32 = 500
constant
pub const HTTP_501_NOT_IMPLEMENTED : Int32 = 501
constant
pub const HTTP_502_BAD_GATEWAY : Int32 = 502
constant
pub const HTTP_503_SERVICE_UNAVAILABLE : Int32 = 503
constant
pub const HTTP_504_GATEWAY_TIMEOUT : Int32 = 504
constant
pub const HTTP_505_HTTP_VERSION_NOT_SUPPORTED : Int32 = 505
constant
pub const HTTP_506_VARIANT_ALSO_NEGOTIATES : Int32 = 506
constant
pub const HTTP_507_INSUFFICIENT_STORAGE : Int32 = 507
constant
pub const HTTP_508_LOOP_DETECTED : Int32 = 508
constant
pub const HTTP_510_NOT_EXTENDED : Int32 = 510
constant
pub const HTTP_511_NETWORK_AUTHENTICATION_REQUIRED : Int32 = 511
value
pub let query_limits : @moonurl.Limits
constant
pub const WS_1000_NORMAL_CLOSURE : Int32 = 1000
constant
pub const WS_1001_GOING_AWAY : Int32 = 1001
constant
pub const WS_1002_PROTOCOL_ERROR : Int32 = 1002
constant
pub const WS_1003_UNSUPPORTED_DATA : Int32 = 1003
constant
pub const WS_1005_NO_STATUS_RCVD : Int32 = 1005
constant
pub const WS_1006_ABNORMAL_CLOSURE : Int32 = 1006
constant
pub const WS_1007_INVALID_FRAME_PAYLOAD_DATA : Int32 = 1007
constant
pub const WS_1008_POLICY_VIOLATION : Int32 = 1008
constant
pub const WS_1009_MESSAGE_TOO_BIG : Int32 = 1009
constant
pub const WS_1010_MANDATORY_EXT : Int32 = 1010
constant
pub const WS_1011_INTERNAL_ERROR : Int32 = 1011
constant
pub const WS_1012_SERVICE_RESTART : Int32 = 1012
constant
pub const WS_1013_TRY_AGAIN_LATER : Int32 = 1013
constant
pub const WS_1014_BAD_GATEWAY : Int32 = 1014
constant
pub const WS_1015_TLS_HANDSHAKE : Int32 = 1015

Functions

function
pub fn check_constraints(Json, Array[@schema.Constraint], Array[String], Array[@schema.ValidationError]) -> Unit
ParameterTypeDefault
type onlyJsonrequired
type onlyArray[@schema.Constraint]required
type onlyArray[String]required
type onlyArray[@schema.ValidationError]required

Returns Unit

function
pub fn create_access_token(String, String, Int64, scopes? : Array[String], expires_in_secs? : Int64, extra? : Map[String, Json], wins? : @jwt.Wins, clash? : @jwt.OnClash[Map[String, Json]]) -> String
ParameterTypeDefault
type onlyStringrequired
type onlyStringrequired
type onlyInt64required
scopesArray[String]optional
expires_in_secsInt64optional
extraMap[String, Json]optional
wins@jwt.Winsoptional
clash@jwt.OnClash[Map[String, Json]]optional

Returns String

function
pub fn data_response(String, filename? : String, status? : Int32, inline? : Bool) -> @http.Response?
ParameterTypeDefault
type onlyStringrequired
filenameStringoptional
statusInt32optional
inlineBooloptional

Returns @http.Response?

function
pub fn data_url(Bytes, media_type? : String) -> String
ParameterTypeDefault
type onlyBytesrequired
media_typeStringoptional

Returns String

function
pub fn file_response(Bytes, filename? : String, media_type? : String, status? : Int32, inline? : Bool) -> @http.Response
ParameterTypeDefault
type onlyBytesrequired
filenameStringoptional
media_typeStringoptional
statusInt32optional
inlineBooloptional

Returns @http.Response

function
pub fn filter_response(@schema.Schema, Json) -> Result[Json, Array[@schema.ValidationError]]
ParameterTypeDefault
type only@schema.Schemarequired
type onlyJsonrequired

Returns Result[Json, Array[@schema.ValidationError]]

function
pub fn group(String, Array[(@route.Router) -> Unit], tags? : Array[String], security? : Array[@security.SecurityRequirement], dependencies? : Array[String], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> (@route.Router) -> Unit
ParameterTypeDefault
type onlyStringrequired
type onlyArray[(@route.Router) -> Unit]required
tagsArray[String]optional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns (@route.Router) -> Unit

function
pub fn html(Int32, String) -> @http.Response
ParameterTypeDefault
type onlyInt32required
type onlyStringrequired

Returns @http.Response

function
pub fn http_error(Int32, String, headers? : Array[(String, String)]) -> @exceptions.HttpException
ParameterTypeDefault
type onlyInt32required
type onlyStringrequired
headersArray[(String, String)]optional

Returns @exceptions.HttpException

function
pub fn json(Int32, Json) -> @http.Response
ParameterTypeDefault
type onlyInt32required
type onlyJsonrequired

Returns @http.Response

function
pub fn json_model(Int32, @schema.Schema, Json) -> @http.Response
ParameterTypeDefault
type onlyInt32required
type only@schema.Schemarequired
type onlyJsonrequired

Returns @http.Response

function
pub fn parse_basic_auth(String) -> @ctx.HttpBasicCredentials?
ParameterTypeDefault
type onlyStringrequired

Returns @ctx.HttpBasicCredentials?

function
pub fn path(String, async (@ctx.Context) -> @http.Response, methods? : Array[@method.Method], name? : String) -> (@route.Router) -> Unit
ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
methodsArray[@method.Method]optional
nameStringoptional

Returns (@route.Router) -> Unit

function
pub fn redirect(String, status? : Int32) -> @http.Response
ParameterTypeDefault
type onlyStringrequired
statusInt32optional

Returns @http.Response

function
pub fn redoc_ui(spec_url? : String, title? : String, js_url? : String, telemetry? : Bool) -> String
ParameterTypeDefault
spec_urlStringoptional
titleStringoptional
js_urlStringoptional
telemetryBooloptional

Returns String

function
pub fn scalar_ui(spec_url? : String, title? : String, js_url? : String, extra? : Map[String, Json]) -> String
ParameterTypeDefault
spec_urlStringoptional
titleStringoptional
js_urlStringoptional
extraMap[String, Json]optional

Returns String

function
pub fn sse(async (@status.Events) -> Unit, status? : Int32, headers? : Array[(String, String)], space? : Bool, wins? : @jwt.Wins, clash? : @jwt.OnClash[Array[(String, String)]]) -> @status.Stream
ParameterTypeDefault
type onlyasync (@status.Events) -> Unitrequired
statusInt32optional
headersArray[(String, String)]optional
spaceBooloptional
wins@jwt.Winsoptional
clash@jwt.OnClash[Array[(String, String)]]optional

Returns @status.Stream

function
pub fn swagger_redirect(js_url? : String) -> String
ParameterTypeDefault
js_urlStringoptional

Returns String

function
pub fn swagger_ui(spec_url? : String, title? : String, js_url? : String, css_url? : String, oauth2_redirect_url? : String, init_oauth? : Json, extra? : Map[String, Json]) -> String
ParameterTypeDefault
spec_urlStringoptional
titleStringoptional
js_urlStringoptional
css_urlStringoptional
oauth2_redirect_urlStringoptional
init_oauthJsonoptional
extraMap[String, Json]optional

Returns String

function
pub fn text(Int32, String) -> @http.Response
ParameterTypeDefault
type onlyInt32required
type onlyStringrequired

Returns @http.Response

function
pub fn token_response(String) -> @http.Response
ParameterTypeDefault
type onlyStringrequired

Returns @http.Response

function
pub fn unprocessable(Array[@schema.ValidationError]) -> @http.Response
ParameterTypeDefault
type onlyArray[@schema.ValidationError]required

Returns @http.Response

function
pub fn validate_schema(@schema.Schema, Json, Array[String], Array[@schema.ValidationError]) -> Unit
ParameterTypeDefault
type only@schema.Schemarequired
type onlyJsonrequired
type onlyArray[String]required
type onlyArray[@schema.ValidationError]required

Returns Unit

function
pub fn validation_error_body(Array[@schema.ValidationError]) -> Json
ParameterTypeDefault
type onlyArray[@schema.ValidationError]required

Returns Json

function
pub fn view(String, &@route.View, name? : String) -> (@route.Router) -> Unit
ParameterTypeDefault
type onlyStringrequired
type only&@route.Viewrequired
nameStringoptional

Returns (@route.Router) -> Unit

function
pub fn websocket(String, async (@socket.WebSocket) -> Unit, name? : String) -> (@route.Router) -> Unit
ParameterTypeDefault
type onlyStringrequired
type onlyasync (@socket.WebSocket) -> Unitrequired
nameStringoptional

Returns (@route.Router) -> Unit

function
pub fn with_constraints(Json, Array[@schema.Constraint], @schema.OpenApiVersion) -> Json
ParameterTypeDefault
type onlyJsonrequired
type onlyArray[@schema.Constraint]required
type only@schema.OpenApiVersionrequired

Returns Json

Methods on App

function
pub fn App::add_security_scheme(Self, String, @security.SecurityScheme, description? : String) -> Unit

Declare a security scheme under name, surfaced in the emitted OpenAPI document (components/securitySchemes in 3.x, securityDefinitions in Swagger 2.0) so the generated spec describes how to authenticate. description is the prose shown beside it in the documentation UI.

This declares only. A route naming this scheme in its security is documented as protected and left unguarded, exactly as a scheme that no path operation depends on is — the secure_* functions are the ones that wire an enforcer.

ParameterTypeDefault
type onlyStringrequired
type only@security.SecuritySchemerequired
descriptionStringoptional

Returns Unit

function
pub fn App::add_status_handler(Self, Int32, (@ctx.Context) -> @http.Response) -> Unit

Register a per-status exception handler keyed by an HTTP status code). Whenever an error path yields status — a routing 404 / 405, or a raised HttpException (or the fallback 500) — the handler's response replaces the default, so an app can serve a custom error page. Successful handler returns are never rewritten.

ParameterTypeDefault
type onlyInt32required
type only(@ctx.Context) -> @http.Responserequired

Returns Unit

function
pub fn App::delete(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a DELETE route. A shorthand for route(Delete, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::depends(Self, @di.Deps) -> Unit

Give the app the dependency container its routes resolve their declared dependencies through the application supplies). The container's value type is erased on the way in, because a route-level dependency runs for its effect and its value is never handed to the handler — the same thing dependencies=[...] does with the values it builds.

A route that declares a dependency the container does not provide is answered with a 500: the setup the route promised did not happen, and running the handler as though it had is worse than saying so.

ParameterTypeDefault
type only@di.Depsrequired

Returns Unit

function
pub fn App::describe(Self, title? : String, summary? : String, api_version? : String, description? : String, terms_of_service? : String, contact? : @openapi.Contact?, license? : @openapi.License?, servers? : Array[@openapi.Server], tags? : Array[@openapi.Tag], external_docs? : @openapi.ExternalDocs?) -> Unit

Set what the OpenAPI document says about this API summary=…, description=…, contact=…, license_info=…, servers=…, openapi_tags=…, openapi_external_docs=…)). App::openapi and the /openapi.json route enable_docs` registers both read it, so the document a client fetches and the one a test builds cannot describe different APIs. An argument left out keeps what was set before.

ParameterTypeDefault
titleStringoptional
summaryStringoptional
api_versionStringoptional
descriptionStringoptional
terms_of_serviceStringoptional
contact@openapi.Contact?optional
license@openapi.License?optional
serversArray[@openapi.Server]optional
tagsArray[@openapi.Tag]optional
external_docs@openapi.ExternalDocs?optional

Returns Unit

function
pub fn App::enable_docs(Self, openapi_url? : String?, docs_url? : String?, redoc_url? : String?, version? : @schema.OpenApiVersion, ui? : @openapi.Ui, oauth2_redirect_url? : String?, init_oauth? : Json, ui_extra? : Map[String, Json], root_path_in_servers? : Bool) -> Unit

Serve the app's own documentation: the OpenAPI document at openapi_url, an interactive reference at docs_url, and ReDoc at redoc_url. Pass None for any of them to leave it off. The routes are kept out of the document they serve, so enabling docs does not change the spec a client reads.

ui picks the reader at docs_url. With Swagger, oauth2_redirect_url is where an OAuth2 flow started from the page returns to, and init_oauth prefills it ; ui_extra is merged over the reader's own settings either way.

Behind a proxy that mounts the app under a prefix, the server reports that prefix as the ASGI root_path. The pages then fetch the document from under it, and with root_path_in_servers the document names it as its first server, so a call tried out from the page goes where the app actually is.

It is a call rather than a default because registering routes behind the app's back would surprise anyone mounting this app under a prefix.

ParameterTypeDefault
openapi_urlString?optional
docs_urlString?optional
redoc_urlString?optional
version@schema.OpenApiVersionoptional
ui@openapi.Uioptional
oauth2_redirect_urlString?optional
init_oauthJsonoptional
ui_extraMap[String, Json]optional
root_path_in_serversBooloptional

Returns Unit

function
pub fn App::exception_handler(Self, (@ctx.Context, Error) -> @http.Response?) -> Unit

Register an exception handler. On a raised error the handlers are tried in registration order; the first to return Some(response) wins. An unhandled error falls through to the built-in mapping — an HttpException becomes its own status / detail, anything else a 500.

ParameterTypeDefault
type only(@ctx.Context, Error) -> @http.Response?required

Returns Unit

function
pub fn App::get(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a GET route. A shorthand for route(Get, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub async fn App::handle(Self, @http.Request) -> @http.Response

Run request through the app in-process and return the response, the way a server would see it answered: the same ASGI path, layers included . A streamed response comes back with its body joined.

async test {
  let app = @moonapi.App::new()
  app.get("/users/{id}", ctx => {
    @moonapi.text(200, "user " + ctx.param("id").unwrap())
  })
  let reply = app.handle({
    http_method: "GET",
    path: "/users/42",
    query_string: b"",
    headers: [],
    body: b"",
  })
  assert_eq(reply.body, b"user 42")
}
ParameterTypeDefault
type only@http.Requestrequired

Returns @http.Response

function
pub fn App::head(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a HEAD route. A shorthand for route(Head, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::include_router(Self, @route.Router, prefix? : String, tags? : Array[String], security? : Array[@security.SecurityRequirement], dependencies? : Array[String], responses? : Array[@endpoint.ResponseSpec], deprecated? : Bool, include_in_schema? : Bool, hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Fold router's routes into this app ( include_router, and the same name — include is a reserved word). Each is registered under prefix and becomes one of the app's own routes, with the arguments given here reaching every one of them as Router::include_router describes.

ParameterTypeDefault
type only@route.Routerrequired
prefixStringoptional
tagsArray[String]optional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
responsesArray[@endpoint.ResponseSpec]optional
deprecatedBooloptional
include_in_schemaBooloptional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::layer(Self, &@mid.Layer) -> Unit

Wrap the application in layer, a moonasgi ASGI middleware add_middleware): moonasgi's Cors, Gzip, TrustedHosts, HttpsRedirect and ServerErrors, or one of your own. The first registered is the outermost, layers and middleware alike, and they wrap mounted applications too.

ParameterTypeDefault
type only&@mid.Layerrequired

Returns Unit

function
pub fn App::middleware(Self, async (@http.Request, async (@http.Request) -> @http.Response) -> @http.Response) -> Unit

Add a request-level middleware , placed among the layers in registration order.

ParameterTypeDefault
type onlyasync (@http.Request, async (@http.Request) -> @http.Response) -> @http.Responserequired

Returns Unit

function
pub fn App::mount(Self, String, Self) -> Unit

Mount a sub-application under prefix . A request whose path lies under prefix is served by subapp, with the prefix moved from path to root_path (its own layers, security and background tasks apply), and the sub-app's routes appear under prefix in the merged OpenAPI document with its security schemes folded into the parent's.

ParameterTypeDefault
type onlyStringrequired

Returns Unit

function
pub fn App::mount_asgi(Self, String, async (@spec.Scope, async () -> @spec.Event, async (@spec.Event) -> Unit) -> Unit) -> Unit

Mount any ASGI application under prefix app.mount("/static", StaticFiles(...))). A request under prefix reaches app with the prefix moved from path to root_path, exactly as for a sub-app.

It is not a moonapi application, so it contributes nothing to the OpenAPI document and has no lifespan of its own to run — the app only routes to it. Mounts are tried in registration order, whichever kind they are.

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@spec.Scope, async () -> @spec.Event, async (@spec.Event) -> Unit) -> Unitrequired

Returns Unit

function
pub fn App::new(redirect_slashes? : Bool) -> Self

Create an empty application. The verification clock defaults to 0 (Unix epoch); a server sets a real one with App::set_clock, and tests inject a fixed time so token expiry is deterministic.

redirect_slashes answers a path that matches no route, but would with its trailing slash added or removed, with a 307 to that other path, the query kept . / itself is never redirected, nor is a WebSocket connection.

async test {
  let app = @moonapi.App::new()
  app.get("/", _ctx => @moonapi.text(200, "Hello"))
  let reply = app.handle({
    http_method: "GET",
    path: "/",
    query_string: b"",
    headers: [],
    body: b"",
  })
  assert_eq(reply.status, 200)
}
ParameterTypeDefault
redirect_slashesBooloptional

Returns Self

function
pub fn App::on_shutdown(Self, async (Map[String, Json]) -> Unit) -> Unit

Run hook when the server shuts down, after the last request has been served on_event("shutdown")). Hooks run in reverse registration order, so a resource is released before whatever it was opened from. A hook that raises does not stop the others — shutdown reports the first failure once the rest have run.

ParameterTypeDefault
type onlyasync (Map[String, Json]) -> Unitrequired

Returns Unit

function
pub fn App::on_startup(Self, async (Map[String, Json]) -> Unit) -> Unit

Run hook when the server starts, before it accepts the first request on_event("startup")). Hooks run in the order they were registered; one that raises aborts startup, and the server is told why.

ParameterTypeDefault
type onlyasync (Map[String, Json]) -> Unitrequired

Returns Unit

function
pub fn App::openapi(Self, version? : @schema.OpenApiVersion, title? : String, summary? : String, api_version? : String, description? : String, terms_of_service? : String, contact? : @openapi.Contact?, license? : @openapi.License?, servers? : Array[@openapi.Server], tags? : Array[@openapi.Tag], external_docs? : @openapi.ExternalDocs?) -> Json

Build the app's OpenAPI document as a Json value, walking the registered routes — this app's and every mounted sub-app's, each under its prefix — into paths, methods and operations. version picks the dialect: Swagger 2.0, OpenAPI 3.0.3 or 3.1.0 off the identical routes. Routes registered with include_in_schema=false are left out.

The webhooks go under webhooks, which only 3.1 has; callbacks go under their operation in both 3.x dialects. Swagger 2.0 can express neither and leaves them out. The named arguments override what App::describe set, for this one document.

ParameterTypeDefault
version@schema.OpenApiVersionoptional
titleStringoptional
summaryStringoptional
api_versionStringoptional
descriptionStringoptional
terms_of_serviceStringoptional
contact@openapi.Contact?optional
license@openapi.License?optional
serversArray[@openapi.Server]optional
tagsArray[@openapi.Tag]optional
external_docs@openapi.ExternalDocs?optional

Returns Json

function
pub fn App::openapi_json(Self, version? : @schema.OpenApiVersion) -> String

The app's OpenAPI / Swagger document for version, stringified.

test {
  let app = @moonapi.App::new()
  app.get("/ping", _ctx => @moonapi.text(200, "pong"), summary="health check")
  let doc = app.openapi_json()
  assert_true(doc.contains("\"openapi\": \"3.1.0\""))
  assert_true(doc.contains("\"/ping\""))
}
ParameterTypeDefault
version@schema.OpenApiVersionoptional

Returns String

function
pub fn App::options(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a OPTIONS route. A shorthand for route(Options, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::patch(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a PATCH route. A shorthand for route(Patch, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::post(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a POST route. A shorthand for route(Post, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::put(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a PUT route. A shorthand for route(Put, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::route(Self, @method.Method, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a route for an explicit method. An optional endpoint descriptor makes the route fully typed (its parameters, request body, and responses surface in the OpenAPI document and drive validation); security attaches per-operation requirements (emitted as OpenAPI security and enforced before the handler when their scheme has an enforcer); dependencies names provider keys resolved through the app's container (App::depends) before the handler and torn down after it, whatever the handler did.

The rest describe the operation: summary and description are its prose, operation_id the stable handle client generators name their method after, status_code the status its success response is documented under, responses further documented responses, name the handle App::url_for resolves, openapi_extra a fragment merged over the generated operation object, and callbacks the requests this operation makes back to its caller, written as routes whose paths are runtime expressions — the same keyword arguments path operations take. hoops wrap this one route, inside any its routers put around it.

ParameterTypeDefault
type only@method.Methodrequired
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::route_stream(Self, @method.Method, String, async (@ctx.Context) -> @status.Stream, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a streaming route StreamingResponse). The handler's chunks reach the client as separate body events, so a long or open-ended reply starts arriving before it is finished.

A stream is only streamed as far as the app can honestly keep it one: a middleware that rewrites the body — gzip does — collapses the reply to a single chunk. Everything else about the route is ordinary; it documents, validates and enforces security exactly as route does.

ParameterTypeDefault
type only@method.Methodrequired
type onlyStringrequired
type onlyasync (@ctx.Context) -> @status.Streamrequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::secure_api_key(Self, String, @security.ApiKey, description? : String, auto_error? : Bool) -> Unit

Declare an API-key scheme under name and wire it as a runtime enforcer Security(APIKeyHeader(name=...))). The scheme appears in the document as apiKey in the header, query or cookie the key names, and a route requiring name is refused with 403 unless it presents a key the scheme accepts.

ParameterTypeDefault
type onlyStringrequired
type only@security.ApiKeyrequired
descriptionStringoptional
auto_errorBooloptional

Returns Unit

function
pub fn App::secure_basic(Self, String, @security.BasicAuth, description? : String, auto_error? : Bool) -> Unit

Declare an HTTP Basic scheme under name and wire it as a runtime enforcer . A route requiring name is refused with 401 and a Basic challenge unless it presents credentials the scheme accepts.

ParameterTypeDefault
type onlyStringrequired
type only@security.BasicAuthrequired
descriptionStringoptional
auto_errorBooloptional

Returns Unit

function
pub fn App::secure_bearer(Self, String, String, bearer_format? : String, description? : String, auto_error? : Bool) -> Unit

Declare a plain HTTP bearer scheme under name and wire it as a runtime enforcer . The token is verified as an HS256 JWT against secret at the app clock's time, and the route's required scopes are checked against the token's — the same guard the OAuth2 flows use, without an OAuth2 flow to advertise.

ParameterTypeDefault
type onlyStringrequired
type onlyStringrequired
bearer_formatStringoptional
descriptionStringoptional
auto_errorBooloptional

Returns Unit

function
pub fn App::secure_digest(Self, String, @security.DigestAuth, description? : String, auto_error? : Bool) -> Unit

Declare an HTTP Digest scheme under name and wire it as a runtime enforcer . A route requiring name is refused with 403 unless it presents a Digest credential the scheme accepts.

ParameterTypeDefault
type onlyStringrequired
type only@security.DigestAuthrequired
descriptionStringoptional
auto_errorBooloptional

Returns Unit

function
pub fn App::secure_oauth2(Self, String, @security.OAuth2PasswordBearer, scopes? : Array[(String, String)], description? : String, auto_error? : Bool) -> Unit

Declare an OAuth2 password-bearer scheme under name and wire it as a runtime enforcer. Like add_security_scheme it surfaces the scheme in the OpenAPI document (with the advertised scopes and description), and additionally registers the guard a route names in its security: the app pulls the bearer token, verifies it against bearer's secret at the app clock's time, and checks the route's required scopes — returning 401/403 before the handler runs.

auto_error=false admits the request instead of refusing it every security class takes, whose dependency then yields None and leaves the decision to the route).

ParameterTypeDefault
type onlyStringrequired
type only@security.OAuth2PasswordBearerrequired
scopesArray[(String, String)]optional
descriptionStringoptional
auto_errorBooloptional

Returns Unit

function
pub fn App::secure_oauth2_code(Self, String, @security.OAuth2CodeBearer, scopes? : Array[(String, String)], description? : String, auto_error? : Bool) -> Unit

Declare an OAuth2 authorization-code scheme under name and wire it as a runtime enforcer . The document describes the browser redirect and token endpoints and the advertised scopes; the guard verifies the presented bearer token exactly as the password flow's does, since by the time a request arrives the two flows have produced the same credential.

ParameterTypeDefault
type onlyStringrequired
type only@security.OAuth2CodeBearerrequired
scopesArray[(String, String)]optional
descriptionStringoptional
auto_errorBooloptional

Returns Unit

function
pub fn App::secure_openid(Self, String, String, String, description? : String, auto_error? : Bool) -> Unit

Declare an OpenID Connect scheme under name and wire it as a runtime enforcer . url is the discovery document a client reads every other parameter from; secret is what the ID token presented as a bearer credential is verified against.

Swagger 2.0 has no openIdConnect type, so this scheme is absent from a 2.0 document rather than described as something it is not.

ParameterTypeDefault
type onlyStringrequired
type onlyStringrequired
type onlyStringrequired
descriptionStringoptional
auto_errorBooloptional

Returns Unit

function
pub fn App::set_clock(Self, () -> Int64) -> Unit

Set the clock the app reads to verify token expiry when enforcing route security (Unix seconds). A native server passes the wall clock; a test passes a fixed function so expiry is deterministic.

ParameterTypeDefault
type only() -> Int64required

Returns Unit

function
pub fn App::stream(Self, String, async (@ctx.Context) -> @status.Stream, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a streaming GET route — the verb a stream is nearly always read over, and what an SSE endpoint is. A shorthand for route_stream(Get, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @status.Streamrequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::to_asgi(Self) -> async (@spec.Scope, async () -> @spec.Event, async (@spec.Event) -> Unit) -> Unit

Compile the app to an ASGI application a server can run: the layers around the router, in registration order with the first outermost.

Returns async (@spec.Scope, async () -> @spec.Event, async (@spec.Event) -> Unit) -> Unit

function
pub fn App::trace(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[@route.Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register a TRACE route. A shorthand for route(Trace, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[@route.Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::url_for(Self, String, params? : Map[String, String]) -> String?

The path of the route registered under name, with its parameters filled from params . Mounted sub-applications are searched too, so what comes back already carries the mount prefix — the path a client would call, not the one the sub-app knows itself by.

None when nothing is registered under that name, or when params is missing one the path needs or holds one its convertor refuses; only a path parameter takes a /.

test {
  let app = @moonapi.App::new()
  app.get("/items/{id}", _ctx => @moonapi.text(200, "item"), name="get_item")
  assert_eq(
    app.url_for("get_item", params=Map([("id", "77")])),
    Some("/items/77"),
  )
}
ParameterTypeDefault
type onlyStringrequired
paramsMap[String, String]optional

Returns String?

function
pub fn App::urls(Self, Array[(@route.Router) -> Unit]) -> Unit

Register a route table; see Router::urls.

ParameterTypeDefault
type onlyArray[(@route.Router) -> Unit]required

Returns Unit

function
pub fn App::view(Self, String, &@route.View, name? : String, tags? : Array[String], security? : Array[@security.SecurityRequirement], dependencies? : Array[String], deprecated? : Bool, include_in_schema? : Bool, hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]) -> Unit

Register the methods view answers at path; see Router::view.

ParameterTypeDefault
type onlyStringrequired
type only&@route.Viewrequired
nameStringoptional
tagsArray[String]optional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
deprecatedBooloptional
include_in_schemaBooloptional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> @route.Reply) -> @route.Reply]optional

Returns Unit

function
pub fn App::websocket(Self, String, async (@socket.WebSocket) -> Unit, name? : String, security? : Array[@security.SecurityRequirement], dependencies? : Array[String]) -> Unit

Register a WebSocket route . The path is a template with the same parameters and convertors as an HTTP route's.

security is enforced and dependencies resolved before the handler is called. A refusal declines the handshake with the response an HTTP route would have answered — through ASGI's websocket.http.response extension where the server offers it, and with close code 1008 otherwise. The dependencies are torn down when the handler returns. name is the handle App::url_for resolves.

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@socket.WebSocket) -> Unitrequired
nameStringoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional

Returns Unit

@ctx

The per-request context: path, query, header and cookie extraction, body parsing, and state.

Types

struct
pub struct BackgroundTasks { // private fields }

A queue of deferred tasks. A handler adds to ctx.background; the app runs the queue in the order tasks were added, after the response is sent and within the same request.

re-export
pub using @moonmime {type Form}
re-export
pub using @moonmime {type Limits}
re-export
pub using @moonmime {type Upload}

Functions

function
pub fn parse_basic_auth(String) -> HttpBasicCredentials?

Parse an HTTP Basic Authorization header value into credentials , or None. Matches the Basic scheme case-insensitively (RFC 7617), base64-decodes the rest, and splits on the first colon so a password may itself contain colons.

ParameterTypeDefault
type onlyStringrequired

Returns HttpBasicCredentials?

function
pub fn split_scopes(String) -> Array[String]

Split a space-delimited scope string into its scopes, dropping empty runs — the OAuth2 scope form field is one string like "read write".

ParameterTypeDefault
type onlyStringrequired

Returns Array[String]

Methods on BackgroundTasks

function
pub fn BackgroundTasks::add_task(Self, async () -> Unit) -> Unit

Enqueue a task to run after the response is sent .

ParameterTypeDefault
type onlyasync () -> Unitrequired

Returns Unit

function
pub fn BackgroundTasks::length(Self) -> Int32

How many tasks are queued.

Returns Int32

function
pub fn BackgroundTasks::new() -> Self

An empty task queue.

Returns Self

function
pub async fn BackgroundTasks::run(Self) -> Unit

Run every queued task in order, each after the previous returns, then clear the queue. A task that raises stops the ones after it and the error goes to the caller, as in .

Returns Unit

Methods on Context

function
pub fn Context::api_key_header(Self, String) -> String?

The API key carried in the request header name , or None. Header names are matched against the request's lower-cased headers.

ParameterTypeDefault
type onlyStringrequired

Returns String?

function
pub fn Context::api_key_query(Self, String) -> String?

The API key carried in the query parameter name , or None.

ParameterTypeDefault
type onlyStringrequired

Returns String?

function
pub fn Context::bearer_token(Self) -> String?

Pull the bearer token out of the Authorization: Bearer <token> header, None if the header is absent or isn't a bearer credential. The scheme name is matched case-insensitively, as RFC 6750 requires.

Returns String?

function
pub fn Context::body_json(Self) -> Json?

Parse the request body as JSON, returning None for an empty body or one that does not parse — the total counterpart of reading a JSON body.

test {
  let request : @moonasgi.Request = {
    http_method: "POST",
    path: "/login",
    query_string: b"",
    headers: [],
    body: b"{\"user\":\"ada\"}",
  }
  assert_eq(@ctx.Context::new(request).body_json(), Some({ "user": "ada" }))
  assert_eq(
    @ctx.Context::new({ ..request, body: b"not json", }).body_json(),
    None,
  )
}

Returns Json?

function
pub fn Context::digest_credentials(Self) -> String?

The credential of an Authorization: Digest <parameters> header — the comma-separated parameter list, verbatim . None when the header is absent or names another scheme; the scheme name is matched case-insensitively, as RFC 7235 requires.

Returns String?

function
pub fn Context::form(Self, limits? : @moonmime.Limits) -> @moonmime.Form?

The posted form — Form(...) and File(...) parameters.

Reading the body is moonhttp/form's job; what belongs here is knowing that a request has a Content-Type and handing it over. None means the form broke its bounds and was refused whole: a handler given the first thousand parts of a larger form would be answering a request nobody sent. An empty form is the other answer, and means the request carried none.

ParameterTypeDefault
limits@moonmime.Limitsoptional

Returns @moonmime.Form?

function
pub fn Context::http_basic(Self) -> HttpBasicCredentials?

The HTTP Basic credentials on this request , or None.

Returns HttpBasicCredentials?

function
pub fn Context::json_field(Self, String) -> Json?

Pull a single field out of a JSON object body by name, None if the body is absent, not an object, or lacks the field.

ParameterTypeDefault
type onlyStringrequired

Returns Json?

function
pub fn Context::last_event_id(Self) -> String?

The id of the last event the client received, from the Last-Event-ID header an event source sends when it reconnects, so a stream can resume after it. None on a first connection; an empty value is one too, since a client with no id sends no header.

Returns String?

function
pub fn Context::new(@http.Request, params? : Map[String, String], scope? : @spec.HttpScope, background? : BackgroundTasks) -> Self

A context for request. The scope defaults to the one a server would build for the request alone, which is what a test or a hand-built context needs.

ParameterTypeDefault
type only@http.Requestrequired
paramsMap[String, String]optional
scope@spec.HttpScopeoptional
backgroundBackgroundTasksoptional

Returns Self

function
pub fn Context::oauth2_password_form(Self) -> OAuth2PasswordRequestForm?

Read an OAuth2PasswordRequestForm off the request's urlencoded (or multipart) body. None when neither username nor password is present — the body isn't a password-grant form at all — and equally when the body is too large to be one, since a grant carries six fields and nothing that big is a login.

Returns OAuth2PasswordRequestForm?

function
pub fn Context::param(Self, String) -> String?

Look up a path parameter by name.

test {
  let request : @moonasgi.Request = {
    http_method: "GET",
    path: "/users/42",
    query_string: b"",
    headers: [],
    body: b"",
  }
  let ctx = @ctx.Context::new(request, params=Map([("id", "42")]))
  assert_eq(ctx.param("id"), Some("42"))
  assert_eq(ctx.param("name"), None)
}
ParameterTypeDefault
type onlyStringrequired

Returns String?

function
pub fn Context::query(Self, String, limits? : @moonurl.Limits) -> String?

Look up a query-string parameter by name, e.g. ?limit=10&q=cat%20dog. Keys and values are percent/plus-decoded, so q above reads back as cat dog. When a key repeats, the first occurrence wins; use query_all to read every one.

test {
  let request : @moonasgi.Request = {
    http_method: "GET",
    path: "/search",
    query_string: b"q=cat%20dog&q=fish",
    headers: [],
    body: b"",
  }
  let ctx = @ctx.Context::new(request)
  assert_eq(ctx.query("q"), Some("cat dog"))
  assert_eq(ctx.query_all("q"), ["cat dog", "fish"])
}
ParameterTypeDefault
type onlyStringrequired
limits@moonurl.Limitsoptional

Returns String?

function
pub fn Context::query_all(Self, String, limits? : @moonurl.Limits) -> Array[String]

Every value given for name, in the order they appear — ?tag=a&tag=b reads back as ["a", "b"]. Empty when the key is absent.

ParameterTypeDefault
type onlyStringrequired
limits@moonurl.Limitsoptional

Returns Array[String]

function
pub fn Context::serve(Self, Bytes, filename? : String, media_type? : String, inline? : Bool, etag? : @conditional.Tag, modified? : @moondate.Moment, ranges? : Bool) -> @http.Response

[file_response] with the request weighed first (RFC 9110 §13, §14):

* 304 — the client's copy is current. * 412 — a precondition it stated does not hold. * 206 — it asked for part, one Content-Range or a multipart/byteranges. * 416 — it asked for what is not there.

Everything turns on etag. Left out, one is hashed from the content, which costs a pass over the body; pass @conditional.stamp(length~, modified~) for one stat's worth instead, or any tag of your own.

ranges=false withdraws the offer in Accept-Ranges.

ParameterTypeDefault
type onlyBytesrequired
filenameStringoptional
media_typeStringoptional
inlineBooloptional
etag@conditional.Tagoptional
modified@moondate.Momentoptional
rangesBooloptional

Returns @http.Response

function
pub fn Context::state(Self) -> Map[String, Json]

The lifespan state: a shallow copy of what the startup hooks stored, so a handler reads the shared resources and anything it adds stays with this request.

Returns Map[String, Json]

Methods on OAuth2PasswordRequestForm

function
pub fn OAuth2PasswordRequestForm::equal(Self, Self) -> Bool

Returns Bool

function
pub fn OAuth2PasswordRequestForm::not_equal(Self, Self) -> Bool

Returns Bool

@di

Dependency-injection container, providers, and scopes resolved per request.

Types

struct
pub struct Deps { open : () -> DepsScope }

A container with its dependency value type erased (Container::erase builds one), so a non-generic App can hold one. Resolving through it runs a provider's factory and records its teardown exactly as Scope::get does; what it cannot do is hand the value back — which is precisely what a route-level dependency does not need, since dependencies=[...] discards the values it builds and keeps only their effects.

FieldType
open() -> DepsScope
struct
pub struct DepsScope { resolve : (String) -> Bool close : (Error?) -> Unit }

One request's resolution scope over an erased container: resolve a key (false when nothing provides it), then close, handing any failure to the teardowns.

FieldType
resolve(String) -> Bool
close(Error?) -> Unit
struct
pub struct Scope[V] { container : Container[V] cache : Map[String, V] building : Map[String, Bool] teardowns : Array[(Error?) -> Unit] }

A request-scoped resolution scope. Each dependency is built at most once and its value cached for the life of the scope ( per-request dependency cache), and each built value's teardown is recorded to run — in reverse registration order (LIFO) — when the scope closes. Open one per request, resolve dependencies through it, then close it (or use Container::run).

FieldType
containerContainer[V]
cacheMap[String, V]
buildingMap[String, Bool]
teardownsArray[(Error?) -> Unit]

@endpoint

Typed request parameters and response specifications that describe and validate a route.

Functions

function
pub fn loc_str(ParamLoc) -> String

The OpenAPI in string for a location.

ParameterTypeDefault
type onlyParamLocrequired

Returns String

Methods on Endpoint

function
pub fn Endpoint::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Endpoint::new(params? : Array[Param], request_body? : @schema.Schema, request_required? : Bool, request_examples? : Map[String, Example], responses? : Array[ResponseSpec]) -> Self

Build an endpoint descriptor. Everything is optional: a bare Endpoint::new() describes an endpoint with no parameters, no body, and (on emit) a default 200 OK response.

ParameterTypeDefault
paramsArray[Param]optional
request_body@schema.Schemaoptional
request_requiredBooloptional
request_examplesMap[String, Example]optional
responsesArray[ResponseSpec]optional

Returns Self

function
pub fn Endpoint::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Endpoint::validate(Self, @ctx.Context) -> Array[@schema.ValidationError]

Validate an inbound request ctx against this endpoint descriptor: every declared parameter (path / query / header / cookie) plus the JSON request body, all off the same descriptor tree that emits the OpenAPI operation. Returns the accumulated errors — an empty array means the request conforms, otherwise pass them to unprocessable for a -shaped 422.

ParameterTypeDefault
type only@ctx.Contextrequired

Returns Array[@schema.ValidationError]

Methods on Example

function
pub fn Example::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Example::new(value? : Json, summary? : String, description? : String, external_value? : String) -> Self
ParameterTypeDefault
valueJsonoptional
summaryStringoptional
descriptionStringoptional
external_valueStringoptional

Returns Self

function
pub fn Example::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Example::to_json(Self) -> Json

The Example Object for example. value and externalValue exclude each other, so a value given in both forms is written as the value.

Returns Json

Methods on Param

function
pub fn Param::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Param::is_required(Self) -> Bool

Whether a request must carry this parameter. One with a default never must — its absence is answered by the default, exactly as a Python default argument is.

Returns Bool

function
pub fn Param::key(Self) -> String

The name this parameter travels under: its alias when it has one, else its own name. This is what is read off the request, what the document calls it, and what a validation error's loc points at — all three being the client's view of the parameter.

Returns String

function
pub fn Param::new(String, ParamLoc, schema? : @schema.Schema, required? : Bool, description? : String, constraints? : Array[@schema.Constraint], default? : Json, alias_? : String, examples? : Map[String, Example]) -> Self

Build a parameter descriptor. schema defaults to a string and required to true. constraints are the Pydantic-style bounds reads off a Query(ge=…, max_length=…) — emitted into the parameter's documented schema *and* enforced on the inbound value. default is emitted and makes the parameter optional, since a value that has one is never missing. alias is the name the parameter travels under when that differs from the one the code calls it . examples are offered by name in the documentation .

ParameterTypeDefault
type onlyStringrequired
type onlyParamLocrequired
schema@schema.Schemaoptional
requiredBooloptional
descriptionStringoptional
constraintsArray[@schema.Constraint]optional
defaultJsonoptional
alias_Stringoptional
examplesMap[String, Example]optional

Returns Self

function
pub fn Param::not_equal(Self, Self) -> Bool

Returns Bool

Methods on ParamLoc

function
pub fn ParamLoc::equal(Self, Self) -> Bool

Returns Bool

function
pub fn ParamLoc::not_equal(Self, Self) -> Bool

Returns Bool

Methods on ResponseSpec

function
pub fn ResponseSpec::equal(Self, Self) -> Bool

Returns Bool

function
pub fn ResponseSpec::new(Int32, description? : String, body? : @schema.Schema, examples? : Map[String, Example]) -> Self

Build a response descriptor. description defaults to "OK" and there is no body unless one is given.

ParameterTypeDefault
type onlyInt32required
descriptionStringoptional
body@schema.Schemaoptional
examplesMap[String, Example]optional

Returns Self

function
pub fn ResponseSpec::not_equal(Self, Self) -> Bool

Returns Bool

@exceptions

HTTP exceptions and the error types the framework raises and renders.

Types

type
pub type ExceptionHandler = (@ctx.Context, Error) -> @http.Response?

An exception handler: given the request context and the raised error, return Some(response) to handle it or None to defer to the next handler. The explicit MoonBit form of @app.exception_handler(ExcType) — the None case stands in for "this handler isn't registered for that type".

Functions

function
pub fn http_error(Int32, String, headers? : Array[(String, String)]) -> HttpException

Build an HttpException with a string detail — the common case — and optional extra headers. raise http_error(404, "Item not found") reads like raise HTTPException(404, "Item not found").

ParameterTypeDefault
type onlyInt32required
type onlyStringrequired
headersArray[(String, String)]optional

Returns HttpException

@openapi

The OpenAPI document model and the bundled documentation UIs.

Constants & values

value
pub let redoc_js : String
value
pub let scalar_js : String
value
pub let swagger_css : String
value
pub let swagger_js : String

The pages load their readers from a CDN at an exact version, so a page does not change under an application that did not change. Self-hosting is a matter of passing other URLs.

value
pub let swagger_redirect_js : String

Functions

function
pub fn redoc_ui(spec_url? : String, title? : String, js_url? : String, telemetry? : Bool) -> String

A ReDoc page rendering the document served at spec_url get_redoc_html): three panels, built for reading rather than for trying calls out. ReDoc reports usage to its maker unless told not to; telemetry is off unless turned on, since the page is served to this API's readers.

ParameterTypeDefault
spec_urlStringoptional
titleStringoptional
js_urlStringoptional
telemetryBooloptional

Returns String

function
pub fn scalar_ui(spec_url? : String, title? : String, js_url? : String, extra? : Map[String, Json]) -> String

A Scalar API reference rendering the document served at spec_url: the reference and a request client on one page. extra is merged over the configuration passed to Scalar.createApiReference, which is where its theme, layout and authentication defaults go.

ParameterTypeDefault
spec_urlStringoptional
titleStringoptional
js_urlStringoptional
extraMap[String, Json]optional

Returns String

function
pub fn swagger_redirect(js_url? : String) -> String

The page an OAuth2 authorisation started from Swagger UI returns to: it hands the code or token back to the window that opened it get_swagger_ui_oauth2_redirect_html).

ParameterTypeDefault
js_urlStringoptional

Returns String

function
pub fn swagger_ui(spec_url? : String, title? : String, js_url? : String, css_url? : String, oauth2_redirect_url? : String, init_oauth? : Json, extra? : Map[String, Json]) -> String

A Swagger UI page rendering the document served at spec_url get_swagger_ui_html). oauth2_redirect_url is the page an OAuth2 flow returns to, served by swagger_redirect; init_oauth is handed to initOAuth to prefill the client id, scopes and the like; extra is merged over the settings passed to Swagger UI .

ParameterTypeDefault
spec_urlStringoptional
titleStringoptional
js_urlStringoptional
css_urlStringoptional
oauth2_redirect_urlStringoptional
init_oauthJsonoptional
extraMap[String, Json]optional

Returns String

Methods on ApiInfo

function
pub fn ApiInfo::new() -> Self

The defaults an app starts with.

Returns Self

Methods on Contact

function
pub fn Contact::new(name? : String, url? : String, email? : String) -> Self
ParameterTypeDefault
nameStringoptional
urlStringoptional
emailStringoptional

Returns Self

Methods on ExternalDocs

function
pub fn ExternalDocs::new(String, description? : String) -> Self
ParameterTypeDefault
type onlyStringrequired
descriptionStringoptional

Returns Self

function
pub fn ExternalDocs::to_json(Self) -> Json

The externalDocs object for docs, the same in every dialect.

Returns Json

Methods on License

function
pub fn License::new(String, url? : String, identifier? : String) -> Self
ParameterTypeDefault
type onlyStringrequired
urlStringoptional
identifierStringoptional

Returns Self

Methods on Server

function
pub fn Server::new(String, description? : String) -> Self
ParameterTypeDefault
type onlyStringrequired
descriptionStringoptional

Returns Self

Methods on Tag

function
pub fn Tag::new(String, description? : String, external_docs? : ExternalDocs) -> Self
ParameterTypeDefault
type onlyStringrequired
descriptionStringoptional
external_docsExternalDocsoptional

Returns Self

function
pub fn Tag::to_json(Self) -> Json

The tag object, the same in every dialect.

Returns Json

Methods on Ui

function
pub fn Ui::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Ui::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Ui::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

@route

Routers, route tables, class-based views, and mounting sub-applications.

Types

type
pub type ApiHandler = async (@ctx.Context) -> @http.Response

A route handler : the request context in, a response out. It runs async, so it can await a database or another service; a plain closure is one too, and a named function that is not async is registered as ctx => f(ctx). It may raise an HttpException (or any error) instead of returning — the app maps it to a response through the registered exception handlers.

type
pub type Hoop = async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply

A middleware on a route or on a router node : the request context and the rest of the route in, the reply out. It runs inside the app's own middleware and outside the route's security, validation and dependencies, so it can answer for the route — refuse, redirect, serve from a cache — or change what the route produced, and it can hand next a context of its own.

re-export
pub using @method {type Method}

The request method a route binds to: the nine standard ones and any other token, from moonhttp.

struct
pub struct Router { routes : Array[Route] ws_routes : Array[WsRoute] hoops : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply] }

A collection of routes built away from any application and folded into one with App::include_router . It carries the registration surface of an App and nothing else: middleware, mounts, security schemes, documentation and lifespan belong to the application that includes it.

FieldType
routesArray[Route]
ws_routesArray[WsRoute]
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]
type
pub type StreamHandler = async (@ctx.Context) -> @status.Stream

A streaming route's handler : the response it returns writes its body while it is sent.

type
pub type Url = (Router) -> Unit

One entry of a route table: what it registers, given the router it lands on. path, view, websocket and group make them.

trait
pub(open) trait View { fn get(Self) -> (async (@ctx.Context) -> @http.Response)? = _ fn head(Self) -> (async (@ctx.Context) -> @http.Response)? = _ fn post(Self) -> (async (@ctx.Context) -> @http.Response)? = _ fn put(Self) -> (async (@ctx.Context) -> @http.Response)? = _ fn patch(Self) -> (async (@ctx.Context) -> @http.Response)? = _ fn delete(Self) -> (async (@ctx.Context) -> @http.Response)? = _ fn options(Self) -> (async (@ctx.Context) -> @http.Response)? = _ fn trace(Self) -> (async (@ctx.Context) -> @http.Response)? = _ }

A type answering the methods of one path . Implement the methods it answers, each giving back its handler; the rest answer None, and a request for one of those gets a 405 whose Allow lists what the view does answer.

struct Articles { db : Db }

impl @moonapi.View for Articles with get(self) {
  Some(ctx => self.db.list(ctx))
}

impl @moonapi.View for Articles with post(self) {
  Some(ctx => self.db.create(ctx))
}

app.view("/articles", Articles::{ db })

Functions

function
pub fn group(String, Array[(Router) -> Unit], tags? : Array[String], security? : Array[@security.SecurityRequirement], dependencies? : Array[String], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> (Router) -> Unit

urls under prefix reserved word). The arguments reach every route of the group as Router::include_router describes, and a group may hold groups.

ParameterTypeDefault
type onlyStringrequired
type onlyArray[(Router) -> Unit]required
tagsArray[String]optional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns (Router) -> Unit

function
pub fn join_prefix(String, String) -> String

A route path under prefix, written as writes it: the prefix with its trailing slashes dropped, then the path as given, so ("/sub", "/items/") is /sub/items/ and ("/sub", "/") is /sub/. A path keeps its own trailing slash because a trailing slash is part of what a route matches.

ParameterTypeDefault
type onlyStringrequired
type onlyStringrequired

Returns String

function
pub fn path(String, async (@ctx.Context) -> @http.Response, methods? : Array[@method.Method], name? : String) -> (Router) -> Unit

handler at path for each of methods default is the same GET, which answers HEAD too).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
methodsArray[@method.Method]optional
nameStringoptional

Returns (Router) -> Unit

function
pub fn segments(String) -> Array[String]

Split a path into its non-empty segments.

ParameterTypeDefault
type onlyStringrequired

Returns Array[String]

function
pub fn view(String, &View, name? : String) -> (Router) -> Unit

The methods view answers at path.

ParameterTypeDefault
type onlyStringrequired
type only&Viewrequired
nameStringoptional

Returns (Router) -> Unit

function
pub fn websocket(String, async (@socket.WebSocket) -> Unit, name? : String) -> (Router) -> Unit

A WebSocket route at path .

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@socket.WebSocket) -> Unitrequired
nameStringoptional

Returns (Router) -> Unit

Methods on Convertor

function
pub fn Convertor::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Convertor::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Convertor::of(StringView) -> Self?

The convertor named name, as a template spells it after the colon.

ParameterTypeDefault
type onlyStringViewrequired

Returns Self?

function
pub fn Convertor::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

Methods on Pattern

function
pub fn Pattern::bind(Self, StringView) -> Map[String, String]?

The parameters path binds, or None when it does not match. The whole path must match: a trailing slash is a different path.

ParameterTypeDefault
type onlyStringViewrequired

Returns Map[String, String]?

function
pub fn Pattern::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Pattern::fill(Self, Map[String, String]) -> String?

The path with params substituted ; None when one is missing or does not fit its convertor.

ParameterTypeDefault
type onlyMap[String, String]required

Returns String?

function
pub fn Pattern::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Pattern::params(Self) -> Array[(String, Convertor)]

The parameters in the order the path names them.

Returns Array[(String, Convertor)]

function
pub fn Pattern::parse(String) -> Self

Read path as a template. An unclosed brace, an empty name, an unknown convertor or two parameters with nothing between them is a mistake in the program, not in a request, so it aborts at registration — the way refuses such a route when the application starts.

ParameterTypeDefault
type onlyStringrequired

Returns Self

function
pub fn Pattern::template(Self) -> String

The path as an OpenAPI template expression: every parameter as {name}, the convertor left to the parameter's schema.

Returns String

function
pub fn Pattern::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

Methods on Piece

function
pub fn Piece::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Piece::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Piece::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

Methods on Router

function
pub fn Router::delete(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a DELETE route. A shorthand for route(Delete, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::get(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a GET route. A shorthand for route(Get, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::head(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a HEAD route. A shorthand for route(Head, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::hoop(Self, async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply) -> Unit

Put hoop around every route of this router . The router's hoops reach its routes when it is included, outside each route's own, in the order they were added.

ParameterTypeDefault
type onlyasync (@ctx.Context, async (@ctx.Context) -> Reply) -> Replyrequired

Returns Unit

function
pub fn Router::include_router(Self, Self, prefix? : String, tags? : Array[String], security? : Array[@security.SecurityRequirement], dependencies? : Array[String], responses? : Array[@endpoint.ResponseSpec], deprecated? : Bool, include_in_schema? : Bool, hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Fold router's routes into this one under prefix APIRouter.include_router), so routers nest into a tree and the tree is included into an app once. The arguments reach every route folded in:

- tags, security, dependencies and hoops are placed before the route's own, so a group's tag leads and a group-wide requirement, dependency or hoop cannot be dropped by a route that adds one of its own; router's own hoops come between the two; - responses are documented under the route's, which therefore wins any status both name; - deprecated marks the whole group, and include_in_schema=false hides it, neither of which a route can undo.

WebSocket routes take the prefix, the security and the dependencies.

ParameterTypeDefault
prefixStringoptional
tagsArray[String]optional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
responsesArray[@endpoint.ResponseSpec]optional
deprecatedBooloptional
include_in_schemaBooloptional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::new() -> Self

An empty router. The prefix and the attributes its routes share are given at include_router rather than here, so one router can be included twice — under a second prefix, or on another app with different tags.

Returns Self

function
pub fn Router::options(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a OPTIONS route. A shorthand for route(Options, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::patch(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a PATCH route. A shorthand for route(Patch, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::post(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a POST route. A shorthand for route(Post, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::put(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a PUT route. A shorthand for route(Put, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::route(Self, @method.Method, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a route on the router for an explicit method. An optional endpoint descriptor makes the route fully typed (its parameters, request body, and responses surface in the OpenAPI document and drive validation); security attaches per-operation requirements (emitted as OpenAPI security and enforced before the handler when their scheme has an enforcer); dependencies names provider keys resolved through the app's container (App::depends) before the handler and torn down after it, whatever the handler did.

The rest describe the operation: summary and description are its prose, operation_id the stable handle client generators name their method after, status_code the status its success response is documented under, responses further documented responses, name the handle App::url_for resolves, openapi_extra a fragment merged over the generated operation object, and callbacks the requests this operation makes back to its caller, written as routes whose paths are runtime expressions — the same keyword arguments path operations take. hoops wrap this one route, inside any its routers put around it.

ParameterTypeDefault
type only@method.Methodrequired
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::route_stream(Self, @method.Method, String, async (@ctx.Context) -> @status.Stream, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a streaming route StreamingResponse). The handler's chunks reach the client as separate body events, so a long or open-ended reply starts arriving before it is finished.

A stream is only streamed as far as the app can honestly keep it one: a middleware that rewrites the body — gzip does — collapses the reply to a single chunk. Everything else about the route is ordinary; it documents, validates and enforces security exactly as route does.

ParameterTypeDefault
type only@method.Methodrequired
type onlyStringrequired
type onlyasync (@ctx.Context) -> @status.Streamrequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::stream(Self, String, async (@ctx.Context) -> @status.Stream, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a streaming GET route — the verb a stream is nearly always read over, and what an SSE endpoint is. A shorthand for route_stream(Get, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @status.Streamrequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::trace(Self, String, async (@ctx.Context) -> @http.Response, summary? : String, description? : String, tags? : Array[String], deprecated? : Bool, operation_id? : String, status_code? : Int32, responses? : Array[@endpoint.ResponseSpec], name? : String, endpoint? : @endpoint.Endpoint, security? : Array[@security.SecurityRequirement], dependencies? : Array[String], include_in_schema? : Bool, validate? : Bool, openapi_extra? : Json, callbacks? : Array[Route], hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register a TRACE route. A shorthand for route(Trace, ...).

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@ctx.Context) -> @http.Responserequired
summaryStringoptional
descriptionStringoptional
tagsArray[String]optional
deprecatedBooloptional
operation_idStringoptional
status_codeInt32optional
responsesArray[@endpoint.ResponseSpec]optional
nameStringoptional
endpoint@endpoint.Endpointoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
include_in_schemaBooloptional
validateBooloptional
openapi_extraJsonoptional
callbacksArray[Route]optional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::urls(Self, Array[(Self) -> Unit]) -> Unit

Register every entry of urls, in order — the order a request tries them in.

ParameterTypeDefault
type onlyArray[(Self) -> Unit]required

Returns Unit

function
pub fn Router::view(Self, String, &View, name? : String, tags? : Array[String], security? : Array[@security.SecurityRequirement], dependencies? : Array[String], deprecated? : Bool, include_in_schema? : Bool, hoops? : Array[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]) -> Unit

Register the methods view answers at path, each as its own route sharing the arguments given here. A view that answers no method is a mistake in the program and aborts.

ParameterTypeDefault
type onlyStringrequired
type only&Viewrequired
nameStringoptional
tagsArray[String]optional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional
deprecatedBooloptional
include_in_schemaBooloptional
hoopsArray[async (@ctx.Context, async (@ctx.Context) -> Reply) -> Reply]optional

Returns Unit

function
pub fn Router::websocket(Self, String, async (@socket.WebSocket) -> Unit, name? : String, security? : Array[@security.SecurityRequirement], dependencies? : Array[String]) -> Unit

Register a WebSocket route on the router . It takes the including prefix like any other route. security and dependencies are checked before the handler runs, as on an HTTP route, and a refusal declines the handshake; name is the handle App::url_for resolves. The OpenAPI attributes do not apply, since a WebSocket route is not an operation.

ParameterTypeDefault
type onlyStringrequired
type onlyasync (@socket.WebSocket) -> Unitrequired
nameStringoptional
securityArray[@security.SecurityRequirement]optional
dependenciesArray[String]optional

Returns Unit

@schema

JSON Schema types, constraints, and validation used for bodies and documents.

Types

trait
pub(open) trait ToSchema { fn to_schema(Self) -> Schema }

The impl-able version of a type's descriptor. A user struct implements it — the value is ignored; it exists so descriptor-carrying code can be generic over "a type that knows its own schema". The primary, mctl-friendly shape is still a plain associated function T::schema() -> Schema (no instance needed, mirroring referencing the model *class*); this trait bridges to it.

Constants & values

value
pub let query_limits : @moonurl.Limits

How much of a query string is a query string.

A thousand parameters is what qs allows by default, and far past anything a link carries; sixty-four kilobytes for one value is well past the eight the common servers allow a whole request line. Beyond either, the request is an attempt to make the server allocate.

An endpoint that genuinely takes more says so: ctx.query("tag", limits=@moonurl.Limits::new(pairs=100000)).

Functions

function
pub fn check_constraints(Json, Array[Constraint], Array[String], Array[ValidationError]) -> Unit

Enforce the constraints on an inbound value, appending a Pydantic-shaped ValidationError (located at loc) for each violation. A constraint that does not apply to the value's kind (a length bound on a number, say) is simply skipped, as pydantic does.

ParameterTypeDefault
type onlyJsonrequired
type onlyArray[Constraint]required
type onlyArray[String]required
type onlyArray[ValidationError]required

Returns Unit

function
pub fn emit_schema(Schema, Map[String, Json], OpenApiVersion) -> Json

Emit schema as inline OpenAPI JSON, hoisting every *named* object into defs (keyed by name) and referencing it by $ref. Recursion-safe: a name is reserved in defs before its body is built, so a self-referential schema terminates instead of looping.

ParameterTypeDefault
type onlySchemarequired
type onlyMap[String, Json]required
type onlyOpenApiVersionrequired

Returns Json

function
pub fn enum_expected(Array[Json]) -> String

The Pydantic-style "expected one of" fragment for an enum error: string members quoted, comma-separated, with a final or before the last.

ParameterTypeDefault
type onlyArray[Json]required

Returns String

function
pub fn enum_member(Array[Json], Json) -> Bool

Whether v is one of the allowed enum values.

ParameterTypeDefault
type onlyArray[Json]required
type onlyJsonrequired

Returns Bool

function
pub fn filter_response(Schema, Json) -> Result[Json, Array[ValidationError]]

Validate value against model and, if it conforms, return it filtered down to the model's declared fields (extras dropped, nested objects and arrays projected too). On a mismatch return the located ValidationErrors under ["response"] — the same shape request validation produces. This is response_model: the outgoing shape is the model, not whatever the handler happened to build.

ParameterTypeDefault
type onlySchemarequired
type onlyJsonrequired

Returns Result[Json, Array[ValidationError]]

function
pub fn json_model(Int32, Schema, Json) -> @http.Response

A JSON response whose body is value filtered through model. On success a status response carrying only the model's declared fields; on a model mismatch a 500 whose body lists the response-validation errors — the return value didn't match what the route promised, which is a server-side fault.

ParameterTypeDefault
type onlyInt32required
type onlySchemarequired
type onlyJsonrequired

Returns @http.Response

function
pub fn parse_int(String) -> Int32?

Parse a base-10 integer, None if s is not a well-formed integer literal (optional leading +/-, then one or more ASCII digits, nothing else).

Not core's @strconv.parse_int: that one also takes 0x prefixes and underscores, which a query or path parameter must not quietly accept.

ParameterTypeDefault
type onlyStringrequired

Returns Int32?

function
pub fn unprocessable(Array[ValidationError]) -> @http.Response

A 422 Unprocessable Entity response whose application/json body lists the validation errors, exactly as reports a failed request.

ParameterTypeDefault
type onlyArray[ValidationError]required

Returns @http.Response

function
pub fn validate_schema(Schema, Json, Array[String], Array[ValidationError]) -> Unit

Validate a JSON value against the descriptor schema, appending -shaped errors to errs (located at loc). This is what "the descriptor drives validation" means: the very tree that emits the OpenAPI body schema also decides whether an inbound body conforms — one source of truth, exactly as pydantic derives both from one model. A named object is validated against its inline fields, so no $ref resolution is needed here.

ParameterTypeDefault
type onlySchemarequired
type onlyJsonrequired
type onlyArray[String]required
type onlyArray[ValidationError]required

Returns Unit

function
pub fn validation_error_body(Array[ValidationError]) -> Json

The {"detail": [ ... ]} body returns when request validation fails, built from a list of ValidationErrors.

ParameterTypeDefault
type onlyArray[ValidationError]required

Returns Json

function
pub fn with_constraints(Json, Array[Constraint], OpenApiVersion) -> Json

Merge the constraints into a scalar/array schema object for OpenAPI emission. exclusiveMinimum / exclusiveMaximum are numeric under OpenAPI 3.1 (JSON-Schema 2020-12) but a boolean flag alongside minimum / maximum under Swagger 2.0 and OpenAPI 3.0, so the form is version-aware.

ParameterTypeDefault
type onlyJsonrequired
type onlyArray[Constraint]required
type onlyOpenApiVersionrequired

Returns Json

function
pub fn with_description(Json, String) -> Json

Return j with a description sibling added (legal beside $ref in OpenAPI 3.1 / JSON-Schema 2020-12).

ParameterTypeDefault
type onlyJsonrequired
type onlyStringrequired

Returns Json

function
pub fn with_key(Json, String, Json) -> Json

Return j with key set to value. Builds a fresh object so nothing shared mutates; a non-object is returned untouched, since there is nothing to set on it.

ParameterTypeDefault
type onlyJsonrequired
type onlyStringrequired
type onlyJsonrequired

Returns Json

Methods on Constraint

function
pub fn Constraint::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Constraint::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Constraint::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

Methods on Field

function
pub fn Field::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Field::is_required(Self) -> Bool

Whether a body must carry this field. A field with a default never must — its absence is answered by the default, exactly as a Python default argument is, so it is left out of the emitted required list and not reported missing.

Returns Bool

function
pub fn Field::new(String, Schema, required? : Bool, description? : String, constraints? : Array[Constraint], default? : Json, examples? : Array[Json]) -> Self

Build a field. required defaults to true ( treats a field without a default as required). constraints are the Pydantic-style value constraints (ge/le/min_length/pattern/…) that are both emitted into the field's OpenAPI schema and enforced when validating an inbound value. default is emitted into the schema and makes the field optional, since a value that has one is never missing.

ParameterTypeDefault
type onlyStringrequired
type onlySchemarequired
requiredBooloptional
descriptionStringoptional
constraintsArray[Constraint]optional
defaultJsonoptional
examplesArray[Json]optional

Returns Self

function
pub fn Field::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Field::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

Methods on ObjectSchema

function
pub fn ObjectSchema::equal(Self, Self) -> Bool

Returns Bool

function
pub fn ObjectSchema::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn ObjectSchema::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

Methods on OpenApiVersion

function
pub fn OpenApiVersion::equal(Self, Self) -> Bool

Returns Bool

function
pub fn OpenApiVersion::not_equal(Self, Self) -> Bool

Returns Bool

Methods on Schema

function
pub fn Schema::array(Self) -> Self

An array schema whose elements all conform to item.

Returns Self

function
pub fn Schema::binary() -> Self

The schema of file content: a string with OpenAPI's binary format — what an upload is described as, and what a multipart file field carries.

Returns Self

function
pub fn Schema::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Schema::format(Self, String) -> Self

base refined by an OpenAPI format. The format is documentation: it tells a reader and a client generator what the string holds, and validation still checks only base, which is what pydantic does for a format it has no validator for.

ParameterTypeDefault
type onlyStringrequired

Returns Self

function
pub fn Schema::json(Json) -> Self

A schema written as JSON Schema itself (2020-12, which is what OpenAPI 3.1 is). Use it for what the other constructors cannot say; it goes into the document unchanged.

ParameterTypeDefault
type onlyJsonrequired

Returns Self

function
pub fn Schema::map(Self) -> Self

An object with no declared fields whose values all conform to value . Schema::map(SAny) is the free-form object.

Returns Self

function
pub fn Schema::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Schema::nullable(Self) -> Self

A schema that also admits null . Wrapping rather than a flag because the three dialects express it three different ways.

Returns Self

function
pub fn Schema::object(String, Array[Field]) -> Self

A named object schema: hoisted to components/schemas under name and referenced by $ref wherever it is used.

ParameterTypeDefault
type onlyStringrequired
type onlyArray[Field]required

Returns Self

function
pub fn Schema::of_model(@moonmodel.Model, known? : Array[@moonmodel.Model]) -> (Self, Array[Unresolved])

A moonmodel description as a schema.

One description, written once, drives request validation and the OpenAPI document here, and the DDL and the SDL in their own libraries. known is where a Ref is looked up: a reference to a model that is not in it, or one that leads back to a model already being written, is reported instead — a schema is a finite value, so a cycle cannot be written out, and the name alone does not say what the thing looks like.

ParameterTypeDefault
type only@moonmodel.Modelrequired
knownArray[@moonmodel.Model]optional

Returns (Self, Array[Unresolved])

function
pub fn Schema::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

Methods on Unresolved

function
pub fn Unresolved::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Unresolved::not_equal(Self, Self) -> Bool

Returns Bool

Methods on ValidationError

function
pub fn ValidationError::missing(Array[String]) -> Self

The canonical "a required parameter was not supplied" error located at loc, matching {"type": "missing", "msg": "Field required"}.

ParameterTypeDefault
type onlyArray[String]required

Returns Self

function
pub fn ValidationError::to_json(Self) -> Json

Render one validation error as its JSON object.

Returns Json

function
pub fn ValidationError::type_error(Array[String], String, String) -> Self

A type/parse error located at loc, e.g. kind = "int_parsing" with the matching pydantic message — the shape reports for a value of the wrong type.

ParameterTypeDefault
type onlyArray[String]required
type onlyStringrequired
type onlyStringrequired

Returns Self

@security

Authentication schemes, security requirements, and their runtime enforcers.

Types

struct
pub struct ApiKey { loc : ApiKeyIn name : String verify : (String) -> Bool }

An API-key scheme: the parameter name the key arrives under, where it arrives, and the predicate that accepts a presented key. APIKeyHeader only extracts and leaves the check to a dependency; a route guard needs both, so the check travels with the scheme.

FieldType
locApiKeyIn
nameString
verify(String) -> Bool
struct
pub struct BasicAuth { realm : String verify : (@ctx.HttpBasicCredentials) -> Bool }

An HTTP Basic scheme : the realm named in the challenge, and the predicate that accepts a presented username/password.

FieldType
realmString
verify(@ctx.HttpBasicCredentials) -> Bool
struct
pub struct DigestAuth { realm : String verify : (String) -> Bool }

An HTTP Digest scheme credential and no more): verify decides whether the Digest parameter string a client sent is acceptable. Computing the RFC 7616 response digest is the application's, since only it holds the password store.

FieldType
realmString
verify(String) -> Bool
struct
pub struct OAuth2CodeBearer { authorization_url : String token_url : String refresh_url : String secret : String }

An OAuth2 authorization-code bearer scheme OAuth2AuthorizationCodeBearer): the authorization_url a browser is sent to, the token_url the code is exchanged at, an optional refresh_url, and the shared HS256 secret a presented token is verified against.

FieldType
authorization_urlString
token_urlString
refresh_urlString
secretString
type
pub type SecurityEnforcer = (@ctx.Context, SecurityScopes, Int64) -> Result[AuthenticatedUser, @http.Response]

The runtime guard behind a named scheme: given the request context, the scopes the route required at this call site, and the verification time (Unix seconds), either the authenticated user or the 401/403 response to return. Registered by the App::secure_* functions; a documentation-only scheme (a bare add_security_scheme) has none, so it is described in the spec but not enforced — exactly split between a declared scheme and a wired dependency.

struct
pub struct SecurityScopes { scopes : Array[String] }

The scopes a route required at the point its security guard runs SecurityScopes). A guard reads them to check what the caller was granted and to build the WWW-Authenticate challenge a 401 owes the client.

FieldType
scopesArray[String]

Functions

function
pub fn anonymous() -> AuthenticatedUser

The caller an auto_error=false guard admits: no subject, no scopes, no claims. auto_error=False hands the route None and lets it decide; the route here sees a caller it knows nothing about.

Returns AuthenticatedUser

function
pub fn create_access_token(String, String, Int64, scopes? : Array[String], expires_in_secs? : Int64, extra? : Map[String, Json], wins? : @jwt.Wins, clash? : @jwt.OnClash[Map[String, Json]]) -> String

Mint an HS256 access token for subject . Stamps sub, iat (= now_secs), exp (= now_secs + expires_in_secs), and, when non-empty, scopes; extra merges in any further claims. Times are Unix seconds. secret is the shared HS256 key.

extra adds claims. Where it names one the arguments already set — sub, iat, exp, scopes — the arguments win and saying it twice aborts, because a token whose subject is not the subject passed in is a mistake in the program rather than a choice about configuration. wins=Extra hands the decision to extra, and clash can silence it or take a callback.

ParameterTypeDefault
type onlyStringrequired
type onlyStringrequired
type onlyInt64required
scopesArray[String]optional
expires_in_secsInt64optional
extraMap[String, Json]optional
wins@jwt.Winsoptional
clash@jwt.OnClash[Map[String, Json]]optional

Returns String

function
pub fn forbidden(String) -> @http.Response

A 403 Forbidden with a {"detail": ...} body — returned when the token is valid but lacks a required scope. The token authenticated the caller, so this is authorization, not authentication: 403, not 401.

ParameterTypeDefault
type onlyStringrequired

Returns @http.Response

function
pub fn hs256(String) -> @jwt.Keyed

The HS256 key a shared secret stands for.

This is the whole of moonapi's relationship with cryptography: it names an algorithm and hands mooncred something that can sign. Nothing here knows what SHA-256 is, and a deployment that wants ES256 passes its own signer to mooncred without moonapi being involved.

ParameterTypeDefault
type onlyStringrequired

Returns @jwt.Keyed

function
pub fn refuse(Bool, () -> @http.Response) -> Result[AuthenticatedUser, @http.Response]

Admit an unauthenticated caller, or refuse with denied — the one place auto_error is decided, so every guard reads the flag the same way.

ParameterTypeDefault
type onlyBoolrequired
type only() -> @http.Responserequired

Returns Result[AuthenticatedUser, @http.Response]

function
pub fn token_response(String) -> @http.Response

The 200 token response body {"access_token": ..., "token_type": "bearer"} — the OAuth2 password-grant reply token endpoint returns.

ParameterTypeDefault
type onlyStringrequired

Returns @http.Response

function
pub fn unauthorized(String, challenge? : String) -> @http.Response

A 401 Unauthorized with a WWW-Authenticate challenge and a {"detail": ...} body — response for a missing or invalid credential. RFC 9110 §15.5.2 requires the challenge, so it is a parameter: Basic realm="…" for Basic, Bearer scope="…" for a scoped bearer route.

ParameterTypeDefault
type onlyStringrequired
challengeStringoptional

Returns @http.Response

function
pub fn verify_bearer(@ctx.Context, String, SecurityScopes, Int64, Bool) -> Result[AuthenticatedUser, @http.Response]

The guard every JWT-verified scheme shares — the OAuth2 password and authorization-code flows, a plain HTTP bearer, and OpenID Connect all present the same Authorization: Bearer <jwt> credential. Pulls the token, verifies it against secret at now, then checks the scopes the route required.

ParameterTypeDefault
type only@ctx.Contextrequired
type onlyStringrequired
type onlySecurityScopesrequired
type onlyInt64required
type onlyBoolrequired

Returns Result[AuthenticatedUser, @http.Response]

Methods on ApiKey

function
pub fn ApiKey::header(String, (String) -> Bool) -> Self

An API key read from the request header name .

ParameterTypeDefault
type onlyStringrequired
type only(String) -> Boolrequired

Returns Self

function
pub fn ApiKey::query(String, (String) -> Bool) -> Self

An API key read from the query parameter name .

ParameterTypeDefault
type onlyStringrequired
type only(String) -> Boolrequired

Returns Self

function
pub fn ApiKey::read(Self, @ctx.Context) -> String?

The key this request presents for the scheme, None when it carries none.

ParameterTypeDefault
type only@ctx.Contextrequired

Returns String?

function
pub fn ApiKey::scheme(Self) -> SecurityScheme

The apiKey scheme object this key is documented as.

Returns SecurityScheme

Methods on ApiKeyIn

function
pub fn ApiKeyIn::equal(Self, Self) -> Bool

Returns Bool

function
pub fn ApiKeyIn::not_equal(Self, Self) -> Bool

Returns Bool

Methods on AuthenticatedUser

function
pub fn AuthenticatedUser::has_scope(Self, String) -> Bool

Whether this user was granted scope.

ParameterTypeDefault
type onlyStringrequired

Returns Bool

Methods on BasicAuth

function
pub fn BasicAuth::challenge(Self) -> String

The WWW-Authenticate value this scheme challenges with.

Returns String

function
pub fn BasicAuth::new((@ctx.HttpBasicCredentials) -> Bool, realm? : String) -> Self

Build an HTTP Basic scheme. A realm is optional and, when given, names the protection space in the challenge so a browser can tell one login from another.

ParameterTypeDefault
type only(@ctx.HttpBasicCredentials) -> Boolrequired
realmStringoptional

Returns Self

Methods on DigestAuth

function
pub fn DigestAuth::challenge(Self) -> String

The WWW-Authenticate value this scheme challenges with.

Returns String

function
pub fn DigestAuth::new((String) -> Bool, realm? : String) -> Self

Build an HTTP Digest scheme, optionally naming the protection realm.

ParameterTypeDefault
type only(String) -> Boolrequired
realmStringoptional

Returns Self

Methods on OAuth2CodeBearer

function
pub fn OAuth2CodeBearer::new(String, String, String, refresh_url? : String) -> Self

Build an authorization-code bearer scheme. refresh_url is left out of the document when empty, since a provider that offers no refresh endpoint should not be described as having one.

ParameterTypeDefault
type onlyStringrequired
type onlyStringrequired
type onlyStringrequired
refresh_urlStringoptional

Returns Self

function
pub fn OAuth2CodeBearer::scheme(Self, scopes? : Array[(String, String)]) -> SecurityScheme

The security scheme that describes this flow, advertising scopes.

ParameterTypeDefault
scopesArray[(String, String)]optional

Returns SecurityScheme

Methods on OAuth2PasswordBearer

function
pub fn OAuth2PasswordBearer::authenticate(Self, @ctx.Context, Int64, scopes? : Array[String]) -> Result[AuthenticatedUser, @http.Response]

Authenticate a request against this scheme and enforce scopes . On success returns the AuthenticatedUser; otherwise the response to return:

- no bearer token -> 401 {"detail":"Not authenticated"} - malformed / bad-signature / expired / not-yet-valid token -> 401 {"detail":"Could not validate credentials"} - valid token missing a required scope -> 403 {"detail":"Not enough permissions"}

Both 401s carry the challenge the required scopes describe — Bearer on its own, or Bearer scope="..." — so a client learns what it should have asked for.

now_secs is the verification time (Unix seconds), passed in so the check stays pure and testable on every backend.

ParameterTypeDefault
type only@ctx.Contextrequired
type onlyInt64required
scopesArray[String]optional

Returns Result[AuthenticatedUser, @http.Response]

function
pub fn OAuth2PasswordBearer::new(String, String) -> Self

Build a password-bearer scheme pointing at the token endpoint at token_url, verifying tokens with secret.

ParameterTypeDefault
type onlyStringrequired
type onlyStringrequired

Returns Self

function
pub fn OAuth2PasswordBearer::scheme(Self, scopes? : Array[(String, String)]) -> SecurityScheme

Build the security scheme that describes this password-bearer flow object derives from OAuth2PasswordBearer). scopes are the (name, description) pairs advertised in the OpenAPI document.

ParameterTypeDefault
scopesArray[(String, String)]optional

Returns SecurityScheme

Methods on SecurityRequirement

function
pub fn SecurityRequirement::equal(Self, Self) -> Bool

Returns Bool

function
pub fn SecurityRequirement::new(String, scopes? : Array[String]) -> Self

Require scheme with the given scopes (default: none — authentication with no scope check). App::get(..., security=[SecurityRequirement::new("OAuth2", scopes=["items"])]) reads like Security(oauth2, scopes=["items"]).

ParameterTypeDefault
type onlyStringrequired
scopesArray[String]optional

Returns Self

function
pub fn SecurityRequirement::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn SecurityRequirement::to_json(Self) -> Json

This requirement as its OpenAPI security entry: {scheme: [scope, ...]}.

Returns Json

Methods on SecurityScheme

function
pub fn SecurityScheme::to_openapi_20(Self) -> Json?

This scheme as a Swagger 2.0 security definition, or None when 2.0 cannot express it. Swagger 2.0 has no http type: an HTTP bearer or digest is expressed as an apiKey in the Authorization header (the standard 2.0 workaround), Basic uses the basic type, and OAuth2 flows are the flat 2.0 form (flow + URLs at top level, accessCode being 2.0's name for the authorization-code flow). Swagger 2.0 apiKey only allows header/query, so a cookie key maps to a header. OpenID Connect has no 2.0 equivalent at all, and inventing one would describe an API that does not exist — so it is left out of the 2.0 document.

Returns Json?

function
pub fn SecurityScheme::to_openapi_3x(Self) -> Json

This scheme as an OpenAPI 3.0 / 3.1 security scheme object.

Returns Json

Methods on SecurityScopes

function
pub fn SecurityScopes::challenge(Self) -> String

The WWW-Authenticate value a bearer challenge carries: Bearer on its own, or Bearer scope="a b" when the route requires scopes, which is how RFC 6750 §3 tells a client what it was missing.

Returns String

function
pub fn SecurityScopes::list(Self) -> Array[String]

The required scopes, in declaration order.

Returns Array[String]

function
pub fn SecurityScopes::new(scopes? : Array[String]) -> Self

The scopes required at one call site; empty means authentication only.

ParameterTypeDefault
scopesArray[String]optional

Returns Self

function
pub fn SecurityScopes::scope_str(Self) -> String

The scopes as OAuth2's single space-delimited string .

Returns String

@socket

WebSocket connections, messages, and lifecycle handling.

Types

struct
pub struct WebSocket { scope : @spec.WebSocketScope params : Map[String, String] // private fields }

A WebSocket connection as a handler sees it.

FieldType
scope@spec.WebSocketScope
paramsMap[String, String]
type
pub type WsHandler = async (WebSocket) -> Unit

A WebSocket route's handler .

Methods on Disconnected

function
pub fn Disconnected::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Disconnected::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn Disconnected::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

Methods on WebSocket

function
pub async fn WebSocket::accept(Self, subprotocol? : String, headers? : Array[(String, String)]) -> Unit

Take the connect, then accept with subprotocol and extra headers on the handshake.

ParameterTypeDefault
subprotocolStringoptional
headersArray[(String, String)]optional

Returns Unit

function
pub async fn WebSocket::close(Self, code? : Int32, reason? : String) -> Unit

Close with code and reason. Before accept this declines the handshake, which a server answers with 403.

ParameterTypeDefault
codeInt32optional
reasonStringoptional

Returns Unit

function
pub async fn WebSocket::deny(Self, @http.Response) -> Unit

Decline the handshake with response : the client gets its status, headers and body instead of a WebSocket. That takes ASGI's websocket.http.response extension; a server without it is sent close code 1008 instead, which it answers with 403. After accept there is no handshake left to decline, and the connection is closed with 1008.

ParameterTypeDefault
type only@http.Responserequired

Returns Unit

function
pub fn WebSocket::header(Self, String) -> String?

The first request header named name (lowercase, as ASGI carries them).

ParameterTypeDefault
type onlyStringrequired

Returns String?

function
pub fn WebSocket::new(@spec.WebSocketScope, async () -> @spec.Event, async (@spec.Event) -> Unit, params? : Map[String, String]) -> Self

A WebSocket over an ASGI connection. The app makes one per connection; a driver of its own makes one over its receive and send.

ParameterTypeDefault
type only@spec.WebSocketScoperequired
type onlyasync () -> @spec.Eventrequired
type onlyasync (@spec.Event) -> Unitrequired
paramsMap[String, String]optional

Returns Self

function
pub fn WebSocket::offered_subprotocols(Self) -> Array[String]

The subprotocols the client offered, in its order of preference.

Returns Array[String]

function
pub fn WebSocket::param(Self, String) -> String?

A path parameter by name.

ParameterTypeDefault
type onlyStringrequired

Returns String?

function
pub async fn WebSocket::receive(Self) -> WsMessage

The next message. Raises Disconnected when the peer has left.

Returns WsMessage

function
pub async fn WebSocket::receive_bytes(Self) -> Bytes

The next message, which must be binary; a text message is taken as its UTF-8.

Returns Bytes

function
pub async fn WebSocket::receive_json(Self) -> Json

The next message parsed as JSON.

Returns Json

function
pub async fn WebSocket::receive_text(Self) -> String

The next message, which must be text; a binary message is taken as its UTF-8.

Returns String

function
pub async fn WebSocket::send(Self, WsMessage) -> Unit

Send message.

ParameterTypeDefault
type onlyWsMessagerequired

Returns Unit

function
pub async fn WebSocket::send_bytes(Self, Bytes) -> Unit

Send a binary message.

ParameterTypeDefault
type onlyBytesrequired

Returns Unit

function
pub async fn WebSocket::send_json(Self, Json) -> Unit

Send value serialised as a text message.

ParameterTypeDefault
type onlyJsonrequired

Returns Unit

function
pub async fn WebSocket::send_text(Self, String) -> Unit

Send a text message.

ParameterTypeDefault
type onlyStringrequired

Returns Unit

Methods on WsMessage

function
pub fn WsMessage::equal(Self, Self) -> Bool

Returns Bool

function
pub fn WsMessage::not_equal(Self, Self) -> Bool

Returns Bool

function
pub fn WsMessage::to_repr(Self) -> @debug.Repr

Returns @debug.Repr

@static

Static file serving with content types and range support.

Types

struct
pub struct Memory { files : Map[String, Asset] }

Files held in the program, keyed by their relative path: built into the binary, generated at startup, or read once from anywhere. Works on every target.

FieldType
filesMap[String, Asset]
trait
pub(open) trait Source { async fn read(Self, String) -> Asset? }

Where the served files come from. path is relative, its parts joined by /, and already checked: no empty part, no . or .., no backslash, colon or NUL. None means there is no such file.

Memory serves files held in the program and Directory (native) serves a directory; a source of your own — an archive, a bucket, a database — is one more implementation.

Functions

function
pub fn serve(&Source, html? : Bool, ranges? : Bool) -> async (@spec.Scope, async () -> @spec.Event, async (@spec.Event) -> Unit) -> Unit

Serve the files source holds, as an ASGI application to mount with App::mount_asgi .

A GET or HEAD for a file answers with it, weighed against the request's conditional headers and Range (304, 412, 206, 416), its type guessed from its name and its entity-tag taken from its date and length when the source knows the date. Any other method is a 405. A path with a .. part is a 404, never a file outside the source: clients resolve dot segments before sending, so only a crafted request carries one.

With html, a directory answers with its index.html, a directory named without its trailing slash is first sent to the name with one (307), and a path with nothing behind it answers with 404.html when there is one. ranges=false withdraws the offer of partial content.

ParameterTypeDefault
type only&Sourcerequired
htmlBooloptional
rangesBooloptional

Returns async (@spec.Scope, async () -> @spec.Event, async (@spec.Event) -> Unit) -> Unit

Methods on Asset

function
pub fn Asset::equal(Self, Self) -> Bool

Returns Bool

function
pub fn Asset::not_equal(Self, Self) -> Bool

Returns Bool

Methods on Memory

function
pub fn Memory::new(Map[String, Bytes], modified? : @moondate.Moment) -> Self

A memory source over files, every one dated modified when given.

ParameterTypeDefault
type onlyMap[String, Bytes]required
modified@moondate.Momentoptional

Returns Self

function
pub async fn Memory::read(Self, String) -> Asset?
ParameterTypeDefault
type onlyStringrequired

Returns Asset?

@status

Response constructors, streaming, server-sent events, and background work.

Types

re-export
pub using @sse {type Event}
struct
pub struct Events { // private fields }

The event side of a text/event-stream: each send is one frame, written as its own chunk.

re-export
pub using @cookie {type SameSite}
struct
pub struct Writer { // private fields }

Where a stream's body goes. The app makes one per response; a test or another driver makes one over its own sink.

Constants & values

constant
pub const HTTP_100_CONTINUE : Int32 = 100

Continue: the headers are acceptable, send the body.

constant
pub const HTTP_101_SWITCHING_PROTOCOLS : Int32 = 101

Switching Protocols: the server is changing to the protocol Upgrade asked for.

constant
pub const HTTP_102_PROCESSING : Int32 = 102

Processing: WebDAV, the request is under way and the reply will follow.

constant
pub const HTTP_103_EARLY_HINTS : Int32 = 103

Early Hints: preload links sent ahead of the real response.

constant
pub const HTTP_200_OK : Int32 = 200

OK.

constant
pub const HTTP_201_CREATED : Int32 = 201

Created: the request made a new resource, named in Location.

constant
pub const HTTP_202_ACCEPTED : Int32 = 202

Accepted: taken for processing, outcome not yet known.

constant
pub const HTTP_203_NON_AUTHORITATIVE_INFORMATION : Int32 = 203

Non-Authoritative Information: an intermediary altered the origin's payload.

constant
pub const HTTP_204_NO_CONTENT : Int32 = 204

No Content: succeeded, and there is nothing to send back.

constant
pub const HTTP_205_RESET_CONTENT : Int32 = 205

Reset Content: succeeded; the client should clear the form that sent it.

constant
pub const HTTP_206_PARTIAL_CONTENT : Int32 = 206

Partial Content: the byte ranges Range asked for.

constant
pub const HTTP_207_MULTI_STATUS : Int32 = 207

Multi-Status: WebDAV, one status per member of a collection.

constant
pub const HTTP_208_ALREADY_REPORTED : Int32 = 208

Already Reported: WebDAV, this member was enumerated earlier in the reply.

constant
pub const HTTP_226_IM_USED : Int32 = 226

IM Used: the body is the result of applying delta encodings.

constant
pub const HTTP_300_MULTIPLE_CHOICES : Int32 = 300

Multiple Choices: several representations, pick one.

constant
pub const HTTP_301_MOVED_PERMANENTLY : Int32 = 301

Moved Permanently: use Location from now on.

constant
pub const HTTP_302_FOUND : Int32 = 302

Found: a temporary move. Clients rewrite POST to GET here, which is why 307 exists.

constant
pub const HTTP_303_SEE_OTHER : Int32 = 303

See Other: fetch the outcome with a GET at Location — the redirect after a form post.

constant
pub const HTTP_304_NOT_MODIFIED : Int32 = 304

Not Modified: the client's cached copy is still current.

constant
pub const HTTP_305_USE_PROXY : Int32 = 305

Use Proxy: deprecated by RFC 9110.

constant
pub const HTTP_306_RESERVED : Int32 = 306

Reserved: never standardised, and reserved so nothing else claims it.

constant
pub const HTTP_307_TEMPORARY_REDIRECT : Int32 = 307

Temporary Redirect: like 302, but the method and body must be kept.

constant
pub const HTTP_308_PERMANENT_REDIRECT : Int32 = 308

Permanent Redirect: like 301, but the method and body must be kept.

constant
pub const HTTP_400_BAD_REQUEST : Int32 = 400

Bad Request: malformed enough that the server will not act on it.

constant
pub const HTTP_401_UNAUTHORIZED : Int32 = 401

Unauthorized: not authenticated. The reply must carry WWW-Authenticate.

constant
pub const HTTP_402_PAYMENT_REQUIRED : Int32 = 402

Payment Required: reserved.

constant
pub const HTTP_403_FORBIDDEN : Int32 = 403

Forbidden: authenticated, and still not allowed.

constant
pub const HTTP_404_NOT_FOUND : Int32 = 404

Not Found.

constant
pub const HTTP_405_METHOD_NOT_ALLOWED : Int32 = 405

Method Not Allowed: the path exists under another verb, listed in Allow.

constant
pub const HTTP_406_NOT_ACCEPTABLE : Int32 = 406

Not Acceptable: nothing on offer matches the request's Accept.

constant
pub const HTTP_407_PROXY_AUTHENTICATION_REQUIRED : Int32 = 407

Proxy Authentication Required.

constant
pub const HTTP_408_REQUEST_TIMEOUT : Int32 = 408

Request Timeout: the client took too long to send it.

constant
pub const HTTP_409_CONFLICT : Int32 = 409

Conflict: it clashes with the resource's current state.

constant
pub const HTTP_410_GONE : Int32 = 410

Gone: it existed and was removed on purpose.

constant
pub const HTTP_411_LENGTH_REQUIRED : Int32 = 411

Length Required: Content-Length is missing and this server insists on it.

constant
pub const HTTP_412_PRECONDITION_FAILED : Int32 = 412

Precondition Failed: an If-* header did not hold.

constant
pub const HTTP_413_REQUEST_ENTITY_TOO_LARGE : Int32 = 413

Content Too Large — name keeps RFC 7231's "Request Entity Too Large".

constant
pub const HTTP_414_REQUEST_URI_TOO_LONG : Int32 = 414

URI Too Long — name keeps RFC 7231's "Request-URI Too Long".

constant
pub const HTTP_415_UNSUPPORTED_MEDIA_TYPE : Int32 = 415

Unsupported Media Type: the body's Content-Type is one this route cannot read.

constant
pub const HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE : Int32 = 416

Range Not Satisfiable: no part of the requested range exists.

constant
pub const HTTP_417_EXPECTATION_FAILED : Int32 = 417

Expectation Failed: the Expect header cannot be met.

constant
pub const HTTP_418_IM_A_TEAPOT : Int32 = 418

I'm a Teapot: RFC 2324's joke, kept because clients test for it.

constant
pub const HTTP_421_MISDIRECTED_REQUEST : Int32 = 421

Misdirected Request: this connection is not authoritative for that authority.

constant
pub const HTTP_422_UNPROCESSABLE_ENTITY : Int32 = 422

Unprocessable Content: well-formed, and it fails validation — what unprocessable returns.

constant
pub const HTTP_423_LOCKED : Int32 = 423

Locked: WebDAV, the resource is locked.

constant
pub const HTTP_424_FAILED_DEPENDENCY : Int32 = 424

Failed Dependency: WebDAV, a request this one depended on failed.

constant
pub const HTTP_425_TOO_EARLY : Int32 = 425

Too Early: replaying this early-data request could be a replay attack.

constant
pub const HTTP_426_UPGRADE_REQUIRED : Int32 = 426

Upgrade Required: resend over the protocol named in Upgrade.

constant
pub const HTTP_428_PRECONDITION_REQUIRED : Int32 = 428

Precondition Required: the server refuses to act on an unconditional write.

constant
pub const HTTP_429_TOO_MANY_REQUESTS : Int32 = 429

Too Many Requests: rate limited; Retry-After says when to come back.

constant
pub const HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE : Int32 = 431

Request Header Fields Too Large.

constant
pub const HTTP_500_INTERNAL_SERVER_ERROR : Int32 = 500

Internal Server Error: the fallback for an error the app did not map.

constant
pub const HTTP_501_NOT_IMPLEMENTED : Int32 = 501

Not Implemented: the server does not support the method at all.

constant
pub const HTTP_502_BAD_GATEWAY : Int32 = 502

Bad Gateway: an upstream sent something invalid.

constant
pub const HTTP_503_SERVICE_UNAVAILABLE : Int32 = 503

Service Unavailable: down or overloaded, and expected back.

constant
pub const HTTP_504_GATEWAY_TIMEOUT : Int32 = 504

Gateway Timeout: an upstream did not answer in time.

constant
pub const HTTP_505_HTTP_VERSION_NOT_SUPPORTED : Int32 = 505

HTTP Version Not Supported.

constant
pub const HTTP_506_VARIANT_ALSO_NEGOTIATES : Int32 = 506

Variant Also Negotiates: the negotiation is configured in a circle.

constant
pub const HTTP_507_INSUFFICIENT_STORAGE : Int32 = 507

Insufficient Storage: WebDAV, no room to store the representation.

constant
pub const HTTP_508_LOOP_DETECTED : Int32 = 508

Loop Detected: WebDAV, the traversal is cyclic.

constant
pub const HTTP_510_NOT_EXTENDED : Int32 = 510

Not Extended.

constant
pub const HTTP_511_NETWORK_AUTHENTICATION_REQUIRED : Int32 = 511

Network Authentication Required: a captive portal wants a login first.

constant
pub const WS_1000_NORMAL_CLOSURE : Int32 = 1000

Normal Closure: the purpose the connection was opened for is fulfilled.

constant
pub const WS_1001_GOING_AWAY : Int32 = 1001

Going Away: the peer is shutting down or navigating off the page.

constant
pub const WS_1002_PROTOCOL_ERROR : Int32 = 1002

Protocol Error.

constant
pub const WS_1003_UNSUPPORTED_DATA : Int32 = 1003

Unsupported Data: a frame of a type this endpoint cannot accept.

constant
pub const WS_1005_NO_STATUS_RCVD : Int32 = 1005

No Status Received: reported locally when a close frame carried no code.

constant
pub const WS_1006_ABNORMAL_CLOSURE : Int32 = 1006

Abnormal Closure: reported locally when the connection died without a close frame.

constant
pub const WS_1007_INVALID_FRAME_PAYLOAD_DATA : Int32 = 1007

Invalid Frame Payload Data: a text frame that is not valid UTF-8, say.

constant
pub const WS_1008_POLICY_VIOLATION : Int32 = 1008

Policy Violation: the generic refusal when no other code fits.

constant
pub const WS_1009_MESSAGE_TOO_BIG : Int32 = 1009

Message Too Big.

constant
pub const WS_1010_MANDATORY_EXT : Int32 = 1010

Mandatory Extension: the client required an extension the server did not negotiate.

constant
pub const WS_1011_INTERNAL_ERROR : Int32 = 1011

Internal Error: the server hit an unexpected condition.

constant
pub const WS_1012_SERVICE_RESTART : Int32 = 1012

Service Restart.

constant
pub const WS_1013_TRY_AGAIN_LATER : Int32 = 1013

Try Again Later: overloaded; come back.

constant
pub const WS_1014_BAD_GATEWAY : Int32 = 1014

Bad Gateway: the gateway got an invalid response upstream.

constant
pub const WS_1015_TLS_HANDSHAKE : Int32 = 1015

TLS Handshake: reported locally when the handshake failed.

Functions

function
pub fn data_response(String, filename? : String, status? : Int32, inline? : Bool) -> @http.Response?

Serve what a data: URL carries (RFC 2397), under the media type it names — what canvas.toDataURL() and FileReader.readAsDataURL() hand back.

None when it is not a data URL, so a handler tells "no picture" from "not a picture" without touching base64.

ParameterTypeDefault
type onlyStringrequired
filenameStringoptional
statusInt32optional
inlineBooloptional

Returns @http.Response?

function
pub fn data_url(Bytes, media_type? : String) -> String

The content as a data: URL, for embedding it instead of costing a second request.

ParameterTypeDefault
type onlyBytesrequired
media_typeStringoptional

Returns String

function
pub fn envelope(Int32, String, String, Bool) -> Array[(String, String)]

What the body is, how long, and what to save it as.

ParameterTypeDefault
type onlyInt32required
type onlyStringrequired
type onlyStringrequired
type onlyBoolrequired

Returns Array[(String, String)]

function
pub fn file_response(Bytes, filename? : String, media_type? : String, status? : Int32, inline? : Bool) -> @http.Response

A download : a media type from filename's extension unless media_type names one, Content-Length, and a Content-Disposition. No filename, no disposition.

Bytes rather than a path: the same app runs on four backends and only the server can read a file on any of them.

Always the whole thing. [Context::serve] weighs the request first.

ParameterTypeDefault
type onlyBytesrequired
filenameStringoptional
media_typeStringoptional
statusInt32optional
inlineBooloptional

Returns @http.Response

function
pub fn html(Int32, String) -> @http.Response

An HTML response — what the documentation pages are served as.

test {
  let page = @status.html(200, "<h1>Hello</h1>")
  assert_eq(page.header("content-type"), Some("text/html; charset=utf-8"))
}
ParameterTypeDefault
type onlyInt32required
type onlyStringrequired

Returns @http.Response

function
pub fn json(Int32, Json) -> @http.Response

A JSON response serialised from a Json value.

test {
  let reply = @status.json(200, { "name": "Ada" })
  assert_eq(reply.header("content-type"), Some("application/json"))
  assert_eq(reply.body, b"{\"name\":\"Ada\"}")
}
ParameterTypeDefault
type onlyInt32required
type onlyJsonrequired

Returns @http.Response

function
pub fn redirect(String, status? : Int32) -> @http.Response

A redirect to url .

307 keeps the method and body, which 302 historically does not. Use 303 after a write, 301 / 308 for a permanent move.

The URL is escaped as a whole URI reference, so an encoded one is not encoded twice and a \r\n cannot open a header of its own.

test {
  let moved = @status.redirect("/new")
  assert_eq(moved.status, 307)
  assert_eq(moved.header("location"), Some("/new"))
}
ParameterTypeDefault
type onlyStringrequired
statusInt32optional

Returns @http.Response

function
pub fn sse(async (Events) -> Unit, status? : Int32, headers? : Array[(String, String)], space? : Bool, wins? : @jwt.Wins, clash? : @jwt.OnClash[Array[(String, String)]]) -> Stream

A text/event-stream response . body sends frames for as long as it likes; the app cancels it when the client goes.

Framing an event is moonhttp/sse's job. What belongs here is the response around the frames, and the three headers that stop an intermediary buffering or closing the stream. One named in headers too replaces ours rather than joining it, because a response carrying two content-type headers is not a response with a choice in it. wins=Base keeps ours, and clash can abort or take a callback instead — worth setting when overriding content-type, which stops the stream being a stream.

ParameterTypeDefault
type onlyasync (Events) -> Unitrequired
statusInt32optional
headersArray[(String, String)]optional
spaceBooloptional
wins@jwt.Winsoptional
clash@jwt.OnClash[Array[(String, String)]]optional

Returns Stream

function
pub fn text(Int32, String) -> @http.Response

A plain-text response.

test {
  let reply = @status.text(200, "Hello")
  assert_eq(reply.header("content-type"), Some("text/plain; charset=utf-8"))
  assert_eq(reply.body, b"Hello")
}
ParameterTypeDefault
type onlyInt32required
type onlyStringrequired

Returns @http.Response

Methods on Events

function
pub async fn Events::ping(Self, comment? : String) -> Unit

Send a comment line, which a client ignores and an idle proxy takes as traffic.

ParameterTypeDefault
commentStringoptional

Returns Unit

function
pub async fn Events::send(Self, @sse.Event) -> Unit

Send event as one frame. A client dispatches it when it reads the frame's blank line, so it goes out on its own rather than waiting for the next.

ParameterTypeDefault
type only@sse.Eventrequired

Returns Unit

Methods on Stream

function
pub fn Stream::new(async (Writer) -> Unit, status? : Int32, headers? : Array[(String, String)], early_hints? : Array[Array[String]], trailers? : Bool) -> Self
ParameterTypeDefault
type onlyasync (Writer) -> Unitrequired
statusInt32optional
headersArray[(String, String)]optional
early_hintsArray[Array[String]]optional
trailersBooloptional

Returns Self

Methods on Writer

function
pub fn Writer::new(async (Bytes) -> Unit) -> Self
ParameterTypeDefault
type onlyasync (Bytes) -> Unitrequired

Returns Self

function
pub fn Writer::trailer(Self, String, String) -> Unit

Add a trailing field, sent after the body when the stream announced trailers.

ParameterTypeDefault
type onlyStringrequired
type onlyStringrequired

Returns Unit

function
pub fn Writer::trailers(Self) -> Array[(String, String)]

The trailing fields set so far.

Returns Array[(String, String)]

function
pub async fn Writer::write(Self, Bytes) -> Unit

Send chunk as one piece of the body. An empty chunk is not sent: it would say nothing.

ParameterTypeDefault
type onlyBytesrequired

Returns Unit

function
pub async fn Writer::write_text(Self, String) -> Unit

Send text as UTF-8.

ParameterTypeDefault
type onlyStringrequired

Returns Unit

@templates

Server-side template rendering and the context processors that feed it.

Types

type
pub type Processor = (@ctx.Context) -> Map[String, Json]

A context processor : the request in, the names every template rendered for it can use.

struct
pub struct Templates { env : @moonpug.Env // private fields }

Templates rendered into HTML responses , over a moonpug environment, which holds the loader, the settings, the filters and the globals.

Every template sees request: its method, url, path, root_path, the first value of each query parameter, the headers and the path params. Given url_for, it also sees url_for(name, **params), which resolves a named route; pass (name, params) => app.url_for(name, params~).

FieldType
env@moonpug.Env

Methods on Templates

function
pub fn Templates::new(@moonpug.Env, processors? : Array[(@ctx.Context) -> Map[String, Json]], url_for? : (String, Map[String, String]) -> String?) -> Self
ParameterTypeDefault
type only@moonpug.Envrequired
processorsArray[(@ctx.Context) -> Map[String, Json]]optional
url_for(String, Map[String, String]) -> String?optional

Returns Self

function
pub fn Templates::response(Self, @ctx.Context, String, context? : Map[String, Json], status? : Int32, media_type? : String, wins? : @jwt.Wins, clash? : @jwt.OnClash[Map[String, Json]]) -> @http.Response raise @spec.Refused

Render the template name into a response TemplateResponse).

A template's names come in three layers: request, then what each processor returns in order, then context. Where a later layer names what an earlier one did, the later one wins by default, the call being the most specific of the three. wins=Base keeps the processors' and ours instead; clash can abort or hand the decision to a callback, which receives the processors' names and the merged ones. url_for is added last, unless a layer already named it.

A template that does not load or does not render raises Refused, which the app answers with a 500 like any other error a handler raises.

ParameterTypeDefault
type only@ctx.Contextrequired
type onlyStringrequired
contextMap[String, Json]optional
statusInt32optional
media_typeStringoptional
wins@jwt.Winsoptional
clash@jwt.OnClash[Map[String, Json]]optional

Returns @http.Response raise @spec.Refused