Skip to content

Commit 6d1f49a

Browse files
authored
Merge pull request #5737 from Turbo87/axum-route-blocking
Implement `block_traffic::block_routes` middleware
2 parents bbcc099 + 5b0a70b commit 6d1f49a

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

src/middleware.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ pub fn apply_axum_middleware(state: AppState, router: Router) -> Router {
7171
state.clone(),
7272
block_traffic::block_traffic,
7373
))
74+
.layer(from_fn_with_state(
75+
state.clone(),
76+
block_traffic::block_routes,
77+
))
7478
.layer(from_fn(head::support_head_requests))
7579
.layer(HandleErrorLayer::new(dummy_error_handler))
7680
.option_layer(

src/middleware/block_traffic.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
1111
use super::prelude::*;
1212
use crate::app::AppState;
13-
use axum::extract::State;
13+
use crate::util::errors::RouteBlocked;
14+
use axum::extract::{MatchedPath, State};
1415
use axum::middleware::Next;
1516
use axum::response::IntoResponse;
1617

@@ -53,3 +54,20 @@ pub async fn block_traffic<B>(
5354

5455
next.run(req).await
5556
}
57+
58+
/// Allow blocking individual routes by their pattern through the `BLOCKED_ROUTES`
59+
/// environment variable.
60+
pub async fn block_routes<B>(
61+
matched_path: Option<MatchedPath>,
62+
State(state): State<AppState>,
63+
req: http::Request<B>,
64+
next: Next<B>,
65+
) -> axum::response::Response {
66+
if let Some(matched_path) = matched_path {
67+
if state.config.blocked_routes.contains(matched_path.as_str()) {
68+
return RouteBlocked.into_response();
69+
}
70+
}
71+
72+
next.run(req).await
73+
}

src/util/errors/json.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use axum::response::{IntoResponse, Response};
2+
use axum::Json;
13
use std::fmt;
24

35
use super::{AppError, InternalAppErrorStatic};
@@ -286,3 +288,10 @@ impl fmt::Display for RouteBlocked {
286288
f.write_str("This route is temporarily blocked. See https://status.crates.io.")
287289
}
288290
}
291+
292+
impl IntoResponse for RouteBlocked {
293+
fn into_response(self) -> Response {
294+
let body = Json(json!({ "errors": [{ "detail": self.to_string() }] }));
295+
(StatusCode::SERVICE_UNAVAILABLE, body).into_response()
296+
}
297+
}

0 commit comments

Comments
 (0)