Cookbook / Requests and responses
Building responses
Status codes, headers, redirects, downloads and streaming, when a plain return value is not enough.
Most handlers return a value and let IntoResponse do the work. When you need control over headers or the body, build a Response.
| Return | Response |
|---|---|
&str, String | 200 text/plain |
Json(value) | 200 application/json |
Html(text) | 200 text/html |
(status, body) | body with the given status |
Option<T> | T, or 404 for None |
() | 204 No Content |
Result<T, E> | T, or the error |
Response | full control |
use axeon::{Html, Response, Server};
use futures::stream;
fn main() {
let mut app = Server::new();
app.get("/page", |_req| async { Html("<h1>Hi</h1>") });
// A download with a filename and cache headers.
app.get("/report.csv", |_req| async {
let mut res = Response::binary("text/csv", "id,name\n1,Ada\n2,Grace\n");
res.attachment("report.csv").cache_control("no-store");
res
});
// Builder style: status and header in one expression.
app.post("/things", |_req| async {
Response::text("made").with_status(201).with_header("Location", "/things/7")
});
app.get("/old", |_req| async { Response::permanent_redirect("/page") });
app.get("/home", |_req| async { Response::redirect("/page") });
// Send a body in chunks instead of building it in memory.
app.get("/count", |_req| async {
let chunks = stream::iter((1..=5).map(|n| Ok::<_, std::io::Error>(format!("{}\n", n))));
Response::stream("text/plain", chunks)
});
app.listen("127.0.0.1:3000").expect("server failed to start");
}
Notes#
Response::json(&value)serialises anySerializetype. Usewith_statusto change the code.- Prefer
Response::stream_with_lengthwhen you know the size, so clients see aContent-Lengthand can show progress. - Large files should be served by static files, which stream from disk and honour range requests.