Expand description
Shared Axum middleware, HTTP telemetry, and public errors for Baukit services.
finalize applies one consistent request lifecycle: standard extractor and
routing errors, request identity, W3C trace extraction and response
propagation, route-template spans, HTTP RED metrics, panic and timeout
envelopes, body and concurrency limits, and explicit CORS.
§Example
use axum::{Router, routing::get};
use baukit_http::{HttpOptions, RequestId, finalize};
async fn hello(request_id: RequestId) -> String {
format!("hello from request {}", request_id.as_str())
}
let options = HttpOptions::default()
.with_allowed_origins(["https://app.example.com"])?
.with_additional_allowed_headers(["accept", "x-webhook-secret"])?
.with_json_rejection_code("invalid_json")?;
let app = finalize(Router::new().route("/hello", get(hello)), options);pagination adds keyset pagination whose opaque cursors are bound to the
request filters, and classify_http_status turns an upstream response into
a RetryClass so outbound clients share one retry policy.
§Paginated handler
use axum::extract::Query;
use baukit_http::{ApiError, Page, PageKey, PageParams, ResponseEnvelope};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Deserialize)]
struct ListQuery {
limit: Option<i64>,
cursor: Option<String>,
category: Option<String>,
}
#[derive(Serialize)]
struct Filters {
category: Option<String>,
}
#[derive(Clone, Serialize)]
struct Item {
id: Uuid,
name: String,
}
#[derive(Serialize)]
struct PageMeta {
next_cursor: Option<String>,
}
async fn list(
Query(query): Query<ListQuery>,
) -> Result<ResponseEnvelope<Vec<Item>, PageMeta>, ApiError> {
let params = PageParams::new(query.limit, query.cursor)?;
let filters = Filters { category: query.category };
let after = params.decode_cursor(&filters)?;
// Fetch `params.fetch_limit()?` rows ordered by (name, id), starting
// after `after.page_key::<String>()?` when it is present.
let _ = after;
let rows: Vec<Item> = Vec::new();
let page = Page::from_rows(rows, ¶ms, &filters, |item| {
PageKey::new(item.name.clone(), item.id)
})?;
Ok(ResponseEnvelope::new(
page.items,
PageMeta { next_cursor: page.next_cursor },
))
}This crate records HTTP metrics through the metrics facade and never
installs a recorder. The recorder owner must configure
http_request_duration_seconds with DURATION_BUCKETS.
Re-exports§
pub use pagination::Cursor;pub use pagination::DEFAULT_PAGE_LIMIT;pub use pagination::MAX_PAGE_LIMIT;pub use pagination::Page;pub use pagination::PageKey;pub use pagination::PageParams;pub use pagination::PaginationError;pub use retry::RetryClass;pub use retry::RetryHeaderOptions;pub use retry::classify_http_status;pub use retry::classify_http_status_with_options;pub use retry::classify_transport_error;pub use retry::retry_after_from_headers;pub use retry::retry_after_from_headers_at;pub use retry::retry_after_from_headers_with_options;pub use retry::retry_after_from_headers_with_options_at;pub use metrics;
Modules§
- pagination
- Keyset pagination with opaque cursors bound to the request filters.
- retry
- Classification of upstream HTTP responses and transport failures.
Structs§
- ApiError
- A safe public API error rendered in Baukit’s standard JSON envelope.
- ApiJson
- A JSON body extractor whose rejections use Baukit’s standard error envelope.
- ApiPath
- Backward-compatible name for
Path. A route-path extractor whose rejections use Baukit’s standard error envelope. - ApiQuery
- Backward-compatible name for
Query. A query-string extractor whose rejections use Baukit’s standard error envelope. - Error
Body - The error body nested inside
ErrorEnvelope. - Error
Envelope - The shared public error response envelope.
- Http
Options - Configuration for the shared HTTP layer stack.
- Path
- A route-path extractor whose rejections use Baukit’s standard error envelope.
- Query
- A query-string extractor whose rejections use Baukit’s standard error envelope.
- Request
Id - A request identifier accepted from the client or generated as a UUID.
- Response
Envelope - A fully typed success-response envelope.
- Rfc3339
Date Time - An API timestamp with one JSON and OpenAPI representation: an RFC 3339
string with OpenAPI
date-timeformat.
Enums§
- Http
Options Error - An invalid shared HTTP layer option.
Constants§
- DURATION_
BUCKETS - Required Prometheus buckets for
HTTP_REQUEST_DURATION_SECONDS, in seconds. - HTTP_
REQUESTS_ IN_ FLIGHT - Gauge metric for active HTTP requests, labeled
methodandroute. - HTTP_
REQUESTS_ TOTAL - Counter metric for completed HTTP requests, labeled
method,route, andstatus. - HTTP_
REQUEST_ DURATION_ SECONDS - Histogram metric for HTTP request seconds, labeled
method,route, andstatus. - X_
REQUEST_ ID - The standard request ID header.
Functions§
- extract_
trace_ context - Extracts W3C trace context from request headers using the global propagator.
- finalize
- Finalizes a public router with standard 404/405 envelopes and HTTP layers.
- inject_
current_ trace_ context - Injects the current tracing span’s OpenTelemetry context into outbound headers.
- inject_
trace_ context - Injects
contextinto outbound headers using the global W3C propagator. - layers
- Applies the complete Baukit HTTP defaults stack to an Axum router.