///|
/// Log verbosity (← go-zero's `LogConf.Level`), ordered from most to least
/// verbose. `Compare` follows that order so thresholds can be tested directly.
pub(all) enum LogLevel {
Debug
Info
Error
Severe
} derive(Eq, Compare, Debug)
///|
/// The canonical lowercase name go-zero uses on the wire.
pub fn LogLevel::to_string(self : LogLevel) -> String {
match self {
Debug => "debug"
Info => "info"
Error => "error"
Severe => "severe"
}
}
///|
/// Parse a level name, falling back to `Info` for anything unrecognised — the
/// same lenient default go-zero applies to a missing/empty level.
pub fn LogLevel::parse(s : String) -> LogLevel {
match s {
"debug" => Debug
"error" => Error
"severe" => Severe
_ => Info
}
}
///|
/// Service configuration (← go-zero's `ServiceConf`): the service name, its bind
/// address, a request timeout, and the log level. `timeout_ms` is the per-request
/// budget in milliseconds; `0` disables the deadline.
pub(all) struct ServiceConf {
name : String
host : String
port : Int
timeout_ms : Int
log_level : LogLevel
} derive(FromJson, Eq)
///|
/// Build a config with sensible defaults (`0.0.0.0:8888`, 3s timeout, `info`).
pub fn ServiceConf::new(
name? : String = "app",
host? : String = "0.0.0.0",
port? : Int = 8888,
timeout_ms? : Int = 3000,
log_level? : LogLevel = Info,
) -> ServiceConf {
{ name, host, port, timeout_ms, log_level }
}
///|
/// An AsgiApp transformer — one layer of the middleware onion.
pub type Middleware = (@moonasgi.AsgiApp) -> @moonasgi.AsgiApp
///|
/// A moonzero service: its config plus the assembled application (a moonapi App
/// with any middleware already wrapped around it).
pub struct Server {
conf : ServiceConf
handler : @moonasgi.AsgiApp
}
///|
/// Assemble a service from config and a moonapi application.
pub fn Server::new(conf : ServiceConf, app : @moonapi.App) -> Server {
{ conf, handler: app.to_asgi() }
}
///|
/// Wrap the current application in another middleware layer (outermost last).
pub fn Server::use_(self : Server, mw : Middleware) -> Server {
{ conf: self.conf, handler: mw(self.handler) }
}
///|
/// The assembled `AsgiApp`, ready for a server (mooncat) to run.
pub fn Server::to_asgi(self : Server) -> @moonasgi.AsgiApp {
self.handler
}
///|
/// A human-readable description of what this service binds to.
pub fn Server::describe(self : Server) -> String {
self.conf.name +
" listening on " +
self.conf.host +
":" +
self.conf.port.to_string()
}
///|
/// A request-logging middleware: prints `METHOD path` for each HTTP request, then
/// delegates to the wrapped application.
pub fn logging(inner : @moonasgi.AsgiApp) -> @moonasgi.AsgiApp {
(scope, receive, send) => {
match scope {
Http(hs) => println(hs.http_method + " " + hs.path)
_ => ()
}
inner(scope, receive, send)
}
}