Skip to main content

ApiDefaults

Struct ApiDefaults 

Source
pub struct ApiDefaults { /* private fields */ }
Expand description

High-level configurable API defaults built from explicit Axum/Tower primitives.

ApiDefaults is a convenience builder for production-oriented middleware, not a hidden application runtime. ApiDefaults::production starts with request IDs, request context, production error envelopes, health routes, security headers, a Content-Length body limit, and a timeout enabled. Prometheus metrics and rate limiting are opt-in and only run when configured.

version and environment are stored as labels on this builder for callers that want to keep one deployment metadata object, but ApiDefaults::apply does not currently emit those labels to logs, metrics, headers, or health responses.

use axum::{Router, routing::get};
use nidus_http::{
    health::{HealthRegistry, HealthStatus},
    middleware::{ApiDefaults, PrometheusMetrics, RequestIdConfig},
};

let metrics = PrometheusMetrics::new();
let health = HealthRegistry::new()
    .ready_check_sync("database", || HealthStatus::up());

let router = Router::new().route("/users", get(list_users));
let app = ApiDefaults::production("users-api")
    .metrics(metrics.clone())
    .health(health)
    .request_ids(RequestIdConfig::production())
    .apply(router)
    .merge(metrics.routes());

Implementations§

Source§

impl ApiDefaults

Source

pub fn production(service_name: impl Into<String>) -> Self

Creates production defaults for a service.

Enabled by default:

Metrics and rate limiting are disabled unless Self::metrics or Self::rate_limit is called. The metrics middleware records requests, but apply does not merge the /metrics route; merge PrometheusMetrics::routes yourself when you want it exposed.

Source

pub fn service_name(&self) -> &str

Returns the service name attached to these defaults.

The current Self::apply implementation keeps this as builder metadata only; it is not emitted by any default middleware.

Source

pub fn version(self, version: impl Into<String>) -> Self

Sets a service version label.

This is metadata on the builder. Self::apply does not currently attach the version to metrics, health responses, logs, or response headers.

Source

pub fn environment(self, environment: impl Into<String>) -> Self

Sets an environment label.

This is metadata on the builder. Self::apply does not currently attach the environment to metrics, health responses, logs, or response headers.

Source

pub fn request_ids(self, config: RequestIdConfig) -> Self

Replaces request ID behavior.

Pass RequestIdConfig::development for permissive inbound validation during local development, or a custom config when you need a different header name or generator.

Source

pub fn without_request_ids(self) -> Self

Disables request ID middleware.

Source

pub fn without_request_context(self) -> Self

Disables request context middleware.

Source

pub fn without_error_envelope(self) -> Self

Disables production error envelopes.

Source

pub fn metrics(self, metrics: PrometheusMetrics) -> Self

Adds a Prometheus metrics collector.

This installs request lifecycle recording. It does not expose the collector’s /metrics route; merge PrometheusMetrics::routes into the router when you want scrape output.

Source

pub fn without_metrics(self) -> Self

Disables metrics middleware.

Source

pub fn health(self, health: HealthRegistry) -> Self

Replaces health routes.

The registry contributes /health/live and /health/ready routes before middleware layers are applied, so the same default security, timeout, and body/header handling applies to health responses too.

Source

pub fn without_health(self) -> Self

Disables health route helpers.

Source

pub fn rate_limit(self, config: RateLimitConfig) -> Self

Adds rate limiting.

Source

pub fn without_rate_limit(self) -> Self

Disables rate limiting.

Source

pub fn body_limit(self, max_bytes: u64) -> Self

Enables or replaces the request body size limit.

The built-in layer checks the declared Content-Length header only. It rejects declared oversized bodies with 413 Payload Too Large; it does not count streamed bytes when the header is absent or invalid (e.g. chunked-transfer clients). For a hard read-time cap across streaming bodies, also enable Self::streaming_body_limit.

Source

pub fn streaming_body_limit(self, max_bytes: usize) -> Self

Enables a streaming request body limit that counts bytes as they are read.

Unlike Self::body_limit (which inspects only the declared Content-Length), this wraps the request body and enforces max_bytes even when Content-Length is absent, closing the chunked-transfer bypass. The cap is applied as the downstream extractor or handler reads the body, so a request is rejected only once it actually reads past the limit. This is opt-in because it wraps every request body; pair it with Self::body_limit for an early Content-Length rejection plus a hard streaming cap.

Source

pub fn without_body_limit(self) -> Self

Disables request body size limiting.

Source

pub fn security_headers(self) -> Self

Enables response security headers.

Source

pub fn without_security_headers(self) -> Self

Disables response security headers.

Source

pub fn timeout(self, timeout: Duration) -> Self

Sets a default request timeout.

Requests whose inner service does not finish before this duration receive 408 Request Timeout with a plain-text request timed out body.

Source

pub fn without_timeout(self) -> Self

Disables timeout middleware.

Source

pub fn without_catch_panic(self) -> Self

Disables the panic-catching layer.

With it disabled, a panicking handler may abort the connection instead of yielding the production 500 envelope. It is enabled by Self::production.

Source

pub fn apply(self, router: Router) -> Router

Applies the configured defaults to an existing router.

Health routes are merged first. The effective inbound request order for the default production stack is (outermost first):

  1. security_headers_layer response wrapper
  2. validated_request_id_layer
  3. request_context_layer
  4. metrics, when configured
  5. ErrorEnvelopeLayer
  6. timeout_response_layer
  7. body_limit_layer Content-Length boundary
  8. rate limiting, when configured
  9. catch_panic_layer, when enabled (innermost, a handler panic is caught and surfaced as a 500 through every outer layer)
  10. route handlers

body_limit sits inside the request-id, metrics, and error-envelope layers so an oversized-body 413 is enveloped, metered, and carries a request id (consistent with how 408 timeouts are observed), rather than being rejected invisibly at the edge.

Order matters when adding route-specific layers. Layers installed on a route before calling apply run inside these defaults, so they can see the validated request ID and enriched crate::context::RequestContext, and their error responses can be wrapped by the production envelope.

Trait Implementations§

Source§

impl Clone for ApiDefaults

Source§

fn clone(&self) -> ApiDefaults

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

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<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

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> Provider for T
where T: Send + Sync + 'static,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
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