pub struct Sites<G: Gate = Open, E: Render = NoRender> { /* private fields */ }Expand description
A table of applications, chosen per request by host and base path: an application that lists the request’s host (or an alias of it) wins over one that answers any host, and among those, the longest base path that holds the request’s path. A request no application claims goes to the first one added, which answers it by its own rules (421 for a host it does not serve, 404 outside its base).
use web_net::{App, Sites, get};
let blog = App::builder()
.host("example.com")
.base("/blog")
.route(get("/", |cx| cx.text(200, "blog")))
.build()?;
let shop = App::builder()
.host("shop.example.com")
.route(get("/", |cx| cx.text(200, "shop")))
.build()?;
let main = App::builder()
.host("example.com")
.route(get("/", |cx| cx.text(200, "home")))
.build()?;
let sites = Sites::new().site(main).site(blog).site(shop);
use serve_net::testing::respond;
assert_eq!(respond(&sites, b"GET /blog/ HTTP/1.1\r\nHost: example.com\r\n\r\n").text(), "blog");
assert_eq!(respond(&sites, b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n").text(), "home");
assert_eq!(respond(&sites, b"GET / HTTP/1.1\r\nHost: shop.example.com\r\n\r\n").text(), "shop");
assert_eq!(respond(&sites, b"GET / HTTP/1.1\r\nHost: other.example\r\n\r\n").status, 421);Implementations§
Source§impl<G: Gate, E: Render> Sites<G, E>
impl<G: Gate, E: Render> Sites<G, E>
Sourcepub fn new() -> Self
pub fn new() -> Self
An empty table.
use web_net::Sites;
// With no application, every request is answered with 421.
let sites: Sites = Sites::new();
let r = serve_net::testing::respond(&sites, b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n");
assert_eq!(r.status, 421);Sourcepub fn site(self, app: App<G, E>) -> Self
pub fn site(self, app: App<G, E>) -> Self
Adds an application. The first one added answers what no other claims.
use serve_net::testing::respond;
use web_net::{App, Sites, get};
let main = App::builder().host("example.com").route(get("/", |cx| cx.text(200, "home"))).build()?;
let shop = App::builder().host("shop.example.com").route(get("/", |cx| cx.text(200, "shop"))).build()?;
let sites = Sites::new().site(main).site(shop);
assert_eq!(respond(&sites, b"GET / HTTP/1.1\r\nHost: shop.example.com\r\n\r\n").text(), "shop");
assert_eq!(respond(&sites, b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n").text(), "home");Sourcepub fn pick(&self, req: &HttpRequest<'_>) -> Option<&App<G, E>>
pub fn pick(&self, req: &HttpRequest<'_>) -> Option<&App<G, E>>
The application for a request, if the table has any.
use serve_net::{Envelope, HttpReply, HttpRequest, HttpService, Outcome};
use web_net::{App, Sites, get};
// A front that picks the application itself before it answers.
struct Front(Sites);
impl HttpService for Front {
fn call(&self, req: &HttpRequest<'_>, env: &Envelope, reply: &mut HttpReply) -> Outcome {
let app = self.0.pick(req).expect("one site is configured");
app.respond(req, env, None, reply).outcome
}
}
let shop = App::builder().host("shop.example.com").route(get("/", |cx| cx.text(200, "shop"))).build()?;
let front = Front(Sites::new().site(shop));
let r = serve_net::testing::respond(&front, b"GET / HTTP/1.1\r\nHost: shop.example.com\r\n\r\n");
assert_eq!(r.text(), "shop");Sourcepub fn listen(self, addr: impl ToSocketAddrs) -> Result<Running, ServeError>
pub fn listen(self, addr: impl ToSocketAddrs) -> Result<Running, ServeError>
Serves every site on addr, as App::listen does for one.
§Errors
As App::listen.
use web_net::{App, Sites, get};
let main = App::builder().host("example.com").route(get("/", |cx| cx.text(200, "home"))).build()?;
let shop = App::builder().host("shop.example.com").route(get("/", |cx| cx.text(200, "shop"))).build()?;
Sites::new().site(main).site(shop).listen("127.0.0.1:8080")?.wait();Sourcepub fn respond(
&self,
req: &HttpRequest<'_>,
env: &Envelope,
who: Option<&G::Identity>,
reply: &mut HttpReply,
) -> Served
pub fn respond( &self, req: &HttpRequest<'_>, env: &Envelope, who: Option<&G::Identity>, reply: &mut HttpReply, ) -> Served
As App::respond on the chosen application.
use serve_net::{Envelope, HttpReply, HttpRequest, HttpService, Outcome};
use web_net::{App, Guest, Sites, get};
// A front that authenticated every request already.
struct Front(Sites);
impl HttpService for Front {
fn call(&self, req: &HttpRequest<'_>, env: &Envelope, reply: &mut HttpReply) -> Outcome {
self.0.respond(req, env, Some(&Guest), reply).outcome
}
}
let app = App::builder().route(get("/", |cx| cx.text(200, "hi"))).build()?;
let r = serve_net::testing::respond(&Front(Sites::new().site(app)), b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n");
assert_eq!(r.text(), "hi");Trait Implementations§
Source§impl<G: Gate, E: Render> HttpService for Sites<G, E>
impl<G: Gate, E: Render> HttpService for Sites<G, E>
Source§fn call(
&self,
request: &HttpRequest<'_>,
env: &Envelope,
reply: &mut HttpReply,
) -> Outcome
fn call( &self, request: &HttpRequest<'_>, env: &Envelope, reply: &mut HttpReply, ) -> Outcome
The request is complete.
Source§fn done(&self, env: &Envelope, _finished: &Finished)
fn done(&self, env: &Envelope, _finished: &Finished)
Exactly once per request that reached
head, on every path.Source§fn head(&self, head: &HttpHead<'_>, env: &mut Envelope) -> HeadAction
fn head(&self, head: &HttpHead<'_>, env: &mut Envelope) -> HeadAction
The head is complete; before admission and before any body byte.
Source§fn upgraded(&self, env: &Envelope, conn: UpgradedConn)
fn upgraded(&self, env: &Envelope, conn: UpgradedConn)
After the 101 for an upgrade this service asked for in
head left,
and after done for that request. The conversation itself belongs to
the upgrade target (a WebSocketService, feature ws).Auto Trait Implementations§
impl<G = Open, E = NoRender> !RefUnwindSafe for Sites<G, E>
impl<G = Open, E = NoRender> !UnwindSafe for Sites<G, E>
impl<G, E> Forget for Sites<G, E>
impl<G, E> Freeze for Sites<G, E>
impl<G, E> Move for Sites<G, E>
impl<G, E> Send for Sites<G, E>
impl<G, E> Sync for Sites<G, E>
impl<G, E> Unpin for Sites<G, E>
impl<G, E> UnsafeUnpin for Sites<G, E>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<S> Service<HttpFamily> for Swhere
S: HttpService,
impl<S> Service<HttpFamily> for Swhere
S: HttpService,
Source§fn head(&self, head: &HttpHead<'_>, env: &mut Envelope) -> HeadAction
fn head(&self, head: &HttpHead<'_>, env: &mut Envelope) -> HeadAction
The head is complete; before admission and any body byte.
Source§fn call(
&self,
request: &HttpRequest<'_>,
env: &Envelope,
reply: &mut Reply<HttpFamily>,
) -> Outcome
fn call( &self, request: &HttpRequest<'_>, env: &Envelope, reply: &mut Reply<HttpFamily>, ) -> Outcome
The request is complete.
Source§fn upgraded(&self, env: &Envelope, conn: UpgradedConn)
fn upgraded(&self, env: &Envelope, conn: UpgradedConn)
After a switch response the service asked for left.