mars

    Hono-inspired MoonBit web framework with trie routing, middleware, SSE, and mizchi/x HTTP backend for native and Node.js

    moonbit
    http
    router
    web-framework
    middleware
    sse
    nodejs
    api
    Download zip
    Author
    Version
    0.3.11
    License
    MIT
    Last updated
    2 months ago
    Downloads
    6K

    Dependencies

    #Mars

    A Hono-inspired HTTP framework for MoonBit.

    #Features

    • Trie-based Router: Fast URL matching with parameter extraction
    • Dynamic Parameters: Support for :id style URL parameters
    • Wildcard Routes: Support for * wildcard patterns
    • Optional Parameters: Support for :param? optional parameters
    • Regex Parameters: Support for :id{[0-9]+} regex-constrained parameters
    • HTTP Methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, CONNECT, TRACE
    • Middleware Support: Chain multiple handlers
    • JSON/HTML/Text Responses: Built-in response helpers

    #Installation

    Add to your moon.mod.json:

    { "deps": { "mizchi/mars": "0.1.0" } }

    #Usage

    async fn main {
    let app = @mars.Mars::new()

    // Static route
    let _ = app.get("/", @mars.handler(async fn(ctx) {
    ctx.text("Hello, Mars!")
    }))

    // Dynamic parameter
    let _ = app.get("/users/:id", @mars.handler(async fn(ctx) {
    let id = ctx.param("id").unwrap_or("unknown")
    ctx.json({ "id": id })
    }))

    // Wildcard
    let _ = app.get("/files/*", @mars.handler(async fn(ctx) {
    ctx.text("File path: " + ctx.path())
    }))

    // Multiple methods
    let _ = app.post("/users", @mars.handler(async fn(ctx) {
    ctx.json({ "status": "created" }, status=201)
    }))

    // Start server
    app.serve(host="127.0.0.1", port=3000)
    }

    #JWT Middleware

    jwt_bearer_with_key and jwt_bearer_with_jwks are temporarily disabled while cross-target JWT verification is being redesigned. Current verifier behavior is fail-closed (always unauthorized).

    jwks_fetch_native, jwks_fetch_node, and jwks_fetch_wasm fetch JWKS documents for applications that need the transport helper directly. Native and Node.js targets use mizchi/x/http.

    Claims helper APIs are still available:

    • jwt_claims_json
    • jwt_claims_map
    • jwt_claims_decode
    • jwt_claims_decode_string

    #API

    #Mars

    • Mars::new() -> Mars - Create new application
    • Mars::get(path, handler) -> Mars - Register GET route
    • Mars::post(path, handler) -> Mars - Register POST route
    • Mars::put(path, handler) -> Mars - Register PUT route
    • Mars::delete(path, handler) -> Mars - Register DELETE route
    • Mars::patch(path, handler) -> Mars - Register PATCH route
    • Mars::all(path, handler) -> Mars - Register route for all methods
    • Mars::use_(middleware) -> Mars - Add middleware
    • Mars::serve(host?, port?) - Start HTTP server

    #Context

    • Context::param(name) -> String? - Get URL parameter
    • Context::path() -> String - Get request path
    • Context::request() -> @http.Request - Get raw HTTP request
    • Context::header(name) -> String? - Get request header
    • Context::text(body, status?) - Send text response
    • Context::json(data, status?) - Send JSON response
    • Context::html(body, status?) - Send HTML response
    • Context::redirect(url) - Send redirect response
    • Context::not_found() - Send 404 response

    #Router Patterns

    • /users - Static path
    • /users/:id - Dynamic parameter
    • /users/:id{[0-9]+} - Regex-constrained parameter
    • /files/* - Wildcard (matches any path)
    • /api/:type? - Optional parameter

    #License

    MIT

    Env

    pub(open) trait Env {
    fn get_var(Self, String) -> String?
    fn get_binding(Self, String) -> Json?
    }

    Environment trait for platform-specific bindings Implement this trait for your platform (Cloudflare, Deno, etc.)

    ExecCtx

    pub(open) trait ExecCtx {
    fn wait_until(Self, async () -> Unit, name~ : String) -> Unit
    }

    Execution context trait for background tasks Similar to Cloudflare Workers ExecutionContext

    Var

    pub(open) trait Var {
    fn to_json(Self) -> Json
    fn from_json(Json) -> Self?
    }

    Trait for types that can be stored in Variables
    impl Var for Bool
    impl Var for Double
    impl Var for String
    impl Var for Json

    BackgroundTask

    pub(all) struct BackgroundTask {
    task : async () -> Unit
    name : String
    }

    Background task that will run after response is sent

    Context

    pub(all) struct Context {
    request :
    Request

    params :
    Params

    vars : Variables
    exec_ctx : &ExecCtx
    // private fields
    }

    HTTP Context for request/response handling

    Context::body

    async fn Context::body(self : Context) -> String

    Read request body as string (native implementation)

    Context::body_json

    async fn Context::body_json(self : Context) -> Json?

    Parse request body as JSON

    Context::conn

    Get server connection (native only)

    Context::cookie

    fn Context::cookie(self : Context, name : String) -> String?

    Get a cookie by name

    Context::cookies

    fn Context::cookies(self : Context) -> Map[String, String]

    Get all cookies
    fn Context::delete_cookie(self : Context, name : String) -> Unit

    Delete a cookie

    Context::end_response

    async fn Context::end_response(self : Context) -> Unit

    End the response (native implementation)

    Context::env_binding

    fn Context::env_binding(self : Context, name : String) -> Json?

    Get environment binding as JSON

    Context::env_var

    fn Context::env_var(self : Context, name : String) -> String?

    Get environment variable

    Context::get

    fn Context::get(self : Context, key : String) -> String?

    Get custom data

    Context::header

    fn Context::header(self : Context, name : String) -> String?

    Get a request header

    Context::html

    async fn Context::html(self : Context, body : String, status? : Int) -> Unit

    Send an HTML response (native implementation)

    Context::is_response_sent

    fn Context::is_response_sent(self : Context) -> Bool

    Check if response has been sent

    Context::json

    async fn Context::json(self : Context, data : Json, status? : Int) -> Unit

    Send a JSON response (native implementation)

    Context::meth

    Get request method

    Context::new

    Create a new Context (native-specific constructor)

    Context::not_found

    async fn Context::not_found(self : Context) -> Unit

    Send a 404 Not Found response (native implementation)

    Context::param

    fn Context::param(self : Context, name : String) -> String?

    Get a URL parameter by name

    Context::path

    fn Context::path(self : Context) -> String

    Get request path

    Context::queries

    fn Context::queries(self : Context) -> Map[String, String]

    Get all query parameters

    Context::query

    fn Context::query(self : Context, name : String) -> String?

    Get a query parameter by name

    Context::redirect

    async fn Context::redirect(self : Context, url : String) -> Unit

    Send a redirect response (native implementation)

    Context::request

    Get raw HTTP request

    Context::set

    fn Context::set(self : Context, key : String, value : String) -> Unit

    Set custom data
    fn Context::set_cookie(self : Context, name : String, value : String, max_age? : Int, path? : String, http_only? : Bool, same_site? : String) -> Unit

    Set a cookie

    Context::set_header

    fn Context::set_header(self : Context, name : String, value : String) -> Unit

    Set a response header

    Context::set_status

    fn Context::set_status(self : Context, status : Int) -> Unit

    Set response status code

    Context::sse_start

    async fn Context::sse_start(self : Context) -> Unit

    Start an SSE response (native implementation)

    Context::text

    async fn Context::text(self : Context, body : String, status? : Int) -> Unit

    Send a text response (native implementation)

    Context::wait_until

    fn Context::wait_until(self : Context, task : async () -> Unit, name? : String) -> Unit

    Schedule a background task (like Cloudflare's waitUntil)

    Context::with_env

    Create a new Context with environment and execution context (native-specific)

    Context::write_raw

    async fn Context::write_raw(self : Context, data : String) -> Unit

    Write raw data to the response (native implementation)

    EmptyEnv

    pub(all) struct EmptyEnv {
    }

    Empty environment (no bindings)
    impl Env for EmptyEnv

    EmptyEnv::new

    fn EmptyEnv::new() -> EmptyEnv

    ExecutionContext

    pub(all) struct ExecutionContext {
    // private fields
    }

    ExecutionContext manages background tasks

    ExecutionContext::deactivate

    fn ExecutionContext::deactivate(self : ExecutionContext) -> Unit

    Deactivate context (no more tasks can be added)

    ExecutionContext::get_tasks

    Get all pending tasks (for testing)

    ExecutionContext::is_active

    fn ExecutionContext::is_active(self : ExecutionContext) -> Bool

    Check if context is still active

    ExecutionContext::new

    Create a new ExecutionContext

    ExecutionContext::pending_count

    fn ExecutionContext::pending_count(self : ExecutionContext) -> Int

    Get number of pending tasks

    ExecutionContext::run_tasks

    async fn ExecutionContext::run_tasks(self : ExecutionContext) -> Unit

    Execute all pending background tasks Called after response is sent

    ExecutionContext::wait_until

    fn ExecutionContext::wait_until(self : ExecutionContext, task : async () -> Unit, name? : String) -> Unit

    Schedule a background task to run after response is sent Similar to Cloudflare's ctx.waitUntil()

    Handler

    pub(all) struct Handler(async (Context) -> Unit)

    Handler function signature Handler receives a Context and returns Unit

    MapEnv

    pub(all) struct MapEnv {
    vars : Map[String, String]
    bindings : Map[String, Json]
    }

    Map-based environment (for testing and simple use cases)
    impl Env for MapEnv

    MapEnv::new

    fn MapEnv::new() -> MapEnv

    MapEnv::with_binding

    fn MapEnv::with_binding(self : MapEnv, name : String, value : Json) -> MapEnv

    MapEnv::with_var

    fn MapEnv::with_var(self : MapEnv, name : String, value : String) -> MapEnv

    PlatformContext

    pub(all) struct PlatformContext {
    conn :
    ServerConnection

    body_reader : &
    Reader

    }

    Native platform-specific context data

    PlatformContext::new

    Create a new PlatformContext for native

    Server

    pub(all) struct Server {
    router :
    TrieRouter

    handlers : Array[Handler]
    middlewares : Array[Handler]
    routes : Array[(
    Method
    , String, Int)]
    }

    Server HTTP Framework A Hono-inspired HTTP framework for MoonBit

    Server::all

    fn Server::all(self : Server, path : String, handler : Handler) -> Unit

    Register a route for all HTTP methods

    Server::delete

    fn Server::delete(self : Server, path : String, handler : Handler) -> Unit

    Register a DELETE route

    Server::get

    fn Server::get(self : Server, path : String, handler : Handler) -> Unit

    Register a GET route

    Server::middleware

    fn Server::middleware(self : Server, handler : Handler) -> Unit

    Add a middleware to the application

    Server::mount

    fn Server::mount(self : Server, prefix : String, sub : Server) -> Unit

    Mount a sub-application at the given prefix

    Server::new

    fn Server::new() -> Server

    Create a new Server application

    Server::new_debug

    fn Server::new_debug() -> Server

    Create a new Server application with debug mode enabled

    Server::patch

    fn Server::patch(self : Server, path : String, handler : Handler) -> Unit

    Register a PATCH route

    Server::post

    fn Server::post(self : Server, path : String, handler : Handler) -> Unit

    Register a POST route

    Server::put

    fn Server::put(self : Server, path : String, handler : Handler) -> Unit

    Register a PUT route

    Server::query

    fn Server::query(self : Server, path : String, handler : Handler) -> Unit

    Register a QUERY route (RFC 9110)

    Server::serve

    async fn Server::serve(self : Server, host? : String, port? : Int) -> Unit

    Start the HTTP server

    Server::serve_with_env

    async fn[E : Env, C : ExecCtx] Server::serve_with_env(self : Server, host? : String, port? : Int, env : E, exec_ctx : C) -> Unit

    Start the HTTP server with environment and execution context

    Server::to_handler

    Convert Server app to a platform handler function (native only)

    Server::to_handler_with_env

    fn[E : Env, C : ExecCtx] Server::to_handler_with_env(self : Server, env : E, exec_ctx : C) -> (async (
    Request
    , &
    Reader
    ,
    ServerConnection
    ) -> Unit)

    Convert Server app to a platform handler function with environment and execution context (native only)

    Variables

    pub(all) struct Variables {
    data : Map[String, Json]
    }

    Typed variables storage Uses Json for flexible storage with runtime type checking

    Variables::get

    fn Variables::get(self : Variables, key : String) -> Json?

    Get a variable as Json for pattern matching

    Variables::has

    fn Variables::has(self : Variables, key : String) -> Bool

    Check if variable exists

    Variables::keys

    fn Variables::keys(self : Variables) -> Array[String]

    Get all keys

    Variables::new

    fn Variables::new() -> Variables

    Variables::remove

    fn Variables::remove(self : Variables, key : String) -> Unit

    Remove a variable

    Variables::set

    fn[V : Var] Variables::set(self : Variables, key : String, value : V) -> Unit

    Set a variable (trait-based)

    char_to_lower

    fn char_to_lower(c : Char) -> Char

    Convert character to lowercase

    compose

    fn compose(handlers : Array[Handler]) -> Handler

    Compose multiple handlers into a chain Each handler is called in order

    find_char

    fn find_char(s : String, c : Char) -> Int

    Find first occurrence of character in string, returns -1 if not found

    handler

    fn handler(f : async (Context) -> Unit) -> Handler

    Helper to create a Handler from an async function

    hex_to_int

    fn hex_to_int(c : Char) -> Int

    Convert hex character to integer, returns -1 for invalid

    is_debug

    fn is_debug() -> Bool

    Check if debug mode is enabled

    is_whitespace

    fn is_whitespace(c : Char) -> Bool

    Check if character is whitespace

    set_debug

    fn set_debug(enabled : Bool) -> Unit

    Enable or disable debug mode globally

    split_by_char

    fn split_by_char(s : String, sep : Char) -> Array[String]

    Split string by separator character

    strip_query_string

    fn strip_query_string(path : String) -> String

    Strip query string from path (everything from first '?' onwards)

    substring

    fn substring(s : String, start : Int, end : Int) -> String

    Extract substring from start to end index

    substring_from

    fn substring_from(s : String, start : Int) -> String

    Extract substring from start to end of string

    to_lower

    fn to_lower(s : String) -> String

    Convert string to lowercase

    trim

    fn trim(s : String) -> String

    Trim whitespace from both ends of string

    url_decode

    fn url_decode(s : String) -> String

    URL decode a string (handles %XX and + encoding)

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io