Skip to main content

fraiseql_server/middleware/
header_limits.rs

1//! HTTP header count and size limit middleware.
2//!
3//! Rejects requests that exceed configured header count or total header byte
4//! limits, preventing header-flooding `DoS` attacks that exhaust memory.
5
6use axum::{
7    body::Body,
8    extract::Request,
9    http::StatusCode,
10    middleware::Next,
11    response::{IntoResponse, Response},
12};
13use tracing::warn;
14
15/// Middleware that enforces header count and total header byte size limits.
16///
17/// Returns 431 Request Header Fields Too Large when either limit is exceeded.
18pub async fn header_limits_middleware(
19    request: Request<Body>,
20    next: Next,
21    max_header_count: usize,
22    max_header_bytes: usize,
23) -> Response {
24    let headers = request.headers();
25    let header_count = headers.len();
26
27    if header_count > max_header_count {
28        warn!(header_count, max_header_count, "Request rejected: too many headers");
29        return (StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE, "Too many request headers")
30            .into_response();
31    }
32
33    let total_bytes: usize =
34        headers.iter().map(|(name, value)| name.as_str().len() + value.len()).sum();
35
36    if total_bytes > max_header_bytes {
37        warn!(total_bytes, max_header_bytes, "Request rejected: headers too large");
38        return (StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE, "Request headers too large")
39            .into_response();
40    }
41
42    next.run(request).await
43}