mocket

A web framework for MoonBit.

http
server
Download zip
Author
Version
0.9.1
License
Apache-2.0
Last updated
7 days ago
Downloads
2K

#oboard/mocket

Version GitHub Workflow Status (with event) License

A web framework for MoonBit.

#Quick Start

async fn main {
let app = @mocket.new()
app.get("/", _ => "Hello, Mocket!")
app.listen(":80")
}

Mocket supports both js and native backends.

#JavaScript Backend

Set the backend of MoonBit to js in Visual Studio Code

Command: MoonBit: Select Backend -> js

moon run src/example --target js

#Native Backend

Set the backend of MoonBit to native in Visual Studio Code

Command: MoonBit: Select Backend -> native

moon run src/example --target native

Then visit http://localhost:4000

#Usage

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

🙌快来吧!🙌

QQ 群号:949886784

QQ 群

ErrorHandler

type ErrorHandler = (MocketEvent, Error) -> &Responder

HttpHandler

type HttpHandler = async (MocketEvent) -> &Responder

Middleware

type Middleware = async (MocketEvent, async () -> &Responder) -> &Responder

MiddlewareNext

type MiddlewareNext = async () -> &Responder

WebSocketHandler

type WebSocketHandler = (WebSocketEvent) -> Unit

BodyReader

pub(open) trait BodyReader {
fn from_request(req : HttpRequest) -> Self raise
}

impl BodyReader for Bytes
impl BodyReader for Json

Responder

pub(open) trait Responder {
fn options(Self, res : HttpResponse) -> Unit
fn output(Self, buf :
Buffer
) -> Unit
}

impl Responder for String
impl Responder for Bytes
impl Responder for Json
impl Responder for ToJson

ServeStaticProvider

pub(open) trait ServeStaticProvider {
async fn get_meta(Self, id : StringView) -> StaticAssetMeta?
async fn get_contents(Self, id : StringView) -> &Responder
fn get_type(Self, ext : String) -> String?
fn get_encodings(Self) -> Map[String, String]
fn get_index_names(Self) -> Array[String]
fn get_fallthrough(Self) -> Bool
}

A backend for Mocket::static_assets.

Asset ids handed to the provider are virtual absolute paths rooted at the mount point: they always start with "/" and are already normalized, so "." / ".." segments can never escape the provider's root. Providers should join the id onto their root directly.

ExecError

pub suberror ExecError

IOError

pub suberror IOError

NetworkError

pub suberror NetworkError

CookieItem

pub(all) struct CookieItem {
name : String
value : String
max_age : Int?
path : String?
domain : String?
secure : Bool?
http_only : Bool?
same_site : SameSiteOption?
} derive(Eq)

impl Show for CookieItem

Html

type Html

impl Responder for Html

HttpRequest

pub(all) struct HttpRequest {
http_method : String
url : String
query : String
headers : Map[
CaseInsensitiveString
, StringView]
raw_body : Bytes
}

HttpRequest::body

fn[T : BodyReader] HttpRequest::body(self : HttpRequest) -> T raise

fn HttpRequest::get_cookie(self : HttpRequest, name : String) -> CookieItem?

HttpRequest::json

HttpRequest::query

fn HttpRequest::query(self : HttpRequest) -> Map[String, String]

HttpResponse

pub(all) struct HttpResponse {
status_code : StatusCode
headers : Map[
CaseInsensitiveString
, StringView]
cookies : Map[String, CookieItem]
raw_body : Bytes
}

HttpResponse::body

fn HttpResponse::body(self : HttpResponse, body : &Responder) -> HttpResponse

Sets the response body from any Responder.

The body responder's default Content-Type is carried into this response only when no explicit "Content-Type" header was set on this response. Explicit response headers always take precedence.

Only the default Content-Type is inferred. The responder's status, other headers, cookies, and any other responder effects are not merged, so self.status_code is preserved.
fn HttpResponse::delete_cookie(self : HttpResponse, key : String) -> Unit

HttpResponse::json

fn HttpResponse::json(self : HttpResponse, obj : &ToJson) -> HttpResponse

Sets a JSON response body.

Infers Content-Type: application/json; charset=utf-8 under the same rule as HttpResponse::body: an explicit "Content-Type" header already present on this response takes precedence, and self.status_code is preserved.

HttpResponse::new

fn HttpResponse::new(status_code : StatusCode, headers? : Map[
CaseInsensitiveString
, StringView], cookies? : Map[String, CookieItem], raw_body? : Bytes) -> HttpResponse

HttpResponse::read_body

fn[T : BodyReader] HttpResponse::read_body(self : HttpResponse) -> T raise

fn HttpResponse::set_cookie(self : HttpResponse, name : String, value : String, max_age? : Int, path? : String, domain? : String, secure? : Bool, http_only? : Bool, same_site? : SameSiteOption) -> Unit

HttpResponse::to_responder

fn HttpResponse::to_responder(self : HttpResponse) -> &Responder

Mocket

#alias(T)
pub(all) struct Mocket {
base_path : String
mappings : Map[(String, String), async (MocketEvent) -> &Responder]
middlewares : Array[(String, async (MocketEvent, async () -> &Responder) -> &Responder)]
static_routes : Map[String, Map[String, async (MocketEvent) -> &Responder]]
dynamic_routes : Map[String, Array[(String, async (MocketEvent) -> &Responder)]]
ws_static_routes : Map[String, (WebSocketEvent) -> Unit]
ws_dynamic_routes : Array[(String, (WebSocketEvent) -> Unit)]
ws_clients : Map[String, Unit]
ws_channels : Map[String, Map[String, Unit]]
ws_client_port : Map[String, Int]
max_body_size : Int
error_handler : (MocketEvent, Error) -> &Responder
// private fields
}

Mocket::acl

fn Mocket::acl(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::all

fn Mocket::all(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::bind

fn Mocket::bind(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::checkin

fn Mocket::checkin(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::checkout

fn Mocket::checkout(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::connect

fn Mocket::connect(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::copy

fn Mocket::copy(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::delete

fn Mocket::delete(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::get

fn Mocket::get(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> 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 (MocketEvent) -> &Responder) -> Unit

Mocket::label

fn Mocket::label(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

fn Mocket::link(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::listen

async fn Mocket::listen(self : Mocket, address : String) -> Unit noraise

Mocket::lock

fn Mocket::lock(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::merge

fn Mocket::merge(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::mkactivity

fn Mocket::mkactivity(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::mkcalendar

fn Mocket::mkcalendar(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::mkcol

fn Mocket::mkcol(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::mkredirectref

fn Mocket::mkredirectref(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::mkworkspace

fn Mocket::mkworkspace(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::move_

fn Mocket::move_(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::on

fn Mocket::on(self : Mocket, event : String, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::on_error

fn Mocket::on_error(self : Mocket, handler : (MocketEvent, Error) -> &Responder) -> Unit

Mocket::options

fn Mocket::options(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::orderpatch

fn Mocket::orderpatch(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::patch

fn Mocket::patch(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::post

fn Mocket::post(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::pri

fn Mocket::pri(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::propfind

fn Mocket::propfind(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::proppatch

fn Mocket::proppatch(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::put

fn Mocket::put(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::query

fn Mocket::query(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::rebind

fn Mocket::rebind(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::report

fn Mocket::report(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::search

fn Mocket::search(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::serve

#deprecated("use `Mocket::listen(address)` instead")
async fn Mocket::serve(self : Mocket, port~ : Int) -> Unit noraise

Mocket::static_assets

fn Mocket::static_assets(self : Mocket, path : String, provider : &ServeStaticProvider) -> Unit

Mocket::trace

fn Mocket::trace(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::unbind

fn Mocket::unbind(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::uncheckout

fn Mocket::uncheckout(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

fn Mocket::unlink(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::unlock

fn Mocket::unlock(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::update

fn Mocket::update(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::updateredirectref

fn Mocket::updateredirectref(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::use_middleware

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

Mocket::version_control

fn Mocket::version_control(self : Mocket, path : String, handler : async (MocketEvent) -> &Responder) -> Unit

Mocket::ws

fn Mocket::ws(self : Mocket, path : String, handler : (WebSocketEvent) -> Unit) -> Unit

MocketEvent

pub(all) struct MocketEvent {
req : HttpRequest
res : HttpResponse
params : Map[String, StringView]
}

MultipartFormValue

pub(all) struct MultipartFormValue {
filename : String?
content_type : String?
data : BytesView
}

SameSiteOption

pub(all) enum SameSiteOption {
Lax
Strict
SameSiteNone
} derive(Eq)

StaticAssetMeta

pub(all) struct StaticAssetMeta {
asset_type : String?
etag : String?
mtime : Int64?
path : String?
size : Int64?
encoding : String?
}

StaticAssetMeta::new

fn StaticAssetMeta::new(asset_type? : String, etag? : String, mtime? : Int64, path? : String, size? : Int64, encoding? : String) -> StaticAssetMeta

StatusCode

pub(all) enum StatusCode {
Continue
SwitchingProtocols
Processing
EarlyHints
OK
Created
Accepted
NonAuthoritativeInfo
NoContent
ResetContent
PartialContent
MultiStatus
AlreadyReported
IMUsed
MultipleChoices
MovedPermanently
Found
SeeOther
NotModified
UseProxy
TemporaryRedirect
PermanentRedirect
BadRequest
Unauthorized
PaymentRequired
Forbidden
NotFound
MethodNotAllowed
NotAcceptable
ProxyAuthRequired
RequestTimeout
Conflict
Gone
LengthRequired
PreconditionFailed
RequestEntityTooLarge
RequestUriTooLong
UnsupportedMediaType
RequestedRangeNotSatisfiable
ExpectationFailed
Teapot
MisdirectedRequest
UnprocessableEntity
Locked
FailedDependency
TooEarly
UpgradeRequired
PreconditionRequired
TooManyRequests
RequestHeaderFieldsTooLarge
UnavailableForLegalReasons
InternalServerError
NotImplemented
BadGateway
ServiceUnavailable
GatewayTimeout
HttpVersionNotSupported
VariantAlsoNegotiates
InsufficientStorage
LoopDetected
NotExtended
NetworkAuthenticationRequired
Custom(Int)
} derive(Eq, ToJson)

HTTP status codes as registered with IANA. See: https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml

StatusCode::from_int

fn StatusCode::from_int(i : Int) -> StatusCode

StatusCode::to_int

fn StatusCode::to_int(self : StatusCode) -> Int

WebSocketAggregatedMessage

pub(all) enum WebSocketAggregatedMessage {
Text(String)
Binary(Bytes)
Ping
}

WebSocketEvent

pub(all) enum WebSocketEvent {
Open(WebSocketPeer)
Message(WebSocketPeer, WebSocketAggregatedMessage)
Close(WebSocketPeer)
}

WebSocketPeer

pub(all) struct WebSocketPeer {
connection_id : String
subscribed_channels : Array[String]
}

WebSocketPeer::binary

fn WebSocketPeer::binary(self : WebSocketPeer, message : Bytes) -> Unit

WebSocketPeer::pong

fn WebSocketPeer::pong(self : WebSocketPeer) -> Unit

WebSocketPeer::publish

fn WebSocketPeer::publish(channel : String, message : String) -> Unit

WebSocketPeer::subscribe

fn WebSocketPeer::subscribe(self : WebSocketPeer, channel : String) -> Unit

WebSocketPeer::text

fn WebSocketPeer::text(self : WebSocketPeer, message : String) -> Unit

WebSocketPeer::to_string

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

WebSocketPeer::unsubscribe

fn WebSocketPeer::unsubscribe(self : WebSocketPeer, channel : String) -> Unit

__ws_emit

fn __ws_emit(event_type : Bytes, connection_id : Bytes, payload : Bytes) -> Unit

fn cookie_to_string(cookie : Array[CookieItem]) -> String

dispatch_http

async fn dispatch_http(mocket : Mocket, http_method : String, url : String, headers : Map[
CaseInsensitiveString
, StringView], raw_body : Bytes) -> HttpResponse

dispatch_ws_event

fn dispatch_ws_event(handler : (WebSocketEvent) -> Unit, peer : WebSocketPeer, event_type : String, payload : Bytes) -> Unit

将 WS 事件类型字符串和 payload 转换为 WebSocketEvent 并调用 handler

encode_multipart

fn encode_multipart(m : Map[String, MultipartFormValue], boundary : String) -> String

escape_html

fn escape_html(s : String) -> String

execute_middlewares

async fn execute_middlewares(middlewares : Array[(String, async (MocketEvent, async () -> &Responder) -> &Responder)], event : MocketEvent, final_handler : async (MocketEvent) -> &Responder) -> &Responder

form_encode

fn form_encode(map : Map[String, String]) -> String

handle_not_found

fn handle_not_found() -> (async (MocketEvent) -> &Responder)

html

fn html(html : &Show) -> &Responder

listen_ffi

async fn listen_ffi(mocket : Mocket, address : String) -> Unit noraise

Listen and serve on address.

The native listener enables SO_REUSEADDR (reuse_addr=true) so that a process can immediately rebind a port that a previous process left in TIME_WAIT. On macOS/BSD this has the side effect that a bind to a specific address may "steal" the specific interface from an existing wildcard bind (0.0.0.0), and a wildcard bind can bind to the remaining interfaces if a specific-interface bind already exists.

new

fn new(base_path? : String, max_body_size? : Int) -> Mocket

fn parse_cookie(cookie : StringView) -> Map[String, CookieItem]

parse_form_data

fn parse_form_data(bytes : BytesView) -> Map[String, String]

parse_multipart

fn parse_multipart(bytes : BytesView, boundary : String) -> Map[String, MultipartFormValue]

parse_query

fn parse_query(query_string : StringView) -> Map[String, String]

register_ws_connection

fn register_ws_connection(connection_id : String, text_sender : (String) -> Unit, binary_sender : (Bytes) -> Unit, pong_sender : () -> Unit) -> Unit

register_ws_handler

fn register_ws_handler(mocket : Mocket, port : Int) -> Unit

serve_ffi

async fn serve_ffi(mocket : Mocket, port~ : Int) -> Unit noraise

suspend

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

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

text

fn text(text : &Show) -> &Responder

unregister_ws_connection

fn unregister_ws_connection(connection_id : String) -> Unit

url_decode

fn url_decode(bytes : BytesView) -> String

url_encode

fn url_encode(s : String) -> String

ws_pong

fn ws_pong(id : String) -> Unit

ws_publish

fn ws_publish(channel : String, msg : String) -> Unit

ws_send

fn ws_send(id : String, msg : String) -> Unit

ws_send_bytes

fn ws_send_bytes(id : String, msg : Bytes) -> Unit

ws_subscribe

fn ws_subscribe(id : String, channel : String) -> Unit

ws_unsubscribe

fn ws_unsubscribe(id : String, channel : String) -> Unit