Skip to content
This repository was archived by the owner on Jun 21, 2024. It is now read-only.

Commit 1ed0af5

Browse files
committed
Make max_body_size configurable via env, drop custom check, use 413
1 parent cf9b82d commit 1ed0af5

File tree

7 files changed

+22
-25
lines changed

7 files changed

+22
-25
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ members = [
1313

1414
[workspace.lints.rust]
1515
# See https://doc.rust-lang.org/stable/rustc/lints/listing/allowed-by-default.html
16-
unsafe_code = "forbid" # forbid cannot be ignored with an annotation
16+
unsafe_code = "forbid" # forbid cannot be ignored with an annotation
1717
unstable_features = "forbid"
1818
macro_use_extern_crate = "forbid"
1919
let_underscore_drop = "deny"
@@ -69,7 +69,7 @@ time = { version = "0.3.20", features = [
6969
thiserror = { version = "1.0" }
7070
tokio = { version = "1.34.0", features = ["full"] }
7171
tower = "0.4.13"
72-
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
72+
tower-http = { version = "0.5.2", features = ["cors", "limit", "trace"] }
7373
tracing = "0.1.40"
7474
tracing-subscriber = "0.3.18"
7575
url = { version = "2.5.0 " }

hook-api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ serde_json = { workspace = true }
1919
sqlx = { workspace = true }
2020
tokio = { workspace = true }
2121
tower = { workspace = true }
22+
tower-http = { workspace = true }
2223
tracing = { workspace = true }
2324
tracing-subscriber = { workspace = true }
2425
url = { workspace = true }

hook-api/src/config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ pub struct Config {
1616

1717
#[envconfig(default = "100")]
1818
pub max_pg_connections: u32,
19+
20+
#[envconfig(default = "5000000")]
21+
pub max_body_size: usize,
1922
}
2023

2124
impl Config {

hook-api/src/handlers/app.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
use axum::{extract::DefaultBodyLimit, routing, Router};
1+
use axum::{routing, Router};
2+
use tower_http::limit::RequestBodyLimitLayer;
23

34
use hook_common::pgqueue::PgQueue;
45

56
use super::webhook;
67

7-
pub fn add_routes(router: Router, pg_pool: PgQueue) -> Router {
8+
pub fn add_routes(router: Router, pg_pool: PgQueue, max_body_size: usize) -> Router {
89
router
910
.route("/", routing::get(index))
1011
.route("/_readiness", routing::get(index))
@@ -13,7 +14,7 @@ pub fn add_routes(router: Router, pg_pool: PgQueue) -> Router {
1314
"/webhook",
1415
routing::post(webhook::post)
1516
.with_state(pg_pool)
16-
.layer(DefaultBodyLimit::disable()),
17+
.layer(RequestBodyLimitLayer::new(max_body_size)),
1718
)
1819
}
1920

@@ -37,7 +38,7 @@ mod tests {
3738
async fn index(db: PgPool) {
3839
let pg_queue = PgQueue::new_from_pool("test_index", db).await;
3940

40-
let app = add_routes(Router::new(), pg_queue);
41+
let app = add_routes(Router::new(), pg_queue, 1_000_000);
4142

4243
let response = app
4344
.oneshot(Request::builder().uri("/").body(Body::empty()).unwrap())

hook-api/src/handlers/webhook.rs

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ use hook_common::pgqueue::{NewJob, PgQueue};
99
use serde::Serialize;
1010
use tracing::{debug, error};
1111

12-
pub const MAX_BODY_SIZE: usize = 5_000_000;
13-
1412
#[derive(Serialize, Deserialize)]
1513
pub struct WebhookPostResponse {
1614
#[serde(skip_serializing_if = "Option::is_none")]
@@ -37,15 +35,6 @@ pub async fn post(
3735
) -> Result<Json<WebhookPostResponse>, (StatusCode, Json<WebhookPostResponse>)> {
3836
debug!("received payload: {:?}", payload);
3937

40-
if payload.parameters.body.len() > MAX_BODY_SIZE {
41-
return Err((
42-
StatusCode::BAD_REQUEST,
43-
Json(WebhookPostResponse {
44-
error: Some("body too large".to_owned()),
45-
}),
46-
));
47-
}
48-
4938
let url_hostname = get_hostname(&payload.parameters.url)?;
5039
// We could cast to i32, but this ensures we are not wrapping.
5140
let max_attempts = i32::try_from(payload.max_attempts).map_err(|_| {
@@ -125,11 +114,13 @@ mod tests {
125114

126115
use crate::handlers::app::add_routes;
127116

117+
const MAX_BODY_SIZE: usize = 1_000_000;
118+
128119
#[sqlx::test(migrations = "../migrations")]
129120
async fn webhook_success(db: PgPool) {
130121
let pg_queue = PgQueue::new_from_pool("test_index", db).await;
131122

132-
let app = add_routes(Router::new(), pg_queue);
123+
let app = add_routes(Router::new(), pg_queue, MAX_BODY_SIZE);
133124

134125
let mut headers = collections::HashMap::new();
135126
headers.insert("Content-Type".to_owned(), "application/json".to_owned());
@@ -171,7 +162,7 @@ mod tests {
171162
async fn webhook_bad_url(db: PgPool) {
172163
let pg_queue = PgQueue::new_from_pool("test_index", db).await;
173164

174-
let app = add_routes(Router::new(), pg_queue);
165+
let app = add_routes(Router::new(), pg_queue, MAX_BODY_SIZE);
175166

176167
let response = app
177168
.oneshot(
@@ -208,7 +199,7 @@ mod tests {
208199
async fn webhook_payload_missing_fields(db: PgPool) {
209200
let pg_queue = PgQueue::new_from_pool("test_index", db).await;
210201

211-
let app = add_routes(Router::new(), pg_queue);
202+
let app = add_routes(Router::new(), pg_queue, MAX_BODY_SIZE);
212203

213204
let response = app
214205
.oneshot(
@@ -229,7 +220,7 @@ mod tests {
229220
async fn webhook_payload_not_json(db: PgPool) {
230221
let pg_queue = PgQueue::new_from_pool("test_index", db).await;
231222

232-
let app = add_routes(Router::new(), pg_queue);
223+
let app = add_routes(Router::new(), pg_queue, MAX_BODY_SIZE);
233224

234225
let response = app
235226
.oneshot(
@@ -250,9 +241,9 @@ mod tests {
250241
async fn webhook_payload_body_too_large(db: PgPool) {
251242
let pg_queue = PgQueue::new_from_pool("test_index", db).await;
252243

253-
let app = add_routes(Router::new(), pg_queue);
244+
let app = add_routes(Router::new(), pg_queue, MAX_BODY_SIZE);
254245

255-
let bytes: Vec<u8> = vec![b'a'; 5_000_000 * 2];
246+
let bytes: Vec<u8> = vec![b'a'; MAX_BODY_SIZE + 1];
256247
let long_string = String::from_utf8_lossy(&bytes);
257248

258249
let response = app
@@ -283,6 +274,6 @@ mod tests {
283274
.await
284275
.unwrap();
285276

286-
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
277+
assert_eq!(response.status(), StatusCode::PAYLOAD_TOO_LARGE);
287278
}
288279
}

hook-api/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async fn main() {
3434
.await
3535
.expect("failed to initialize queue");
3636

37-
let app = handlers::add_routes(Router::new(), pg_queue);
37+
let app = handlers::add_routes(Router::new(), pg_queue, config.max_body_size);
3838
let app = setup_metrics_routes(app);
3939

4040
match listen(app, config.bind()).await {

0 commit comments

Comments
 (0)