Skip to content

Commit 9b1e226

Browse files
committed
Use tower-http corslayer for handling cors
This pr addresses part of #941. it replaces the custom cors handling with tower-http corslayer
1 parent bc58d70 commit 9b1e226

4 files changed

Lines changed: 16 additions & 30 deletions

File tree

payjoin-mailroom/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ tokio-rustls-acme = { version = "0.9.0", features = ["axum"], optional = true }
7878
tokio-stream = { version = "0.1.17", features = ["net"] }
7979
tokio-tungstenite = { version = "0.27.0", optional = true }
8080
tower = "0.5.2"
81-
tower-http = { version = "0.6.11", features = ["trace"] }
81+
tower-http = { version = "0.6.6", features = ["cors","trace"] }
8282
tracing = "0.1.41"
8383
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "json"] }
8484
unicode-segmentation = "=1.12.0"

payjoin-mailroom/src/directory.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::task::{Context, Poll};
55

66
use anyhow::Result;
77
use axum::body::{Body, Bytes};
8-
use axum::http::header::{HeaderValue, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE};
8+
use axum::http::header::{HeaderValue, CONTENT_TYPE};
99
use axum::http::{Method, Request, Response, StatusCode, Uri};
1010
use http_body_util::BodyExt;
1111
use payjoin::directory::{ShortId, ShortIdError, ENCAPSULATED_MESSAGE_BYTES};
@@ -147,7 +147,7 @@ impl<D: Db> Service<D> {
147147
}
148148
}
149149

150-
let mut response = match (parts.method, path_segments.as_slice()) {
150+
let response = match (parts.method, path_segments.as_slice()) {
151151
(Method::POST, ["", ".well-known", "ohttp-gateway"]) =>
152152
self.handle_ohttp_gateway(body).await,
153153
(Method::GET, ["", ".well-known", "ohttp-gateway"]) =>
@@ -161,8 +161,6 @@ impl<D: Db> Service<D> {
161161
}
162162
.unwrap_or_else(|e| e.to_response());
163163

164-
// Allow CORS for third-party access
165-
response.headers_mut().insert(ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static("*"));
166164
Ok(response)
167165
}
168166

payjoin-mailroom/src/lib.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#[cfg(feature = "access-control")]
22
use axum::extract::connect_info::Connected;
33
use axum::extract::State;
4+
use axum::http::header::{CONTENT_LENGTH, CONTENT_TYPE};
45
use axum::http::Method;
56
use axum::response::{IntoResponse, Response};
67
#[cfg(feature = "access-control")]
@@ -11,6 +12,7 @@ use opentelemetry_sdk::metrics::SdkMeterProvider;
1112
use rand::Rng;
1213
use tokio_listener::{Listener, SystemOptions, UserOptions};
1314
use tower::{Service, ServiceBuilder};
15+
use tower_http::cors::{Any, CorsLayer};
1416
use tower_http::trace::TraceLayer;
1517
use tracing::info;
1618

@@ -378,14 +380,20 @@ fn build_app(services: Services) -> Router {
378380
#[cfg(feature = "access-control")]
379381
let geoip = services.geoip.clone();
380382

383+
let cors = CorsLayer::new()
384+
.allow_origin(Any)
385+
.allow_methods([Method::CONNECT, Method::GET, Method::OPTIONS, Method::POST])
386+
.allow_headers([CONTENT_TYPE, CONTENT_LENGTH]);
387+
381388
#[allow(unused_mut)]
382389
let mut router = Router::new()
383390
.fallback(route_request)
384391
.layer(
385392
ServiceBuilder::new()
386393
.layer(TraceLayer::new_for_http())
387394
.layer(axum::middleware::from_fn_with_state(metrics.clone(), track_metrics))
388-
.layer(axum::middleware::from_fn_with_state(metrics, track_connections)),
395+
.layer(axum::middleware::from_fn_with_state(metrics, track_connections))
396+
.layer(cors),
389397
)
390398
.with_state(services);
391399

@@ -421,17 +429,17 @@ async fn route_request(
421429
/// Determines if a request should be routed to the OHTTP relay service.
422430
///
423431
/// Routing rules:
424-
/// - `(OPTIONS, _)` => CORS preflight handling
425432
/// - `(CONNECT, _)` => OHTTP bootstrap tunneling
426433
/// - `(POST, "/")` => relay to default gateway (needed for backwards-compatibility only)
427434
/// - `(POST, /http(s)://...)` => RFC 9540 opt-in gateway specified in path
428435
/// - `(GET, /http(s)://...)` => OHTTP bootstrap via WebSocket with opt-in gateway
436+
/// - `(OPTIONS, _)` => CORS preflight handling (handled by `tower_http::cors::CorsLayer`)
429437
fn is_relay_request(req: &axum::extract::Request) -> bool {
430438
let method = req.method();
431439
let path = req.uri().path();
432440

433441
match (method, path) {
434-
(&Method::OPTIONS, _) | (&Method::CONNECT, _) | (&Method::POST, "/") => true,
442+
(&Method::CONNECT, _) | (&Method::POST, "/") => true,
435443
(&Method::POST, p) | (&Method::GET, p)
436444
if p.starts_with("/http://") || p.starts_with("/https://") =>
437445
true,

payjoin-mailroom/src/ohttp_relay/mod.rs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ use http::uri::Authority;
1010
use http_body_util::combinators::BoxBody;
1111
use http_body_util::{BodyExt, Empty, Full};
1212
use hyper::body::{Bytes, Incoming};
13-
use hyper::header::{
14-
HeaderValue, ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS,
15-
ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_LENGTH, CONTENT_TYPE,
16-
};
13+
use hyper::header::{HeaderValue, CONTENT_LENGTH, CONTENT_TYPE};
1714
use hyper::{Method, Request, Response};
1815
use hyper_rustls::builderstates::WantsSchemes;
1916
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
@@ -182,8 +179,7 @@ where
182179
let path = req.uri().path();
183180
let authority = req.uri().authority().cloned();
184181

185-
let mut res = match (&method, path) {
186-
(&Method::OPTIONS, _) => Ok(handle_preflight()),
182+
let res = match (&method, path) {
187183
(&Method::GET, "/health") => Ok(health_check().await),
188184
(&Method::POST, _) => match parse_gateway_uri(&method, path, authority, config).await {
189185
Ok(gateway_uri) => handle_ohttp_relay(req, config, gateway_uri).await,
@@ -206,7 +202,6 @@ where
206202
_ => Err(Error::NotFound),
207203
}
208204
.unwrap_or_else(|e| e.to_response());
209-
res.headers_mut().insert(ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static("*"));
210205
Ok(res)
211206
}
212207

@@ -255,21 +250,6 @@ fn parse_gateway_uri_from_path(path: &str, default: &GatewayUri) -> Result<Gatew
255250
}
256251
}
257252

258-
fn handle_preflight() -> Response<BoxBody<Bytes, hyper::Error>> {
259-
let mut res = Response::new(empty());
260-
*res.status_mut() = hyper::StatusCode::NO_CONTENT;
261-
res.headers_mut().insert(ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static("*"));
262-
res.headers_mut().insert(
263-
ACCESS_CONTROL_ALLOW_METHODS,
264-
HeaderValue::from_static("CONNECT, GET, OPTIONS, POST"),
265-
);
266-
res.headers_mut().insert(
267-
ACCESS_CONTROL_ALLOW_HEADERS,
268-
HeaderValue::from_static("Content-Type, Content-Length"),
269-
);
270-
res
271-
}
272-
273253
async fn health_check() -> Response<BoxBody<Bytes, hyper::Error>> { Response::new(empty()) }
274254

275255
#[instrument]

0 commit comments

Comments
 (0)