Sign in

    moonbitstack/moonasgi/mid does not have a README file

    Layer

    Something that wraps one ASGI application in another: CORS, compression, a host check, or the caller's own. Every middleware here is a record that implements it, so a caller's middleware stacks with them on equal terms.

    BodyLimit

    pub(all) struct BodyLimit {
    limit : Int
    } derive(Eq,
    Debug
    )

    A ceiling on a request body. A Content-Length above it is answered 413 at once, without calling the application. A body that grows past it while the application reads it is answered 413 too, when no response has started; the application then reads a disconnect, and what it sends afterwards is dropped, since the client already has its answer.

    BodyLimit::equal

    fn BodyLimit::equal(BodyLimit, BodyLimit) -> Bool

    BodyLimit::new

    fn BodyLimit::new(limit? : Int) -> BodyLimit

    BodyLimit::not_equal

    fn BodyLimit::not_equal(x : BodyLimit, y : BodyLimit) -> Bool

    Cors

    pub(all) struct Cors {
    origins : Array[String]
    methods : Array[String]
    headers : Array[String]
    credentials : Bool
    expose : Array[String]
    max_age : Int
    } derive(Eq,
    Debug
    )

    Cross-origin resource sharing, as Starlette's CORSMiddleware does it (Fetch standard §3.2).

    origins, methods and headers are allow-lists, and "*" in one allows anything. A preflight is answered here: 200 with the negotiated headers, or 400 naming what was refused. Other cross-origin responses get access-control-allow-origin when the origin is allowed. With credentials the origin is echoed rather than *, as the standard requires.

    Cors::equal

    fn Cors::equal(Cors, Cors) -> Bool

    Cors::new

    fn Cors::new(origins? : Array[String], methods? : Array[String], headers? : Array[String], credentials? : Bool, expose? : Array[String], max_age? : Int) -> Cors

    Cors::not_equal

    fn Cors::not_equal(x : Cors, y : Cors) -> Bool

    Cors::to_repr

    Gzip

    pub(all) struct Gzip {
    minimum : Int
    level : Int
    } derive(Eq,
    Debug
    )

    Gzip for responses a client accepts it for, as Starlette's GZipMiddleware: a body of at least minimum octets, sent in one message, not already content-encoded. level is the zlib effort, 0 to 9.

    A body sent in several messages is passed through as it comes: compressing it would hold it back until the end, and a stream is sent in pieces so that it is not held back. An event stream is never compressed, for the same reason.

    Gzip::equal

    fn Gzip::equal(Gzip, Gzip) -> Bool

    Gzip::new

    fn Gzip::new(minimum? : Int, level? : Int) -> Gzip

    Gzip::not_equal

    fn Gzip::not_equal(x : Gzip, y : Gzip) -> Bool

    Gzip::to_repr

    HttpsRedirect

    pub(all) struct HttpsRedirect {
    } derive(Eq,
    Debug
    )

    Send every plain request to its secure equivalent, as Starlette's HTTPSRedirectMiddleware: http to https and ws to wss, with a 307 so the method and body are kept. Port 80 or 443 in the host is dropped; any other port stays.

    HttpsRedirect::equal

    HttpsRedirect::new

    HttpsRedirect::not_equal

    fn HttpsRedirect::not_equal(x : HttpsRedirect, y : HttpsRedirect) -> Bool

    ProxyHeaders

    pub(all) struct ProxyHeaders {
    trusted : Array[String]
    } derive(Eq,
    Debug
    )

    The client and scheme a reverse proxy saw, put back in the scope (← uvicorn's ProxyHeadersMiddleware, and RFC 7239). Only a request from an address in trusted is rewritten, since anyone else could claim any address; "*" trusts every peer.

    X-Forwarded-For gives the client: the rightmost address that is not trusted, every proxy before it having appended its own; when all are trusted, the leftmost. X-Forwarded-Proto gives the scheme, http or https (ws or wss for a WebSocket). Without either header, the Forwarded header is read the same way through its for and proto.

    ProxyHeaders::equal

    ProxyHeaders::new

    fn ProxyHeaders::new(trusted? : Array[String]) -> ProxyHeaders

    ProxyHeaders::not_equal

    fn ProxyHeaders::not_equal(x : ProxyHeaders, y : ProxyHeaders) -> Bool

    ServerErrors

    pub(all) struct ServerErrors {
    debug : Bool
    handler : (Error) -> (Int, Array[(String, String)], String)?
    }

    What an application's failure becomes, as Starlette's ServerErrorMiddleware: a 500 when the response has not started, then the error raised on to the server, which logs it. debug puts the error in the body. handler writes the answer instead: (status, headers, body) for the error.

    ServerErrors::new

    fn ServerErrors::new(debug? : Bool, handler? : (Error) -> (Int, Array[(String, String)], String)) -> ServerErrors

    TrustedHosts

    pub(all) struct TrustedHosts {
    hosts : Array[String]
    www_redirect : Bool
    } derive(Eq,
    Debug
    )

    Only the hosts listed may be asked for, as Starlette's TrustedHostMiddleware: a host header naming another answers 400. *.example.com allows any subdomain, * alone allows any host. With www_redirect, a request for example.com where only www.example.com is listed is sent there.

    TrustedHosts::equal

    TrustedHosts::new

    fn TrustedHosts::new(hosts? : Array[String], www_redirect? : Bool) -> TrustedHosts

    TrustedHosts::not_equal

    fn TrustedHosts::not_equal(x : TrustedHosts, y : TrustedHosts) -> Bool

    body_limit

    let body_limit : BodyLimit

    One mebibyte, nginx's client_max_body_size.

    cors

    let cors : Cors

    Starlette's defaults: no origin, GET only, the safelisted headers only, no credentials, preflights cached for ten minutes.

    gzip

    let gzip : Gzip

    Starlette's defaults: 500 octets and up, the most effort.

    https_redirect

    let https_redirect : HttpsRedirect

    proxy_headers

    let proxy_headers : ProxyHeaders

    uvicorn's default: only a proxy on the same machine is believed.

    server_errors

    let server_errors : ServerErrors

    Starlette's defaults: no detail in the body, the plain 500.

    stack

    app inside layers, the first outermost: it sees the request first and the response last, the order Starlette's middleware=[...] gives.

    trusted_hosts

    let trusted_hosts : TrustedHosts

    Starlette's defaults: any host, and the redirect to www. on.