refactor: single refusal shape with openapi contract test
This commit is contained in:
@@ -1,14 +1,21 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use axum::{Router, routing};
|
||||
use axum_governor::{GovernorConfigBuilder, GovernorLayer, Quota, extractor::PeerIp};
|
||||
use axum::{Router, http::StatusCode, routing};
|
||||
use axum_governor::{
|
||||
GovernorConfigBuilder, GovernorLayer, Quota, RejectionReason, extractor::PeerIp,
|
||||
};
|
||||
use tower_http::{
|
||||
cors::CorsLayer,
|
||||
services::{ServeDir, ServeFile},
|
||||
trace::TraceLayer,
|
||||
};
|
||||
|
||||
use crate::{api, federation, html, state::AppState};
|
||||
use crate::{
|
||||
api,
|
||||
errors::{INTERNAL, RATE_LIMITED, refuse},
|
||||
federation, html,
|
||||
state::AppState,
|
||||
};
|
||||
|
||||
pub fn build_router(state: AppState, ap_router: Router) -> Router {
|
||||
let rate_limit = state.app_ctx.config.rate_limit;
|
||||
@@ -41,6 +48,22 @@ async fn health_handler() -> axum::Json<serde_json::Value> {
|
||||
axum::Json(serde_json::json!({ "status": "ok" }))
|
||||
}
|
||||
|
||||
/// JSON API rate-limit refusals use the one error shape.
|
||||
fn slow_down(reason: RejectionReason) -> axum::response::Response {
|
||||
match reason {
|
||||
RejectionReason::QuotaExceeded { .. } => refuse(
|
||||
StatusCode::TOO_MANY_REQUESTS,
|
||||
RATE_LIMITED,
|
||||
"too many requests: slow down and try again shortly",
|
||||
),
|
||||
RejectionReason::KeyExtractionFailed(_) => refuse(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
INTERNAL,
|
||||
"the caller could not be identified for rate limiting",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn per_minute(n: u64) -> Quota {
|
||||
let n = NonZeroU32::new(n.clamp(1, u32::MAX as u64) as u32).unwrap();
|
||||
Quota::requests_per_minute(n)
|
||||
@@ -111,6 +134,7 @@ fn api_routes(rate_limit: u64, cors_origins: &str) -> Router<AppState> {
|
||||
.with_extractor(PeerIp::default())
|
||||
.expect_connect_info()
|
||||
.quota_default(per_minute(rate_limit))
|
||||
.error_handler(slow_down)
|
||||
.finish()
|
||||
.unwrap();
|
||||
|
||||
@@ -120,6 +144,7 @@ fn api_routes(rate_limit: u64, cors_origins: &str) -> Router<AppState> {
|
||||
.with_extractor(PeerIp::default())
|
||||
.expect_connect_info()
|
||||
.quota_default(per_minute(rate_limit / 4))
|
||||
.error_handler(slow_down)
|
||||
.finish()
|
||||
.unwrap();
|
||||
let webhook_routes = api::webhook_router().layer(GovernorLayer::new(webhook_cfg));
|
||||
|
||||
Reference in New Issue
Block a user