Skip to main content

Server

Struct Server 

Source
#[non_exhaustive]
pub struct Server { pub app_state: Arc<AppState>, pub http_addr: Option<SocketAddr>, pub https_addr: Option<SocketAddr>, /* private fields */ }
Expand description

HTTP(S) server.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§app_state: Arc<AppState>

RFC 071: shared via Arc, not cloned per request. HTTP and HTTPS listeners each hold a clone of this Arc (a pointer bump, not a clone of AppState’s contents) rather than each keeping its own independent copy of the state as before.

§http_addr: Option<SocketAddr>§https_addr: Option<SocketAddr>

Implementations§

Source§

impl Server

Source

pub async fn new(config: Config) -> ServerResult<Self>

Resolve listener addresses and build the server shell.

Also compiles Rhai middlewares listed in config.service.middlewares_file_paths. Compilation happens here (not in the config crate) because the compiled artefact is a runtime object — see the server-level module docstring.

§TLS material is loaded here, eagerly (RFC 074 S-08)

If [listener.tls] is present, its cert/key are loaded and the TLS config built as part of this call — not lazily, the first time bind_https runs. A malformed PEM (the file exists — apimock_config::Config::new already rejected a missing one — but doesn’t parse) now fails Server::new itself, which App::new propagates with ?, which main propagates with ?: the process exits before main ever reaches app.server.start().await, so no listener binds, HTTP included. Building this lazily inside bind_https — the previous behaviour — let https_start log the error and return while any separately-configured HTTP listener kept serving, which is exactly the silent HTTP-only degradation this RFC exists to close.

Source

pub async fn start(&self)

Start both listeners (whichever are configured) and block.

Source

pub async fn bind_http(&self) -> ServerResult<Option<TcpListener>>

Bind the HTTP listener without accepting connections yet.

Returns Ok(None) if no HTTP listener is configured, Ok(Some(_)) on a successful bind, or Err if the bind itself failed — this is the piece http_start used to swallow via log::error! + early return, with no way for a caller to observe it.

Splitting bind from serve exists for callers (namely the integration-test harness) that need the two to be separate steps: bind, read back the real port via local_addr() (useful when [listener].port is 0 and the OS assigns one), then hand the same listener to Server::serve_http. Because it’s the same listener throughout, there is no window between “port known” and “port held” for another process to take it.

Source

pub async fn serve_http(&self, listener: TcpListener)

Accept connections forever on an already-bound HTTP listener.

Source

pub async fn bind_https( &self, ) -> ServerResult<Option<(TcpListener, TlsAcceptor)>>

Bind the HTTPS listener without accepting connections yet. See Server::bind_http for why this is split from serving.

TLS material is already loaded and validated by this point — see Server::new’s doc comment — so the only failure left here is the socket bind itself (e.g. the port is in use).

Source

pub async fn serve_https(&self, listener: TcpListener, acceptor: TlsAcceptor)

Accept connections forever on an already-bound HTTPS listener.

§RFC 074 S-07: handshake timeout and connection cap

A connection that opens and never completes its TLS handshake is dropped after handshake_timeout — previously nothing bounded this, so such a connection held its task (and the OS socket) forever. Concurrency is bounded by a Semaphore sized to max_connections: a permit is acquired before spawning the per-connection task, so once max_connections connections are in flight, listener.accept() keeps accepting into the kernel backlog but this loop stops handing new connections to the TLS handshake until a permit frees — the server recovers as soon as existing connections close, rather than needing a restart.

Auto Trait Implementations§

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self>

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