// Copyright 2026 Leo Cheng
// SPDX-License-Identifier: Apache-2.0
///|
/// Middleware from `mid` around an application, and one of our own beside them:
///
/// moon run src/examples/14-stack --target native
///
/// The application answers 4 KB of text. The stack refuses an unlisted host, answers a CORS
/// preflight itself, compresses the answer for a client that accepts gzip, and times every
/// request with a layer written here.
#coverage.skip
async fn main {
let app : @spec.AsgiApp = async fn(_, receive, send) {
ignore(receive())
send(
HttpResponseStart(
status=200,
headers=[("content-type", "text/plain")],
trailers=false,
),
)
send(HttpResponseBody(body=Bytes::make(4096, b'a'), more_body=false))
}
let seen : Array[String] = []
let timing = @mid.Wrap(inner => {
async fn(scope, receive, send) {
if scope is Http(h) {
seen.push("\{h.http_method} \{h.path}")
}
inner(scope, receive, send)
}
})
let stacked = @mid.stack(
[
@mid.server_errors,
@mid.TrustedHosts::new(hosts=["example.com"]),
@mid.Cors::new(origins=["https://app.example.com"], methods=["GET", "PUT"]),
@mid.gzip,
timing,
],
app,
)
for
request in [
("GET", [("host", "example.com"), ("accept-encoding", "gzip")]),
("GET", [("host", "evil.example")]),
(
"OPTIONS",
[
("host", "example.com"),
("origin", "https://app.example.com"),
("access-control-request-method", "PUT"),
],
),
] {
let (verb, headers) = request
let scope : @spec.Scope = Http(
@spec.HttpScope::new(http_method=verb, path="/", headers~),
)
let answer : Array[@spec.Event] = []
stacked(
scope,
async fn() {
@async.pause()
HttpRequest(body=b"", more_body=false)
},
async fn(e) {
@async.pause()
answer.push(e)
},
)
for e in answer {
match e {
HttpResponseStart(status~, headers~, ..) => {
let encoding = headers
.iter()
.find_first(h => h.0 == "content-encoding")
.map(h => h.1)
.unwrap_or("none")
println("\{verb}: \{status}, content-encoding \{encoding}")
}
HttpResponseBody(body~, ..) => println(" body \{body.length()} bytes")
_ => ()
}
}
}
println("reached the application: " + seen.join(", "))
}