pavex::server

Struct Server

source
pub struct Server { /* private fields */ }
Expand description

An HTTP server to handle incoming connections for Pavex applications.
It handles both HTTP1 and HTTP2 connections.

§Example

use std::net::SocketAddr;
use pavex::server::Server;

let addr = SocketAddr::from(([127, 0, 0, 1], 8080));

Server::new()
    .bind(addr)
    .await?
    // Both the routing function and the application state will usually
    // be code-generated by Pavex, starting from your `Blueprint`.
    // You don't have to define them manually!
    .serve(router, application_state)
    // The `serve` method returns a `ServerHandle` that you can use to
    // interact with the server.
    // Calling `.await` on the handle lets you wait until the server
    // shuts down.
    .await;

§Configuration

Server::new returns a new Server with default configuration.
You can customize the server default settings by creating your own ServerConfiguration and invoking Server::set_config.

§Architecture

By default, Server::serve creates a worker per CPU core and distributes connection from an acceptor thread using a round-robin strategy.

Each worker has its own single-threaded [tokio] runtime—there is no work stealing across workers.
Each worker takes care to invoke your routing and request handling logic, with the help of [hyper].

Implementations§

source§

impl Server

source

pub fn new() -> Self

Create a new Server with default configuration.

source

pub fn set_config(self, config: ServerConfiguration) -> Self

Configure this Server according to the values set in the ServerConfiguration passed as input parameter. It will overwrite any previous configuration set on this Server.

If you want to retrieve the current configuration, use Server::get_config.

source

pub fn get_config(&self) -> &ServerConfiguration

Get a reference to the ServerConfiguration for this Server.

If you want to overwrite the existing configuration, use Server::set_config.

source

pub async fn bind(self, addr: SocketAddr) -> Result<Self>

Bind the server to the given address: the server will accept incoming connections from this address when started.
Binding an address may fail (e.g. if the address is already in use), therefore this method may return an error.

Check out Server::listen for an alternative binding mechanism as well as a discussion of the pros and cons of Server::bind vs Server::listen.

§Note

A Server can be bound to multiple addresses: just call this method multiple times with all the addresses you want to bind to.

§Example: bind one address
use std::net::SocketAddr;
use pavex::server::Server;

let addr = SocketAddr::from(([127, 0, 0, 1], 8080));

Server::new()
    .bind(addr)
    .await?
    // [...]
§Example: bind multiple addresses
use std::net::SocketAddr;
use pavex::server::Server;

let addr1 = SocketAddr::from(([127, 0, 0, 1], 8080));
let addr2 = SocketAddr::from(([127, 0, 0, 1], 4000));

Server::new()
    .bind(addr1)
    .await?
    .bind(addr2)
    .await?
    // [...]
source

pub fn listen(self, incoming: IncomingStream) -> Self

Ask the server to process incoming connections from the provided IncomingStream.

§Server::listen vs Server::bind

Server::bind only requires you to specify the address you want to listen at. The socket configuration is handled by the Server, with a set of reasonable default parameters. You have no access to the IncomingStream that gets bound to the address you specified.

Server::listen, instead, expects an IncomingStream.
You are free to configure the socket as you see please and the Server will just poll it for incoming connections.
It also allows you to interact with the bound IncomingStream directly

§Example: bind to a random port
use std::net::SocketAddr;
use pavex::server::{IncomingStream, Server};

// `0` is a special port: it tells the OS to assign us
// a random **unused** port
let addr = SocketAddr::from(([127, 0, 0, 1], 0));
let incoming = IncomingStream::bind(addr).await?;
// We can then retrieve the actual port we were assigned
// by the OS.
let addr = incoming.local_addr()?.to_owned();

Server::new()
    .listen(incoming);
    // [...]
§Example: set a custom socket backlog
use std::net::SocketAddr;
use socket2::Domain;
use pavex::server::{IncomingStream, Server};

// `0` is a special port: it tells the OS to assign us
// a random **unused** port
let addr = SocketAddr::from(([127, 0, 0, 1], 0));

let socket = socket2::Socket::new(
   Domain::for_address(addr),
   socket2::Type::STREAM,
   Some(socket2::Protocol::TCP),
)
.expect("Failed to create a socket");
socket.set_reuse_address(true)?;
socket.set_nonblocking(true)?;
socket.bind(&addr.into())?;
// The custom backlog!
socket.listen(2048_i32)?;

let listener = std::net::TcpListener::from(socket);
Server::new()
    .listen(listener.try_into()?)
    // [...]
§Note

A Server can listen to multiple streams of incoming connections: just call this method multiple times!

source

pub fn serve<HandlerFuture, ApplicationState>( self, handler: fn(_: Request<Incoming>, _: Option<ConnectionInfo>, _: ApplicationState) -> HandlerFuture, application_state: ApplicationState, ) -> ServerHandle
where HandlerFuture: Future<Output = Response> + 'static, ApplicationState: Clone + Send + Sync + 'static,

Start listening for incoming connections.

You must specify:

  • a handler function, which will be called for each incoming request;
  • the application state, the set of singleton components that will be available to your handler function.

Both the handler function and the application state are usually code-generated by Pavex starting from your Blueprint.

§Wait for the server to shut down

serve returns a ServerHandle.
Calling .await on the handle lets you wait until the server shuts down.

§Panics

This method will panic if the Server has no registered source of incoming connections, i.e. if you did not call Server::bind or Server::listen before calling serve.

Trait Implementations§

source§

impl Default for Server

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Server

§

impl RefUnwindSafe for Server

§

impl Send for Server

§

impl Sync for Server

§

impl Unpin for Server

§

impl UnwindSafe for Server

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.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> Same for T

source§

type Output = T

Should always be Self
source§

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

source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more