pub struct WebServer<S = ()> { /* private fields */ }Expand description
An HTTP server.
Requires only an address, a port and an Environment. A sidecar that
serves nothing but its health check is a valid server; a full site adds
frontend. A single binary can run several of these
and drain them from one Shutdown.
Implementations§
Source§impl WebServer<()>
impl WebServer<()>
Sourcepub fn new(host: impl Into<String>, port: u16, environment: Environment) -> Self
pub fn new(host: impl Into<String>, port: u16, environment: Environment) -> Self
A server with no application state.
Sourcepub fn from_env() -> Result<Self, WebServerError>
pub fn from_env() -> Result<Self, WebServerError>
A server with no application state, read entirely from the environment.
WSB_ENVIRONMENT is required. WSB_HOST defaults to 127.0.0.1
locally and 0.0.0.0 in production; WSB_PORT defaults to
DEFAULT_PORT.
§Errors
WebServerError::Env if a variable is missing or malformed.
Source§impl<S> WebServer<S>
impl<S> WebServer<S>
Sourcepub fn with_state(
host: impl Into<String>,
port: u16,
environment: Environment,
app: S,
) -> Self
pub fn with_state( host: impl Into<String>, port: u16, environment: Environment, app: S, ) -> Self
A server carrying application state.
Sourcepub fn from_env_with_state(app: S) -> Result<Self, WebServerError>
pub fn from_env_with_state(app: S) -> Result<Self, WebServerError>
A server carrying application state, read entirely from the environment.
§Errors
WebServerError::Env if a variable is missing or malformed.
Sourcepub const fn body_limit(self, body_limit: usize) -> Self
pub const fn body_limit(self, body_limit: usize) -> Self
Caps request bodies. Defaults to DEFAULT_BODY_LIMIT.
The one size that genuinely varies: an image-upload endpoint and a landing page have nothing in common here.
Sourcepub fn root_dir(self, root_dir: impl Into<PathBuf>) -> Self
pub fn root_dir(self, root_dir: impl Into<PathBuf>) -> Self
Where html/, static/ and cache-buster.json are read from.
Defaults to the working directory.
Covers every file the server reads, at boot and per request. It does
not move the build-time asset pipeline, which always runs in the working
directory. Set it when the process cannot run from the built site: a
cargo test runs from its crate’s directory, not from bin/.
Sourcepub fn nest(self, path: &str, router: Router<WebServerState<S>>) -> Self
pub fn nest(self, path: &str, router: Router<WebServerState<S>>) -> Self
Nests a router under path.
Sourcepub fn merge(self, router: Router<WebServerState<S>>) -> Self
pub fn merge(self, router: Router<WebServerState<S>>) -> Self
Merges a router at the root.
Sourcepub fn nest_service<T>(self, path: &str, service: T) -> Selfwhere
T: Service<Request, Error = Infallible> + Clone + Send + Sync + 'static,
T::Response: IntoResponse,
T::Future: Send + 'static,
pub fn nest_service<T>(self, path: &str, service: T) -> Selfwhere
T: Service<Request, Error = Infallible> + Clone + Send + Sync + 'static,
T::Response: IntoResponse,
T::Future: Send + 'static,
Nests a service under path.
Sourcepub fn frontend(self, params: FrontendParams<S>) -> Self
pub fn frontend(self, params: FrontendParams<S>) -> Self
Declares this server a frontend: it serves HTML to humans.
This is the line between a site and a service, and everything downstream
hangs off it — the embedded layout, the icon set, the web manifest,
robots.txt, the sitemaps, analytics and browser error monitoring. A
server that never calls it needs none of them and boots clean.
Sourcepub fn feed(self, feed: Feed) -> Self
pub fn feed(self, feed: Feed) -> Self
Gives this site a feed, served as RSS 2.0, Atom 1.0 and JSON Feed.
Omittable, because most sites publish no stream: a site that never calls
this serves no feed documents and emits no autodiscovery links. Requires
frontend — calling this without it fails the
boot rather than silently serving nothing.
Entries are supplied rather than derived: a blog is a
dynamic_page_group, and a dynamic page
builds its template data per request, so there is nothing to read at
boot. They may be in any order and may exceed
MAX_FEED_ENTRIES; the newest survive.
Sourcepub fn into_router(self, shutdown: Shutdown) -> Result<Router, WebServerError>
pub fn into_router(self, shutdown: Shutdown) -> Result<Router, WebServerError>
The finished application, without binding a socket.
Exactly the router run serves — pages, the 404, the
well-known documents, the cache policy, tracing and the body limit — so
driving it with tower::ServiceExt::oneshot tests what ships. Boot
validation runs here too: Ok is a server run would have started.
It never runs the drain window or AppShutdown::on_shutdown;
triggering shutdown reaches only handlers that listen for it. A
.layer() added on top of the result is outside what this library
guarantees.
§Errors
WebServerError if the frontend cannot be assembled.
Sourcepub async fn run(self, shutdown: Shutdown) -> Result<(), WebServerError>where
S: AppShutdown,
pub async fn run(self, shutdown: Shutdown) -> Result<(), WebServerError>where
S: AppShutdown,
Binds, serves, and drains.
§Errors
WebServerError if the host is unparseable, the port cannot be bound,
the frontend cannot be assembled, or serving fails.
Auto Trait Implementations§
impl<S = ()> !RefUnwindSafe for WebServer<S>
impl<S = ()> !UnwindSafe for WebServer<S>
impl<S> Freeze for WebServer<S>
impl<S> Send for WebServer<S>
impl<S> Sync for WebServer<S>
impl<S> Unpin for WebServer<S>
impl<S> UnsafeUnpin for WebServer<S>where
S: UnsafeUnpin,
Router<WebServerState<S>>: UnsafeUnpin,
Option<FrontendParams<S>>: UnsafeUnpin,
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> ServiceExt for T
impl<T> ServiceExt for T
Source§fn propagate_header(self, header: HeaderName) -> PropagateHeader<Self>where
Self: Sized,
fn propagate_header(self, header: HeaderName) -> PropagateHeader<Self>where
Self: Sized,
Source§fn add_extension<T>(self, value: T) -> AddExtension<Self, T>where
Self: Sized,
fn add_extension<T>(self, value: T) -> AddExtension<Self, T>where
Self: Sized,
Source§fn map_request_body<F>(self, f: F) -> MapRequestBody<Self, F>where
Self: Sized,
fn map_request_body<F>(self, f: F) -> MapRequestBody<Self, F>where
Self: Sized,
Source§fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>where
Self: Sized,
fn map_response_body<F>(self, f: F) -> MapResponseBody<Self, F>where
Self: Sized,
Source§fn compression(self) -> Compression<Self>where
Self: Sized,
fn compression(self) -> Compression<Self>where
Self: Sized,
Source§fn decompression(self) -> Decompression<Self>where
Self: Sized,
fn decompression(self) -> Decompression<Self>where
Self: Sized,
Source§fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>where
Self: Sized,
fn trace_for_http(self) -> Trace<Self, SharedClassifier<ServerErrorsAsFailures>>where
Self: Sized,
Source§fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>where
Self: Sized,
fn trace_for_grpc(self) -> Trace<Self, SharedClassifier<GrpcErrorsAsFailures>>where
Self: Sized,
Source§fn follow_redirects(self) -> FollowRedirect<Self>where
Self: Sized,
fn follow_redirects(self) -> FollowRedirect<Self>where
Self: Sized,
Source§fn sensitive_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveRequestHeaders<SetSensitiveResponseHeaders<Self>>where
Self: Sized,
fn sensitive_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveRequestHeaders<SetSensitiveResponseHeaders<Self>>where
Self: Sized,
Source§fn sensitive_request_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveRequestHeaders<Self>where
Self: Sized,
fn sensitive_request_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveRequestHeaders<Self>where
Self: Sized,
Source§fn sensitive_response_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveResponseHeaders<Self>where
Self: Sized,
fn sensitive_response_headers(
self,
headers: impl IntoIterator<Item = HeaderName>,
) -> SetSensitiveResponseHeaders<Self>where
Self: Sized,
Source§fn override_request_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
fn override_request_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
Source§fn append_request_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
fn append_request_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
Source§fn insert_request_header_if_not_present<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
fn insert_request_header_if_not_present<M>(
self,
header_name: HeaderName,
make: M,
) -> SetRequestHeader<Self, M>where
Self: Sized,
Source§fn override_response_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
fn override_response_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
Source§fn append_response_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
fn append_response_header<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
Source§fn insert_response_header_if_not_present<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
fn insert_response_header_if_not_present<M>(
self,
header_name: HeaderName,
make: M,
) -> SetResponseHeader<Self, M>where
Self: Sized,
Source§fn set_request_id<M>(
self,
header_name: HeaderName,
make_request_id: M,
) -> SetRequestId<Self, M>where
Self: Sized,
M: MakeRequestId,
fn set_request_id<M>(
self,
header_name: HeaderName,
make_request_id: M,
) -> SetRequestId<Self, M>where
Self: Sized,
M: MakeRequestId,
Source§fn set_x_request_id<M>(self, make_request_id: M) -> SetRequestId<Self, M>where
Self: Sized,
M: MakeRequestId,
fn set_x_request_id<M>(self, make_request_id: M) -> SetRequestId<Self, M>where
Self: Sized,
M: MakeRequestId,
x-request-id as the header name. Read moreSource§fn propagate_request_id(
self,
header_name: HeaderName,
) -> PropagateRequestId<Self>where
Self: Sized,
fn propagate_request_id(
self,
header_name: HeaderName,
) -> PropagateRequestId<Self>where
Self: Sized,
Source§fn propagate_x_request_id(self) -> PropagateRequestId<Self>where
Self: Sized,
fn propagate_x_request_id(self) -> PropagateRequestId<Self>where
Self: Sized,
x-request-id as the header name. Read moreSource§fn catch_panic(self) -> CatchPanic<Self, DefaultResponseForPanic>where
Self: Sized,
fn catch_panic(self) -> CatchPanic<Self, DefaultResponseForPanic>where
Self: Sized,
500 Internal Server responses. Read moreSource§fn request_body_limit(self, limit: usize) -> RequestBodyLimit<Self>where
Self: Sized,
fn request_body_limit(self, limit: usize) -> RequestBodyLimit<Self>where
Self: Sized,
413 Payload Too Large responses. Read more