mooncat — a native ASGI 3.0 server for MoonBit (← uvicorn), built on moonbitlang/async and the moonasgi SEAM. HTTP/1.1, HTTP/2, WebSocket, TLS and HTTP/3, a uvicorn-shaped command line, and a process model with graceful shutdown; the protocols themselves are moonhttp, moontls and moonquic.
Moved on mooncakes from Lfan-ke/mooncat to moonbitstack/mooncat.
flowchart LR
net["moonbitlang/async<br/>(sockets · TLS · HTTP/1.1)"] --> cat["**mooncat**<br/>accept loop"]
cat -->|"Scope / Receive / Send"| asgi(["moonasgi SEAM"])
asgi --> app["your app<br/>(moonapi, …)"]async fn main {
let app : @moonasgi.AsgiApp = (_scope, _receive, send) => {
send(
@moonasgi.Event::HttpResponseStart(
status=200,
headers=[("content-type", "text/plain; charset=utf-8")],
trailers=false,
),
)
send(
@moonasgi.Event::HttpResponseBody(body=b"Hello from mooncat!", more_body=false),
)
}
@mooncat.serve(app, host="127.0.0.1", port=12000) catch {
err => println("mooncat stopped: \{err}")
}
}moon run src/main --target native
curl http://127.0.0.1:12000async fn main {
@cli.run(app) catch {
err => println("mooncat: \{err}")
}
}moon run src/main --target native -- --port 9000 --log-level debug
moon run src/main --target native -- --help$ moon run src/main --target native -- --workers 4
mooncat: --workers: mooncat serves from one process; there is no fork here// All three are required arguments; `serve_tls` reads the pair its platform
// accepts and ignores the other, so one call compiles everywhere.
@mooncat.serve_tls(
app,
certificate_file="certs/cert.pem", // PEM cert, OpenSSL platforms
private_key_file="certs/key.pem", // PEM key, OpenSSL platforms
pfx_file="certs/dev.pfx", // PKCS#12, Windows and SChannel
port=12000,
)let handle = @mooncat.ShutdownHandle::new()
g.spawn(() => @mooncat.serve_graceful(app, @mooncat.Config::new(port=12000), handle~))
// … later, from anywhere:
handle.shutdown() // stop accepting → drain in-flight → lifespan shutdown → close@mooncat.serve_h2c(app, host="127.0.0.1", port=12000)| Package | What | What it costs to link |
|---|---|---|
| mooncat | The accept loop, HTTP/1.1, h2c, WebSocket, TLS, the process model, Config | moonasgi, moonhttp's http1 / http2 / hpack / ws / upgrade, moonbitlang/async |
| mooncat/cli | uvicorn's flags, and run(app) | the above, plus core's argparse |
| mooncat/quic | QUIC and HTTP/3: the UDP socket, the datagram loop, the handshake QUIC does inline | moonquic, moontls, mooncred's certificate reader, moonhttp/http3 |
pub suberror LifespanError {
LifespanError(String)
}pub(all) struct Config {
host : String
port : Int
backlog : Int
dual_stack : Bool
reuse_addr : Bool
server_headers : Map[String, String]
max_connections : Int?
allow_failure : Bool
graceful_timeout : Int?
root_path : String
logger : Logger
timeout_keep_alive : Int
limit_max_requests : Int?
limit_concurrency : Int?
max_head_size : Int
date_header : Bool
proxy_headers : Bool
forwarded_allow_ips : Array[String]
ws : WsConfig
}fn Config::new(host? : String, port? : Int, backlog? : Int, dual_stack? : Bool, reuse_addr? : Bool, server_headers? : Map[String, String], max_connections? : Int, allow_failure? : Bool, graceful_timeout? : Int, root_path? : String, logger? : Logger, timeout_keep_alive? : Int, limit_max_requests? : Int, limit_concurrency? : Int, max_head_size? : Int, date_header? : Bool, proxy_headers? : Bool, forwarded_allow_ips? : Array[String], ws? : WsConfig) -> Configpub(all) struct TlsCert {
certificate_file : String
private_key_file : String
pfx_file : String
}pub(all) struct WsConfig {
max_size : Int
}fn http_date(ms : Int64) -> Stringfn http_date_now() -> Stringlet port : Intasync fn reload_watch(path : String, on_reload : async () -> Unit) -> Unitasync fn serve_graceful(app : async (Scope, async () -> Event, async (Event) -> Unit) -> Unit, config : Config, handle? : ShutdownHandle) -> UnitInstall
Download zipmooncat — a native ASGI 3.0 server for MoonBit (← uvicorn), built on moonbitlang/async and the moonasgi SEAM. HTTP/1.1, HTTP/2, WebSocket, TLS and HTTP/3, a uvicorn-shaped command line, and a process model with graceful shutdown; the protocols themselves are moonhttp, moontls and moonquic.