Sign in

    mocket

    A web framework for MoonBit.

    http
    server
    Download zip
    Author
    Version
    0.4.2
    License
    Apache-2.0
    Last updated
    last year
    Downloads
    2K

    #oboard/mocket

    Version GitHub Workflow Status (with event) License

    A web framework for MoonBit.

    logo

    screenshots

    #Quick Start

    It's necessary to set the backend of MoonBit to js in Visual Studio Code

    Command: MoonBit: Select Backend -> js

    moon run src/main/main.mbt --target js

    Then visit http://localhost:4000

    #Usage

    Minimum Example: https://github.com/oboard/mocket_example

    #Features

    #Dynamic Routes

    Support named parameters with :param syntax:

    app.get("/hello/:name", fn(event) {
    let name = event.params.get("name").or("World")
    "Hello, \{name}!"
    })

    #Wildcard Routes

    Support single and double wildcards:

    // Single wildcard - matches one path segment
    app.get("/hello/*", fn(event) {
    let name = event.params.get("_").or("World")
    "Hello, \{name}!"
    })

    // Double wildcard - matches multiple path segments
    app.get("/hello/**", fn(event) {
    let path = event.params.get("_").or("")
    "Hello, \{path}!"
    })

    #Async Support

    The library supports async/await for I/O operations:

    #Async /GET Example

    // async json data example
    app.get("/async_data", async fn(event) {
    { "name": "John Doe", "age": 30, "city": "New York" }
    })

    #Route Groups

    Group related routes under a common base path with shared middleware:

    app.group("/api", group => {
    // Add group-level middleware
    group.use_middleware(event => println(
    "🔒 API Group Middleware: \{event.req.reqMethod} \{event.req.url}",
    ))

    // Routes under /api prefix
    group.get("/hello", _ => "Hello from API!")
    group.get("/users", _ => { "users": ["Alice", "Bob"] })
    group.post("/data", e => e.req.body.to_json())
    })

    This creates routes:
    • GET /api/hello
    • GET /api/users
    • POST /api/data

    All routes in the group will execute the group middleware in addition to any global middleware.

    #Example usage

    fn main {

    let app = @mocket.new()

    // Register global middleware
    app
    ..use_middleware(event => println(
    "📝 Request: \{event.req.reqMethod} \{event.req.url}",
    ))

    // Text Response
    ..get("/", _event => "⚡️ Tadaa!")

    // Route Groups with middleware
    ..group("/api", group => {
    // Add group-level middleware
    group.use_middleware(event => println(
    "🔒 API Group Middleware: \{event.req.reqMethod} \{event.req.url}",
    ))
    group.get("/hello", _ => "Hello from API!")
    group.get("/json", _ => {
    "name": "John Doe",
    "age": 30,
    "city": "New York",
    })
    })

    // JSON Response
    ..get("/json", _event => { "name": "John Doe", "age": 30, "city": "New York" })

    // Async Response
    ..get("/async_data", async fn(_event) {
    { "name": "John Doe", "age": 30, "city": "New York" }
    })

    // Dynamic Routes
    // /hello2/World = Hello, World!
    ..get("/hello/:name", fn(event) {
    let name = event.params.get("name").or("World")
    "Hello, \{name}!"
    })
    // /hello2/World = Hello, World!
    ..get("/hello2/*", fn(event) {
    let name = event.params.get("_").or("World")
    "Hello, \{name}!"
    })

    // Wildcard Routes
    // /hello3/World/World = Hello, World/World!
    ..get("/hello3/**", fn(event) {
    let name = event.params.get("_").or("World")
    "Hello, \{name}!"
    })

    // Echo Server
    ..post("/echo", e => e.req.body.to_json())

    // 404 Page
    ..get("/404", e => {
    e.res.statusCode = 404
    @mocket.html(
    #|<html>
    #|<body>
    #| <h1>404</h1>
    #|</body>
    #|</html>
    ,
    )
    })

    // Serve
    ..serve(port=4000)

    // Print Server URL
    for path in app.mappings.keys() {
    println("http://localhost:4000\{path.1}")
    }
    }

    #Route Matching Examples

    Route PatternURLParameters
    /hello/:name/hello/worldname: "world"
    /hello/*/hello/world_: "world"
    /hello/**/hello/foo/bar_: "foo/bar"
    /users/:id/posts/:postId/users/123/posts/456id: "123", postId: "456"
    /api/**/api/v1/users/123_: "v1/users/123"
    group("/api", ...).get("/hello")/api/hello-
    group("/users", ...).get("/:id")/users/123id: "123"

    🙌快来吧!🙌

    QQ 群号:949886784

    QQ 群

    typealias Mocket as T

    ExecError

    pub suberror ExecError

    impl Show for ExecError

    IOError

    pub suberror IOError

    impl Show for IOError

    NetworkError

    pub suberror NetworkError

    HttpEvent

    pub struct HttpEvent {
    req : HttpRequest
    res : HttpResponse
    params : Map[String, String]
    }

    HttpRequest

    pub struct HttpRequest {
    method_ : String
    url : String
    headers : Map[String, String]
    body : String
    }

    HttpRequestInternal

    #external
    pub type HttpRequestInternal

    HttpRequestInternal::headers

    HttpRequestInternal::on

    fn HttpRequestInternal::on(self : HttpRequestInternal, event : String, handler : (
    Value
    ) -> Unit) -> Unit

    HttpRequestInternal::req_method

    fn HttpRequestInternal::req_method(self : HttpRequestInternal) -> String

    HttpRequestInternal::url

    fn HttpRequestInternal::url(self : HttpRequestInternal) -> String

    HttpResponse

    pub(all) struct HttpResponse {
    status_code : Int
    headers : Map[String, String]
    }

    HttpResponseInternal

    #external
    pub type HttpResponseInternal

    HttpResponseInternal::end

    fn HttpResponseInternal::end(self : HttpResponseInternal, data : String) -> Unit

    HttpResponseInternal::statusCode

    fn HttpResponseInternal::statusCode(self : HttpResponseInternal) -> Int

    HttpResponseInternal::url

    fn HttpResponseInternal::url(self : HttpResponseInternal) -> String

    HttpResponseInternal::write_head

    fn HttpResponseInternal::write_head(self : HttpResponseInternal, statusCode : Int, headers :
    Value
    ) -> Unit

    LogLevel

    pub enum LogLevel {
    Debug
    Info
    Warn
    Error
    }

    Logger

    pub struct Logger {
    enabled : Bool
    level : LogLevel
    }

    Logger::debug

    fn Logger::debug(self : Logger, message_fn : () -> String) -> Unit

    Logger::debug_str

    fn Logger::debug_str(self : Logger, message : String) -> Unit

    Logger::error

    fn Logger::error(self : Logger, message_fn : () -> String) -> Unit

    Logger::info

    fn Logger::info(self : Logger, message_fn : () -> String) -> Unit

    Logger::route_added

    fn Logger::route_added(self : Logger, path : String) -> Unit

    Logger::route_created

    fn Logger::route_created(self : Logger, path : String) -> Unit

    Logger::route_dynamic

    fn Logger::route_dynamic(self : Logger, method_ : String, path : String) -> Unit

    Logger::route_found

    fn Logger::route_found(self : Logger, method_ : String, path : String) -> Unit

    Logger::route_lookup

    fn Logger::route_lookup(self : Logger, method_ : String, path : String) -> Unit

    Logger::route_merge_existing

    fn Logger::route_merge_existing(self : Logger, method_ : String) -> Unit

    Logger::route_merge_new

    fn Logger::route_merge_new(self : Logger, method_ : String) -> Unit

    Logger::route_not_found

    fn Logger::route_not_found(self : Logger, path : String) -> Unit

    Logger::route_register

    fn Logger::route_register(self : Logger, method_ : String, path : String) -> Unit

    Logger::route_static

    fn Logger::route_static(self : Logger, method_ : String, path : String) -> Unit

    Logger::routes_available

    fn Logger::routes_available(self : Logger, routes : Array[String]) -> Unit

    Logger::warn

    fn Logger::warn(self : Logger, message_fn : () -> String) -> Unit

    Mocket

    pub(all) struct Mocket {
    base_path : String
    mappings : Map[(String, String), async (HttpEvent) -> Json]
    middlewares : Array[(String, async (HttpEvent) -> Unit)]
    static_routes : Map[String, Map[String, async (HttpEvent) -> Json]]
    dynamic_routes : Map[String, Array[(String, async (HttpEvent) -> Json)]]
    logger : Logger
    }

    Mocket::all

    fn Mocket::all(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::connect

    fn Mocket::connect(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::delete

    fn Mocket::delete(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::get

    fn Mocket::get(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::group

    fn Mocket::group(self : Mocket, base_path : String, configure : (Mocket) -> Unit) -> Unit

    Mocket::head

    fn Mocket::head(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::on

    fn Mocket::on(self : Mocket, event : String, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::options

    fn Mocket::options(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::patch

    fn Mocket::patch(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::post

    fn Mocket::post(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::put

    fn Mocket::put(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::serve

    fn Mocket::serve(self : Mocket, port~ : Int) -> Unit

    Mocket::trace

    fn Mocket::trace(self : Mocket, path : String, handler : async (HttpEvent) -> Json) -> Unit

    Mocket::use_middleware

    fn Mocket::use_middleware(self : Mocket, middleware : async (HttpEvent) -> Unit, base_path? : String) -> Unit

    URL

    pub struct URL {
    protocol : String?
    host : String?
    port : Int?
    path : String
    query : Map[String, String]?
    fragment : String?
    }

    impl Show for URL

    URL::output

    fn URL::output(self : URL, logger : Logger) -> Unit

    URL::parse

    fn URL::parse(rawUrl : String) -> URL

    URL::to_string

    fn URL::to_string(self : URL) -> String

    createServer

    fn createServer(handler : (HttpRequestInternal, HttpResponseInternal, () -> Unit) -> Unit, port : Int) -> Unit

    html

    fn html(body : String) -> Json

    json

    fn json(body : Json) -> Json

    new

    fn new(base_path? : String, logger? : Logger) -> Mocket

    new_debug_logger

    fn new_debug_logger() -> Logger

    new_logger

    fn new_logger(enabled? : Bool, level? : LogLevel) -> Logger

    new_production_logger

    fn new_production_logger() -> Logger

    run

    fn run(f : async () -> Unit) -> Unit

    suspend

    async fn[T, E : Error] suspend(f : ((T) -> Unit, (E) -> Unit) -> Unit) -> T raise E

    suspend 会中断当前协程的运行。 suspend 会接受一个回调函数,并让这个回调函数来操作中断的协程

    text

    fn text(body : String) -> Json