Skip to main content

Route

Struct Route 

Source
pub struct Route<I, R> { /* private fields */ }
Expand description

A route: a path pattern, one handler per method, and who may use it.

Patterns are made of literal segments, parameters (:id, one segment) and one wildcard at the end (*rest, the rest of the path). Literals are written decoded (/café); web-net compares them with the canonical request path.

use web_net::{App, get, Route};

let app = App::builder()
    .route(get("/", |cx| { cx.html(200, "<h1>Home</h1>"); Ok(()) }).public())
    .route(
        Route::at("/contact")
            .get(|cx| { cx.html(200, "<form method=post></form>"); Ok(()) })
            .post(|cx| { cx.see_other("/contact/thanks") })
            .public()
            // A real form gets CSRF protection: Builder::csrf and a gate
            // whose identities carry a binding.
            .csrf_exempt("example: the POST changes nothing"),
    )
    .build()?;

A closure that reads fields of a custom identity types its parameter, because the closure is checked before the builder fixes the type (a named fn handler needs nothing extra):

use web_net::{Cx, Route, get};

struct User { name: String }
impl web_net::Identity for User {
    fn is_guest(&self) -> bool { self.name.is_empty() }
}
enum Rule { SignedIn }

let account: Route<User, Rule> = get("/account", |cx: &mut Cx<'_, User>| {
    let name = cx.identity().name.clone();
    cx.text(200, &name);
    Ok(())
})
.allow(Rule::SignedIn);

Implementations§

Source§

impl<I: 'static, R> Route<I, R>

Source

pub fn at(pattern: impl Into<String>) -> Self

A route at pattern with no methods yet.

Examples found in repository?
examples/hello.rs (line 39)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    let app = App::builder()
16        .host("127.0.0.1:8091")
17        .development()
18        .base("/app")
19        .route(
20            get("/", |cx| {
21                let users = cx.url("/users/7");
22                cx.html(
23                    200,
24                    &format!("<h1>Hello</h1><a href=\"{users}\">user 7</a>"),
25                );
26                Ok(())
27            })
28            .public(),
29        )
30        .route(
31            get("/users/:id", |cx| {
32                let id: u64 = cx.param_as("id")?;
33                cx.text(200, &format!("user {id}"));
34                Ok(())
35            })
36            .public(),
37        )
38        .route(
39            Route::at("/contact")
40                .get(|cx| {
41                    cx.html(200, "<form method=post><button>Send</button></form>");
42                    Ok(())
43                })
44                .post(|cx| cx.see_other("/"))
45                .public()
46                // A form that changes state gets Builder::csrf(..) and a gate
47                // whose identities carry a CSRF binding instead.
48                .csrf_exempt("demo: the POST changes nothing"),
49        )
50        .build()?;
51
52    let server = serve_net::Server::builder()
53        .listener(serve_net::ListenerSpec::tcp("web", "127.0.0.1:8091"))
54        .serve(app)?;
55    println!("listening on http://127.0.0.1:8091/app/");
56    server.wait();
57    Ok(())
58}
Source

pub fn on(self, method: Method, handler: impl Handler<I>) -> Self

Adds a handler for method. HEAD follows GET unless it has its own; OPTIONS is answered for every route unless it has its own.

Source

pub fn get<F>(self, f: F) -> Self
where F: Fn(&mut Cx<'_, I>) -> Result + Send + Sync + 'static,

Adds a GET handler.

Examples found in repository?
examples/hello.rs (lines 40-43)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    let app = App::builder()
16        .host("127.0.0.1:8091")
17        .development()
18        .base("/app")
19        .route(
20            get("/", |cx| {
21                let users = cx.url("/users/7");
22                cx.html(
23                    200,
24                    &format!("<h1>Hello</h1><a href=\"{users}\">user 7</a>"),
25                );
26                Ok(())
27            })
28            .public(),
29        )
30        .route(
31            get("/users/:id", |cx| {
32                let id: u64 = cx.param_as("id")?;
33                cx.text(200, &format!("user {id}"));
34                Ok(())
35            })
36            .public(),
37        )
38        .route(
39            Route::at("/contact")
40                .get(|cx| {
41                    cx.html(200, "<form method=post><button>Send</button></form>");
42                    Ok(())
43                })
44                .post(|cx| cx.see_other("/"))
45                .public()
46                // A form that changes state gets Builder::csrf(..) and a gate
47                // whose identities carry a CSRF binding instead.
48                .csrf_exempt("demo: the POST changes nothing"),
49        )
50        .build()?;
51
52    let server = serve_net::Server::builder()
53        .listener(serve_net::ListenerSpec::tcp("web", "127.0.0.1:8091"))
54        .serve(app)?;
55    println!("listening on http://127.0.0.1:8091/app/");
56    server.wait();
57    Ok(())
58}
Source

pub fn post<F>(self, f: F) -> Self
where F: Fn(&mut Cx<'_, I>) -> Result + Send + Sync + 'static,

Adds a POST handler.

Examples found in repository?
examples/hello.rs (line 44)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    let app = App::builder()
16        .host("127.0.0.1:8091")
17        .development()
18        .base("/app")
19        .route(
20            get("/", |cx| {
21                let users = cx.url("/users/7");
22                cx.html(
23                    200,
24                    &format!("<h1>Hello</h1><a href=\"{users}\">user 7</a>"),
25                );
26                Ok(())
27            })
28            .public(),
29        )
30        .route(
31            get("/users/:id", |cx| {
32                let id: u64 = cx.param_as("id")?;
33                cx.text(200, &format!("user {id}"));
34                Ok(())
35            })
36            .public(),
37        )
38        .route(
39            Route::at("/contact")
40                .get(|cx| {
41                    cx.html(200, "<form method=post><button>Send</button></form>");
42                    Ok(())
43                })
44                .post(|cx| cx.see_other("/"))
45                .public()
46                // A form that changes state gets Builder::csrf(..) and a gate
47                // whose identities carry a CSRF binding instead.
48                .csrf_exempt("demo: the POST changes nothing"),
49        )
50        .build()?;
51
52    let server = serve_net::Server::builder()
53        .listener(serve_net::ListenerSpec::tcp("web", "127.0.0.1:8091"))
54        .serve(app)?;
55    println!("listening on http://127.0.0.1:8091/app/");
56    server.wait();
57    Ok(())
58}
Source

pub fn put<F>(self, f: F) -> Self
where F: Fn(&mut Cx<'_, I>) -> Result + Send + Sync + 'static,

Adds a PUT handler.

Source

pub fn patch<F>(self, f: F) -> Self
where F: Fn(&mut Cx<'_, I>) -> Result + Send + Sync + 'static,

Adds a PATCH handler.

Source

pub fn delete<F>(self, f: F) -> Self
where F: Fn(&mut Cx<'_, I>) -> Result + Send + Sync + 'static,

Adds a DELETE handler.

Source

pub fn public(self) -> Self

Anyone may use the route, guests included. Public is a declaration, never a default: a route with neither public nor allow stops the build.

Examples found in repository?
examples/hello.rs (line 28)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    let app = App::builder()
16        .host("127.0.0.1:8091")
17        .development()
18        .base("/app")
19        .route(
20            get("/", |cx| {
21                let users = cx.url("/users/7");
22                cx.html(
23                    200,
24                    &format!("<h1>Hello</h1><a href=\"{users}\">user 7</a>"),
25                );
26                Ok(())
27            })
28            .public(),
29        )
30        .route(
31            get("/users/:id", |cx| {
32                let id: u64 = cx.param_as("id")?;
33                cx.text(200, &format!("user {id}"));
34                Ok(())
35            })
36            .public(),
37        )
38        .route(
39            Route::at("/contact")
40                .get(|cx| {
41                    cx.html(200, "<form method=post><button>Send</button></form>");
42                    Ok(())
43                })
44                .post(|cx| cx.see_other("/"))
45                .public()
46                // A form that changes state gets Builder::csrf(..) and a gate
47                // whose identities carry a CSRF binding instead.
48                .csrf_exempt("demo: the POST changes nothing"),
49        )
50        .build()?;
51
52    let server = serve_net::Server::builder()
53        .listener(serve_net::ListenerSpec::tcp("web", "127.0.0.1:8091"))
54        .serve(app)?;
55    println!("listening on http://127.0.0.1:8091/app/");
56    server.wait();
57    Ok(())
58}
Source

pub fn allow(self, rule: R) -> Self

Those rule allows may use the route; the gate’s authorize decides on every request.

Source

pub fn name(self, name: &'static str) -> Self

A name for logs, events, and hooks.

Source

pub fn work(self, work: WorkClass) -> Self

How the handlers behave: Quick (the default), Io, or Cpu. A dispatcher in front of web-net reads it through App::classify to move slow work off the connection’s worker.

Source

pub fn csrf_exempt(self, reason: &'static str) -> Self

Takes the route out of CSRF protection, with the reason (a webhook signed by its sender, an API authenticated by a bearer token that a browser never sends on its own). The reason is required and must not be empty: an exemption is a decision, never a default.

Examples found in repository?
examples/hello.rs (line 48)
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15    let app = App::builder()
16        .host("127.0.0.1:8091")
17        .development()
18        .base("/app")
19        .route(
20            get("/", |cx| {
21                let users = cx.url("/users/7");
22                cx.html(
23                    200,
24                    &format!("<h1>Hello</h1><a href=\"{users}\">user 7</a>"),
25                );
26                Ok(())
27            })
28            .public(),
29        )
30        .route(
31            get("/users/:id", |cx| {
32                let id: u64 = cx.param_as("id")?;
33                cx.text(200, &format!("user {id}"));
34                Ok(())
35            })
36            .public(),
37        )
38        .route(
39            Route::at("/contact")
40                .get(|cx| {
41                    cx.html(200, "<form method=post><button>Send</button></form>");
42                    Ok(())
43                })
44                .post(|cx| cx.see_other("/"))
45                .public()
46                // A form that changes state gets Builder::csrf(..) and a gate
47                // whose identities carry a CSRF binding instead.
48                .csrf_exempt("demo: the POST changes nothing"),
49        )
50        .build()?;
51
52    let server = serve_net::Server::builder()
53        .listener(serve_net::ListenerSpec::tcp("web", "127.0.0.1:8091"))
54        .serve(app)?;
55    println!("listening on http://127.0.0.1:8091/app/");
56    server.wait();
57    Ok(())
58}
Source

pub fn form_limits(self, limits: Limits) -> Self

The budgets for reading this route’s forms (field count, sizes, files; default form_net::Limits::DEFAULT). Keep them to what the form needs: they bound what one request can make the server hold.

Source

pub fn template(self, name: &'static str) -> Self

The template Cx::render uses. Resolved when the application is built: an unknown name stops the build.

Trait Implementations§

Source§

impl<I, R> Debug for Route<I, R>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<I, R> !RefUnwindSafe for Route<I, R>

§

impl<I, R> !UnwindSafe for Route<I, R>

§

impl<I, R> Forget for Route<I, R>

§

impl<I, R> Freeze for Route<I, R>
where Vec<(Method, Arc<dyn Handler<I>>)>: Freeze, Access<R>: Freeze,

§

impl<I, R> Send for Route<I, R>
where Vec<(Method, Arc<dyn Handler<I>>)>: Send, Access<R>: Send,

§

impl<I, R> Sync for Route<I, R>
where Vec<(Method, Arc<dyn Handler<I>>)>: Sync, Access<R>: Sync,

§

impl<I, R> Unpin for Route<I, R>
where Vec<(Method, Arc<dyn Handler<I>>)>: Unpin, Access<R>: Unpin,

§

impl<I, R> UnsafeUnpin for Route<I, R>
where Vec<(Method, Arc<dyn Handler<I>>)>: UnsafeUnpin, Access<R>: 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.