///|
/// A synchronous application on an ASGI server:
///
/// moon run src/examples/17-wsgi --target native
///
/// The application is a plain function from the request environment and a
/// `start_response` to the body. It cannot wait for anything, and it does not
/// need to: `to_asgi` reads the request body first, calls it, and sends each
/// chunk it yields as soon as it yields it. Mounted under `/legacy`, it sees its
/// mount point as `SCRIPT_NAME` and the rest of the path as `PATH_INFO`.
#coverage.skip
async fn main {
tour() catch {
e => println("failed: \{e}")
}
}
///|
/// Answers `/hello` with a greeting built in three pieces, `/echo` with the
/// request body, `/env` with the CGI variables it was given, and anything else
/// with a 404.
#coverage.skip
fn legacy() -> @wsgi.WsgiApp {
(environ, start) => {
match environ.path_info {
"/hello" => {
ignore(start("200 OK", [("Content-Type", "text/plain")]))
[b"hello", b", ", b"world"].iter()
}
"/echo" => {
// The older style: write the body through what start_response returns.
let write = start("200 OK", [
("Content-Type", "application/octet-stream"),
])
write(environ.input)
[].iter()
}
"/env" => {
ignore(start("200 OK", [("Content-Type", "text/plain")]))
let cgi = environ.to_map()
let lines = [
"SCRIPT_NAME=" + cgi["SCRIPT_NAME"],
"PATH_INFO=" + cgi["PATH_INFO"],
"QUERY_STRING=" + cgi["QUERY_STRING"],
"HTTP_USER_AGENT=" + cgi.get("HTTP_USER_AGENT").unwrap_or(""),
]
[@utf8.encode(lines.join("\n"))].iter()
}
_ => {
ignore(start("404 Not Found", []))
[b"no such page"].iter()
}
}
}
}
///|
#coverage.skip
async fn tour() -> Unit {
let app = @dispatch.mount([("/legacy", @wsgi.to_asgi(legacy()))])
let client = @testing.Client::new(app)
let hello = client.get("/legacy/hello")
println("GET /legacy/hello -> \{hello.status} \{hello.text()}")
let echo = client.post("/legacy/echo", body=b"sent and returned")
println("POST /legacy/echo -> \{echo.status} \{echo.text()}")
let env = client.get("/legacy/env?page=2", headers=[("user-agent", "moonbit")])
println("GET /legacy/env?page=2 ->\n" + env.text())
let missing = client.get("/legacy/nope")
println("GET /legacy/nope -> \{missing.status} \{missing.text()}")
}