pub struct Cx<'r, I> { /* private fields */ }Expand description
The context a handler receives: proof that the request passed its route’s access check, the identity it carries, and the reply.
There is no public way to make one: web-net builds it only after the gate cleared the request.
Implementations§
Source§impl<'r, I> Cx<'r, I>
impl<'r, I> Cx<'r, I>
Sourcepub fn param(&self, name: &str) -> Option<Cow<'r, str>>
pub fn param(&self, name: &str) -> Option<Cow<'r, str>>
A route parameter (:id or *rest), percent-decoded.
Sourcepub fn param_as<T: FromStr>(&self, name: &str) -> Result<T>
pub fn param_as<T: FromStr>(&self, name: &str) -> Result<T>
A route parameter parsed as T. A value that does not parse means
the page does not exist (/users/abc for a numeric id): 404.
§Errors
404 route.param when the parameter is missing or does not parse.
Sourcepub fn query(&self, name: &str) -> Result<Option<Cow<'r, str>>>
pub fn query(&self, name: &str) -> Result<Option<Cow<'r, str>>>
The first value of a query parameter, decoded (+ is a space).
§Errors
400 query.duplicate when the name appears twice (parameter
pollution is refused, never resolved by picking one), 400
query.invalid when the value does not decode to UTF-8.
Sourcepub fn body(&self) -> Result<&'r [u8]>
pub fn body(&self) -> Result<&'r [u8]>
The raw request body. On an unsafe method its CSRF token was checked before the handler ran.
§Errors
None today; reading the body stays fallible so a content inspector can refuse it in a later version without changing handlers.
Sourcepub fn form<T: FromForm>(&mut self) -> Result<T, FormError>
pub fn form<T: FromForm>(&mut self) -> Result<T, FormError>
Reads the body as a typed form (urlencoded or multipart text fields),
with the route’s form_limits.
On an unsafe method the CSRF token was checked before the handler
ran. A form type that is posted with a token lists the token field in
its ignore list (ignore = ["csrf_token"]).
The error keeps form-net’s detail, so an action can render the form
again with 422; ? turns it into an Error with its status.
use web_net::form_net::{self, FromForm};
form_net::form! {
pub struct Signup { pub email: String }
ignore = ["csrf_token"];
}
let app = web_net::App::builder()
.route(web_net::post("/signup", |cx| {
let form: Signup = cx.form()?;
cx.text(200, &form.email);
Ok(())
}).public().csrf_exempt("example without a session"))
.build()?;
let r = serve_net::testing::respond(&app,
b"POST /signup HTTP/1.1\r\nHost: a\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 15\r\n\r\nemail=a%40b.com");
assert_eq!(r.text(), "a@b.com");§Errors
form-net’s FormError: 415 for another media
type, 413 for a budget passed, 400 for malformed input, 422 for
fields that do not fit T, 403 for a CSRF token.
Sourcepub fn form_inspected<T: FromForm, N: Inspector>(
&mut self,
inspector: &mut N,
) -> Result<T, FormError>
pub fn form_inspected<T: FromForm, N: Inspector>( &mut self, inspector: &mut N, ) -> Result<T, FormError>
Sourcepub fn upload(&mut self, store: &Store) -> Result<Upload, FormError>
Available on crate feature uploads only.
pub fn upload(&mut self, store: &Store) -> Result<Upload, FormError>
uploads only.Reads a multipart upload into store (feature uploads): text
fields in memory, files in the store’s private temporary files, with
the route’s form limits. The CSRF token was checked before the
handler ran, so a forged one stores nothing. Turn the result into a typed form with
T::from_upload(upload).
§Errors
As form, plus the store’s errors.
Sourcepub fn upload_inspected<N: Inspector>(
&mut self,
store: &Store,
inspector: &mut N,
) -> Result<Upload, FormError>
Available on crate feature uploads only.
pub fn upload_inspected<N: Inspector>( &mut self, store: &Store, inspector: &mut N, ) -> Result<Upload, FormError>
uploads only.Sourcepub fn csrf_token(&self) -> Result<String>
pub fn csrf_token(&self) -> Result<String>
A CSRF token for the visitor’s session, to put in a form’s hidden
csrf_token field or a script’s X-CSRF-Token header. Different on
every call (masked), so a compression side channel cannot recover it.
§Errors
500 csrf.no_engine without Builder::csrf;
500 csrf.no_binding when the identity has no binding.
Sourcepub fn precondition(
&self,
tag: Option<&str>,
modified: Option<SystemTime>,
) -> Result
pub fn precondition( &self, tag: Option<&str>, modified: Option<SystemTime>, ) -> Result
Checks If-Match and If-Unmodified-Since against the current
version of what an unsafe request would change (RFC 9110 section
13.2): tag is its entity tag’s opaque part, modified its
modification time. Call it before changing anything.
§Errors
412 precondition.failed when a condition is false. Without either
field, Ok.
Sourcepub fn set_header(&mut self, name: &str, value: impl AsRef<[u8]>) -> &mut Self
pub fn set_header(&mut self, name: &str, value: impl AsRef<[u8]>) -> &mut Self
Adds a reply field. A name that is not a token, a value with a
control character, or a framing field (content-length, …) turns
the reply into a 500 when the handler returns.
Sourcepub fn body_bytes(&mut self, bytes: &[u8]) -> &mut Self
pub fn body_bytes(&mut self, bytes: &[u8]) -> &mut Self
Sets the body.
Sourcepub fn language(&self, offers: &[&'static str]) -> Option<&'static str>
pub fn language(&self, offers: &[&'static str]) -> Option<&'static str>
The best of offers for the request’s Accept-Language
(["en", "fr"]), or None when the request states no preference
any offer meets.
Sourcepub fn media(&self, offers: &[&'static str]) -> Option<&'static str>
pub fn media(&self, offers: &[&'static str]) -> Option<&'static str>
The best of offers for the request’s Accept (["text/html", "application/json"]).
Sourcepub fn body_mut(&mut self) -> &mut Vec<u8> ⓘ
pub fn body_mut(&mut self) -> &mut Vec<u8> ⓘ
The reply body’s buffer, emptied, for a writer that appends to a
Vec<u8> (a template engine with its own API writing straight in).
Set content-type yourself; the page budget does not apply here.
Sourcepub fn html(&mut self, status: u16, html: &str) -> &mut Self
pub fn html(&mut self, status: u16, html: &str) -> &mut Self
Status, content-type: text/html; charset=utf-8, and the HTML.
Sourcepub fn text(&mut self, status: u16, text: &str) -> &mut Self
pub fn text(&mut self, status: u16, text: &str) -> &mut Self
Status, content-type: text/plain; charset=utf-8, and the text.
Adds a Set-Cookie field built with cookie-net (re-exported as
web_net::cookie_net).
use web_net::{App, get, cookie_net::SetCookie};
let app = App::builder()
.route(get("/", |cx| {
cx.set_cookie(&SetCookie::new("theme", "dark").map_err(|_| web_net::Error::internal("cookie"))?);
cx.text(200, "ok");
Ok(())
}).public())
.build()?;
let r = serve_net::testing::respond(&app, b"GET / HTTP/1.1\r\nHost: a\r\n\r\n");
assert!(r.header("set-cookie").is_some());Sourcepub fn not_modified(&mut self, tag: &str) -> bool
pub fn not_modified(&mut self, tag: &str) -> bool
The conditional fast path for a page: sets ETag: "<tag>" and, when
the request’s If-None-Match matches it (a GET or HEAD), turns the
reply into 304 Not Modified and returns true, so the handler
returns before building the page.
tag is the opaque part (letters, digits, and -._~ are safe), for
example a revision number. An unusable tag sets nothing and returns
false.
use web_net::{App, get};
let app = App::builder()
.route(get("/", |cx| {
if cx.not_modified("rev-7") {
return Ok(());
}
cx.html(200, "<h1>page</h1>");
Ok(())
}).public())
.build()?;
let r = serve_net::testing::respond(&app, b"GET / HTTP/1.1\r\nHost: a\r\nIf-None-Match: \"rev-7\"\r\n\r\n");
assert_eq!(r.status, 304);Sourcepub fn url(&self, path: &str) -> String
pub fn url(&self, path: &str) -> String
The site-relative path as a URL path: the site’s base path in
front (/blog + /posts/1). Every link a page writes goes through
this, so the site works installed in a folder.
Sourcepub fn see_other(&mut self, path: &str) -> Result
pub fn see_other(&mut self, path: &str) -> Result
303 See Other to a site-relative path: the answer to a form that
was accepted, so a reload does not post it again.
§Errors
500 redirect.not_local when path is not a local path (it must
start with one /): redirects to other hosts are never built from a
string a handler passes along.
Sourcepub fn redirect_external(&mut self, status: u16, url: &str) -> Result
pub fn redirect_external(&mut self, status: u16, url: &str) -> Result
A redirect to another site, only to a host listed with
Builder::redirect_hosts:
https:// (or http://), the host, and a visible-ASCII rest.
§Errors
500 redirect.not_allowed for any other target, 500
redirect.status for a status that is not a redirect.
Sourcepub fn render(&mut self, view: &dyn View) -> Result
pub fn render(&mut self, view: &dyn View) -> Result
Renders the route’s template (declared with
Route::template) against view into the
body. The status stays as set (200 by default); content-type is
HTML unless the handler set one.
§Errors
500 render.no_engine or render.no_template when nothing can
render; the engine’s own RenderError as a 500;
a checkpoint’s denial.