///|
pub struct App {
routes : Array[Route]
middlewares : Array[(Context) -> Context]
mut cache_policy : @http.CachePolicy[@cache.RedisClient]?
ws_routes : Array[@http.WsRoute]
mut static_dir : String?
}
///|
pub fn new() -> App {
{
routes: [],
middlewares: [],
cache_policy: None,
ws_routes: [],
static_dir: None,
}
}
///|
/// Serve static files from `dir` as a fallback for unmatched GET requests:
/// `/` maps to `index.html`, directories to their `index.html`, and
/// path-traversal attempts are rejected. Dynamic routes always win.
pub fn App::static_files(self : App, dir : String) -> Unit {
self.static_dir = Some(dir)
}
///|
/// Enable response caching for GET requests through a Redis client: hits
/// are served before middlewares and handlers (X-Cache: HIT); 200 responses
/// are stored with the configured TTL (X-Cache: MISS). Cache failures
/// degrade to plain dispatch.
pub fn App::cache(
self : App,
client : @cache.RedisClient,
ttl~ : Int32 = 60,
prefix~ : String = "moonway",
) -> Unit {
self.cache_policy = Some({ store: client, prefix, ttl, })
}
///|
/// Register a middleware. Middlewares run in registration order, before the
/// matched route handler; each receives and returns the context. A
/// middleware may short-circuit the pipeline with `ctx.halt()`: later
/// middlewares and the route handler are skipped.
pub fn App::middleware(self : App, middleware : (Context) -> Context) -> Unit {
self.middlewares.push(middleware)
}
///|
pub fn App::get(
self : App,
path : String,
handler : (Context) -> Context,
) -> Unit {
self.add_route("GET", path, handler)
}
///|
pub fn App::post(
self : App,
path : String,
handler : (Context) -> Context,
) -> Unit {
self.add_route("POST", path, handler)
}
///|
pub fn App::put(
self : App,
path : String,
handler : (Context) -> Context,
) -> Unit {
self.add_route("PUT", path, handler)
}
///|
pub fn App::patch(
self : App,
path : String,
handler : (Context) -> Context,
) -> Unit {
self.add_route("PATCH", path, handler)
}
///|
pub fn App::delete(
self : App,
path : String,
handler : (Context) -> Context,
) -> Unit {
self.add_route("DELETE", path, handler)
}
///|
fn App::add_route(
self : App,
verb : String,
path : String,
handler : (Context) -> Context,
) -> Unit {
self.routes.push({ verb, path, handler, })
}