Skip to content

Commit 5d391cc

Browse files
committed
feat: configure request body limit
1 parent a163ae7 commit 5d391cc

File tree

4 files changed

+72
-11
lines changed

4 files changed

+72
-11
lines changed

rust/server/src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use tokio::signal::unix::SignalKind;
1717
use hyper::server::conn::http1;
1818
use hyper_util::rt::TokioIo;
1919

20-
use crate::vss_service::VssService;
20+
use crate::vss_service::{VssService, VssServiceConfig};
2121
use api::auth::{Authorizer, NoopAuthorizer};
2222
use api::kv_store::KvStore;
2323
use impls::postgres_store::{Certificate, PostgresPlaintextBackend, PostgresTlsBackend};
@@ -118,7 +118,10 @@ fn main() {
118118
match res {
119119
Ok((stream, _)) => {
120120
let io_stream = TokioIo::new(stream);
121-
let vss_service = VssService::new(Arc::clone(&store), Arc::clone(&authorizer));
121+
let vss_service_config = if let Some(req_body_size) = config.server_config.maximum_request_body_size {
122+
VssServiceConfig::new(req_body_size)
123+
} else {VssServiceConfig::default()};
124+
let vss_service = VssService::new(Arc::clone(&store), Arc::clone(&authorizer), vss_service_config);
122125
runtime.spawn(async move {
123126
if let Err(err) = http1::Builder::new().serve_connection(io_stream, vss_service).await {
124127
eprintln!("Failed to serve connection: {}", err);

rust/server/src/util/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub(crate) struct Config {
1010
pub(crate) struct ServerConfig {
1111
pub(crate) host: String,
1212
pub(crate) port: u16,
13+
pub(crate) maximum_request_body_size: Option<u32>,
1314
}
1415

1516
#[derive(Deserialize)]

rust/server/src/vss_service.rs

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,44 @@ use std::future::Future;
1818
use std::pin::Pin;
1919
use std::sync::Arc;
2020

21-
const MAXIMUM_REQUEST_BODY_SIZE: u16 = 65_535;
21+
const DEFAULT_MAXIMUM_REQUEST_BODY_SIZE: u32 = 20 * 1024 * 1024;
22+
23+
#[derive(Clone)]
24+
pub(crate) struct VssServiceConfig {
25+
maximum_request_body_size: u32,
26+
}
27+
28+
impl VssServiceConfig {
29+
pub fn new(maximum_request_body_size: u32) -> Self {
30+
let capped = maximum_request_body_size.min(DEFAULT_MAXIMUM_REQUEST_BODY_SIZE);
31+
if capped < maximum_request_body_size {
32+
eprintln!(
33+
"Warning: maximum_request_body_size {} exceeds limit, capped to {}.",
34+
maximum_request_body_size, DEFAULT_MAXIMUM_REQUEST_BODY_SIZE
35+
);
36+
}
37+
Self { maximum_request_body_size: capped }
38+
}
39+
}
40+
41+
impl Default for VssServiceConfig {
42+
fn default() -> Self {
43+
Self { maximum_request_body_size: DEFAULT_MAXIMUM_REQUEST_BODY_SIZE }
44+
}
45+
}
2246

2347
#[derive(Clone)]
2448
pub struct VssService {
2549
store: Arc<dyn KvStore>,
2650
authorizer: Arc<dyn Authorizer>,
51+
config: VssServiceConfig,
2752
}
2853

2954
impl VssService {
30-
pub(crate) fn new(store: Arc<dyn KvStore>, authorizer: Arc<dyn Authorizer>) -> Self {
31-
Self { store, authorizer }
55+
pub(crate) fn new(
56+
store: Arc<dyn KvStore>, authorizer: Arc<dyn Authorizer>, config: VssServiceConfig,
57+
) -> Self {
58+
Self { store, authorizer, config }
3259
}
3360
}
3461

@@ -43,22 +70,51 @@ impl Service<Request<Incoming>> for VssService {
4370
let store = Arc::clone(&self.store);
4471
let authorizer = Arc::clone(&self.authorizer);
4572
let path = req.uri().path().to_owned();
73+
let maximum_request_body_size = self.config.maximum_request_body_size;
4674

4775
Box::pin(async move {
4876
let prefix_stripped_path = path.strip_prefix(BASE_PATH_PREFIX).unwrap_or_default();
4977

5078
match prefix_stripped_path {
5179
"/getObject" => {
52-
handle_request(store, authorizer, req, handle_get_object_request).await
80+
handle_request(
81+
store,
82+
authorizer,
83+
req,
84+
maximum_request_body_size as usize,
85+
handle_get_object_request,
86+
)
87+
.await
5388
},
5489
"/putObjects" => {
55-
handle_request(store, authorizer, req, handle_put_object_request).await
90+
handle_request(
91+
store,
92+
authorizer,
93+
req,
94+
maximum_request_body_size as usize,
95+
handle_put_object_request,
96+
)
97+
.await
5698
},
5799
"/deleteObject" => {
58-
handle_request(store, authorizer, req, handle_delete_object_request).await
100+
handle_request(
101+
store,
102+
authorizer,
103+
req,
104+
maximum_request_body_size as usize,
105+
handle_delete_object_request,
106+
)
107+
.await
59108
},
60109
"/listKeyVersions" => {
61-
handle_request(store, authorizer, req, handle_list_object_request).await
110+
handle_request(
111+
store,
112+
authorizer,
113+
req,
114+
maximum_request_body_size as usize,
115+
handle_list_object_request,
116+
)
117+
.await
62118
},
63119
_ => {
64120
let error_msg = "Invalid request path.".as_bytes();
@@ -99,7 +155,7 @@ async fn handle_request<
99155
Fut: Future<Output = Result<R, VssError>> + Send,
100156
>(
101157
store: Arc<dyn KvStore>, authorizer: Arc<dyn Authorizer>, request: Request<Incoming>,
102-
handler: F,
158+
maximum_request_body_size: usize, handler: F,
103159
) -> Result<<VssService as Service<Request<Incoming>>>::Response, hyper::Error> {
104160
let (parts, body) = request.into_parts();
105161
let headers_map = parts
@@ -113,7 +169,7 @@ async fn handle_request<
113169
Err(e) => return Ok(build_error_response(e)),
114170
};
115171

116-
let limited_body = Limited::new(body, MAXIMUM_REQUEST_BODY_SIZE.into());
172+
let limited_body = Limited::new(body, maximum_request_body_size);
117173
let bytes = match limited_body.collect().await {
118174
Ok(body) => body.to_bytes(),
119175
Err(_) => {

rust/server/vss-server-config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[server_config]
22
host = "127.0.0.1"
33
port = 8080
4+
# maximum_request_body_size = 10485760 # Optional: maximum request body size in bytes capped at 20971520 (20 MB).
45

56
[postgresql_config]
67
username = "postgres" # Optional in TOML, can be overridden by env var `VSS_POSTGRESQL_USERNAME`

0 commit comments

Comments
 (0)