pub struct Router { /* private fields */ }Expand description
An HTTP router.
This contains a set of paths, and the Endpoints they point
to. This expects a root, /, and all paths placed in this router are
expected to be based off of this root. Ultimately, this is an array of
routes, where each route is a path, a method, and an endpoint. If
the incoming request matches on the path and method, then the last route
inserted that matches will have its endpoint run. So, assuming that you
have the following routes defined:
// ...
POST /user/{id} -> endpoint_user_id
POST /user/@me -> endpoint_user_me
// ...
Even though the former route can match /user/@me, the latter route will
always be picked instead, as it is defined after the former.
Internals
Internally, the router uses a regular expression matcher to convert the
given paths (e.g. /user/{id}) into a regular expression
(^/user/(?P<id>[^/]+)). It does this segment-by-segment in the path, and
is rather strict about what the names of a placeholder component can be
(only alphabetical). This is compiled into a RegexSet, which, when run
against a given path, will return a list of routes that the path matches.
Because we don’t have to fool around with matching every route, the timing
is O(n), with n being the length of the input path. After the
RegexSet match, we again match against the route to collect the pattern
matchers (e.g. {some} and {value:path}), before returning both. This
information is included as a part of the request.
Implementations§
source§impl Router
impl Router
sourcepub async fn listen(self, address: &str) -> Result<(), UnderError>
pub async fn listen(self, address: &str) -> Result<(), UnderError>
Creates a listen server on the specified address.
The server will prepare the routes, and then start listening for incoming connections.
Errors
This can fail if the socket address is invalid, or if the socket is already in use.
Examples
let mut http = under::http();
http.at("/").get(|_| async { Response::text("hello, world!") });
http.listen("0.0.0.0:8080").await?;source§impl Router
impl Router
sourcepub fn prepare(&mut self)
pub fn prepare(&mut self)
Prepares the router, constructing the routes.
This is automatically called when listening using Router::listen.
However, you may want to use the router before that point for e.g.
testing, and so this must be called before any requests are routed
(or, if any routes are changed). If this is not called, you will
receive only 500 errors.
sourcepub fn under<P: AsRef<str>, F: FnOnce(&mut Path<'_>)>(
&mut self,
prefix: P,
build: F
) -> &mut Self
pub fn under<P: AsRef<str>, F: FnOnce(&mut Path<'_>)>(
&mut self,
prefix: P,
build: F
) -> &mut Self
Creates a Path at the provided prefix, and executes the provided
closure with it. See Path::under for more.
sourcepub fn with<M: Middleware>(&mut self, middleware: M) -> &mut Self
pub fn with<M: Middleware>(&mut self, middleware: M) -> &mut Self
Appends middleware to the router. Each middleware is executed in the order that it is appended to the router (i.e., the first middleware inserted executes first).
Examples
let mut http = under::http();
http.with(under::middleware::TraceMiddleware::new())
.with(under::middleware::StateMiddleware::new(123u32));sourcepub fn fallback<E: Endpoint>(&mut self, endpoint: E) -> &mut Self
pub fn fallback<E: Endpoint>(&mut self, endpoint: E) -> &mut Self
Sets a fallback endpoint. If there exists no other endpoint in the router that could potentially respond to the request, it will first attempt to execute this fallback endpoint, before instead returning an empty 500 error.
Examples
let mut http = under::http();
http.at("/foo").get(under::endpoints::simple(Response::empty_204));
http.fallback(under::endpoints::simple(Response::empty_404));
http.prepare();
let response = http.handle(Request::get("/foo")?).await?;
assert_eq!(response.status(), http::StatusCode::NO_CONTENT);
let response = http.handle(Request::get("/bar")?).await?;
assert_eq!(response.status(), http::StatusCode::NOT_FOUND);sourcepub fn termination_signal(&mut self) -> Sender<bool>
pub fn termination_signal(&mut self) -> Sender<bool>
A channel to handle the termination singal. By default, the router does
not terminate, at least not gracefully, even in the face of
SIGINT/SIGTERM. This allows you to signal to the router when it should
terminate, and it will gracefully shut down, letting all current
requests finish before exiting. Note that the return type is not
Clone, and dropping the sender will not terminate the router.
Note this only applies to the router when listening, and not when handling a single request.
sourcepub async fn handle(&self, request: Request) -> Result<Response, Error>
pub async fn handle(&self, request: Request) -> Result<Response, Error>
Handles a one-off request to the router. This is equivalent to pinning
the router (with Pin::new, since the Router is Unpin), before
calling crate::Endpoint::apply.
Errors
This will error if any middleware or endpoint errors. Note that this does not error if the router was not prepared before calling this method.