swadhinbiswas

[email protected]
2026-07-25 15:36:14 +0600 committed NaN years ago
cb8f7c6
commit cb8f7c6
2 files changed
+26 -13
▼crates/justapi-core/src/middleware.rs
+18-8
8
8
use async_trait::async_trait;
9
9
use futures::future::BoxFuture;
10
10
use governor::clock::Clock;
11
+use http::HeaderValue;
11
12
use http_body_util::combinators::UnsyncBoxBody;
12
13
use http_body_util::BodyExt;
13
14
use hyper::body::{Bytes, Incoming};
270
271
let add_vary = !allow_all;
271
272
272
273
if req.method() == Method::OPTIONS {
274
+ let origin_val: HeaderValue = matched_origin
275
+ .parse()
276
+ .map_err(|e| anyhow::anyhow!("invalid CORS origin header value: {e}"))?;
273
277
let mut builder = Response::builder()
274
278
.status(StatusCode::NO_CONTENT)
275
- .header("access-control-allow-origin", matched_origin)
279
+ .header("access-control-allow-origin", origin_val)
276
280
.header("access-control-allow-methods", &self.allow_methods)
277
281
.header("access-control-allow-headers", &self.allow_headers)
278
282
.header("access-control-max-age", &self.max_age);
298
302
}
299
303
300
304
let mut resp = next.run(req).await?;
301
- resp.headers_mut().insert("access-control-allow-origin", matched_origin.parse().unwrap());
305
+ let origin_val: HeaderValue = matched_origin
306
+ .parse()
307
+ .map_err(|e| anyhow::anyhow!("invalid CORS origin header value: {e}"))?;
308
+ resp.headers_mut().insert("access-control-allow-origin", origin_val);
302
309
if self.allow_credentials {
303
- resp.headers_mut().insert("access-control-allow-credentials", "true".parse().unwrap());
310
+ resp.headers_mut()
311
+ .insert("access-control-allow-credentials", HeaderValue::from_static("true"));
304
312
}
305
313
if !self.expose_headers.is_empty() {
306
- resp.headers_mut().insert(
307
- "access-control-expose-headers",
308
- self.expose_headers.join(", ").parse().unwrap(),
309
- );
314
+ let val: HeaderValue = self
315
+ .expose_headers
316
+ .join(", ")
317
+ .parse()
318
+ .map_err(|e| anyhow::anyhow!("invalid CORS expose-headers value: {e}"))?;
319
+ resp.headers_mut().insert("access-control-expose-headers", val);
310
320
}
311
321
if add_vary {
312
- resp.headers_mut().insert("vary", "Origin".parse().unwrap());
322
+ resp.headers_mut().insert("vary", HeaderValue::from_static("Origin"));
313
323
}
314
324
Ok(resp)
315
325
}
316
326
▼crates/justapi-core/src/server/mod.rs
+8-5
1297
1297
// Bound concurrent connections: a permit is held for the life of
1298
1298
// the connection so a flood of accepts can't exhaust FDs/memory
1299
1299
// (connection-flood / slowloris resource exhaustion).
1300
- let _permit = conn_semaphore.acquire_owned().await.expect("connection semaphore closed");
1300
+ let Ok(_permit) = conn_semaphore.acquire_owned().await else {
1301
+ tracing::warn!("connection semaphore closed, dropping connection");
1302
+ return;
1303
+ };
1301
1304
let io = TokioIo::new(stream);
1302
1305
let token_clone = shutdown.clone();
1303
1306
let spawn_metrics = metrics.clone();
1987
1990
let conn_semaphore = conn_semaphore.clone();
1988
1991
connections.spawn(async move {
1989
1992
// Bound concurrent connections (see serve_http for rationale).
1990
- let _permit = conn_semaphore
1991
- .acquire_owned()
1992
- .await
1993
- .expect("connection semaphore closed");
1993
+ let Ok(_permit) = conn_semaphore.acquire_owned().await else {
1994
+ tracing::warn!("TLS connection semaphore closed, dropping connection");
1995
+ return;
1996
+ };
1994
1997
match acceptor.accept(stream).await {
1995
1998
Ok(tls_stream) => {
1996
1999
let io = TokioIo::new(tls_stream);
1997
2000