soma_http_server/middleware/
timeout.rs1use std::time::Duration;
12
13use axum::http::StatusCode;
14pub use tower_http::timeout::TimeoutLayer;
15
16pub fn timeout_layer(duration: Duration) -> TimeoutLayer {
20 TimeoutLayer::with_status_code(StatusCode::REQUEST_TIMEOUT, duration)
21}
22
23pub fn timeout_layer_with_status(status_code: StatusCode, duration: Duration) -> TimeoutLayer {
26 TimeoutLayer::with_status_code(status_code, duration)
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32 use axum::{body::Body, http::Request, routing::get, Router};
33 use tower::ServiceExt;
34
35 #[tokio::test]
36 async fn fast_handler_is_unaffected_by_a_generous_timeout() {
37 let app = Router::new()
38 .route("/", get(|| async { "ok" }))
39 .layer(timeout_layer(Duration::from_secs(30)));
40
41 let request = Request::builder().uri("/").body(Body::empty()).unwrap();
42 let response = app.oneshot(request).await.unwrap();
43 assert_eq!(response.status(), StatusCode::OK);
44 }
45
46 #[tokio::test]
47 async fn slow_handler_is_cut_off_by_the_timeout() {
48 let app = Router::new()
49 .route(
50 "/",
51 get(|| async {
52 tokio::time::sleep(Duration::from_millis(200)).await;
53 "too slow"
54 }),
55 )
56 .layer(timeout_layer(Duration::from_millis(20)));
57
58 let request = Request::builder().uri("/").body(Body::empty()).unwrap();
59 let response = app.oneshot(request).await.unwrap();
60 assert_eq!(response.status(), StatusCode::REQUEST_TIMEOUT);
61 }
62}