Skip to main content

Cx

Struct Cx 

Source
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>

Source

pub fn request(&self) -> &Request<'r>

The request.

Source

pub fn method(&self) -> Method

The method.

Source

pub fn path(&self) -> &'r str

The canonical path inside the site.

Source

pub fn header(&self, name: &str) -> Option<&'r [u8]>

The first value of a request field.

Source

pub fn identity(&self) -> &'r I

Who the request comes from: always present, possibly a guest.

Source

pub fn id(&self) -> RequestId

The request’s reference, as shown on error pages.

Source

pub fn param(&self, name: &str) -> Option<Cow<'r, str>>

A route parameter (:id or *rest), percent-decoded.

Source

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.

Source

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.

Source

pub fn body(&self) -> Result<&'r [u8]>

The raw request body.

§Errors

403 csrf.unverified for a multipart body whose CSRF token has not been checked yet: read it with form or upload (feature uploads), which check the token in the same pass.

Source

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.

A multipart body’s CSRF token is checked in the same pass (it must come before any file part). 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.

Source

pub fn form_inspected<T: FromForm, N: Inspector>( &mut self, inspector: &mut N, ) -> Result<T, FormError>

As form, with an inspector beside the parse (a content policy that sees every part and field first).

§Errors

As form, plus the inspector’s refusals.

Source

pub fn upload(&mut self, store: &Store) -> Result<Upload, FormError>

Available on crate feature 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 is checked before any file byte is stored. Turn the result into a typed form with T::from_upload(upload).

§Errors

As form, plus the store’s errors.

Source

pub fn upload_inspected<N: Inspector>( &mut self, store: &Store, inspector: &mut N, ) -> Result<Upload, FormError>

Available on crate feature uploads only.

As upload, with an inspector beside the parse.

§Errors

As upload, plus the inspector’s refusals.

Source

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.

Source

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.

Source

pub fn status(&mut self, status: u16) -> &mut Self

Sets the status (default 200).

Source

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.

Source

pub fn body_bytes(&mut self, bytes: &[u8]) -> &mut Self

Sets the body.

Source

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.

Source

pub fn media(&self, offers: &[&'static str]) -> Option<&'static str>

The best of offers for the request’s Accept (["text/html", "application/json"]).

Source

pub fn html(&mut self, status: u16, html: &str) -> &mut Self

Status, content-type: text/html; charset=utf-8, and the HTML.

Source

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());
Source

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);
Source

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.

Source

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.

Source

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.

Source

pub fn redirect(&mut self, status: u16, path: &str) -> Result

A redirect with status (301, 302, 303, 307, 308) to a site-relative path.

§Errors

As see_other; 500 redirect.status for a status that is not a redirect.

Source

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.

Source

pub fn render_named(&mut self, name: &str, view: &dyn View) -> Result

Renders the template name against view. The name is resolved by the engine on every call; prefer render with a template declared on the route, resolved once at build.

§Errors

As render.

Trait Implementations§

Source§

impl<I> Debug for Cx<'_, I>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'r, I> !RefUnwindSafe for Cx<'r, I>

§

impl<'r, I> !UnwindSafe for Cx<'r, I>

§

impl<'r, I> Forget for Cx<'r, I>

§

impl<'r, I> Freeze for Cx<'r, I>
where &'r I: Freeze, &'r [Arc<dyn Fn(&mut Cx<'_, I>) -> Result<(), Error> + Send + Sync>]: Freeze,

§

impl<'r, I> Send for Cx<'r, I>
where &'r I: Send, &'r [Arc<dyn Fn(&mut Cx<'_, I>) -> Result<(), Error> + Send + Sync>]: Send,

§

impl<'r, I> Sync for Cx<'r, I>
where &'r I: Sync, &'r [Arc<dyn Fn(&mut Cx<'_, I>) -> Result<(), Error> + Send + Sync>]: Sync,

§

impl<'r, I> Unpin for Cx<'r, I>
where &'r I: Unpin, &'r [Arc<dyn Fn(&mut Cx<'_, I>) -> Result<(), Error> + Send + Sync>]: Unpin,

§

impl<'r, I> UnsafeUnpin for Cx<'r, I>
where &'r I: UnsafeUnpin, &'r [Arc<dyn Fn(&mut Cx<'_, I>) -> Result<(), Error> + Send + Sync>]: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.