Remove /health route from main listener and hardcode X-Forwarded-Proto to https
- Remove health_handler and /health early return from proxy_handler - Remove /health route from proxy_router (now just fallback) - Remove is_https field from ProxyState struct - Remove is_https parameter from inject_proxy_headers, hardcode https - Add comment explaining why X-Forwarded-Proto is always https - Remove health_path_returns_200 and health_with_unknown_host tests - Update all inject_proxy_headers test calls to remove is_https param - Remove inject_proxy_headers_sets_x_forwarded_proto_http test
This commit is contained in:
@@ -74,7 +74,6 @@ async fn run_server(loaded_config: cli::LoadedConfig, config_path: &str) -> Resu
|
||||
config: config_arc.clone(),
|
||||
http_client,
|
||||
https_client,
|
||||
is_https: true,
|
||||
});
|
||||
|
||||
let reload_handle = Arc::new(ConfigReloadHandle::new(
|
||||
|
||||
@@ -7,7 +7,6 @@ use axum::body::Body;
|
||||
use axum::extract::{ConnectInfo, State};
|
||||
use axum::http::{Request, StatusCode, Uri};
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use hyper_util::client::legacy::connect::HttpConnector;
|
||||
use hyper_util::client::legacy::Client;
|
||||
@@ -22,11 +21,6 @@ pub struct ProxyState {
|
||||
pub config: Arc<ArcSwap<DynamicConfig>>,
|
||||
pub http_client: Client<HttpConnector, Body>,
|
||||
pub https_client: Client<hyper_rustls::HttpsConnector<HttpConnector>, Body>,
|
||||
pub is_https: bool,
|
||||
}
|
||||
|
||||
async fn health_handler() -> impl IntoResponse {
|
||||
StatusCode::OK
|
||||
}
|
||||
|
||||
async fn proxy_handler(
|
||||
@@ -34,10 +28,6 @@ async fn proxy_handler(
|
||||
State(state): State<Arc<ProxyState>>,
|
||||
mut req: Request<Body>,
|
||||
) -> Response {
|
||||
if req.uri().path() == "/health" {
|
||||
return StatusCode::OK.into_response();
|
||||
}
|
||||
|
||||
let host = req
|
||||
.headers()
|
||||
.get(axum::http::header::HOST)
|
||||
@@ -55,7 +45,7 @@ async fn proxy_handler(
|
||||
};
|
||||
|
||||
let host_owned = host.to_string();
|
||||
inject_proxy_headers(req.headers_mut(), remote_addr, state.is_https);
|
||||
inject_proxy_headers(req.headers_mut(), remote_addr);
|
||||
remove_hop_by_hop(req.headers_mut());
|
||||
|
||||
let upstream_scheme = site.upstream_scheme.clone();
|
||||
@@ -165,10 +155,7 @@ fn root_certs() -> rustls::RootCertStore {
|
||||
}
|
||||
|
||||
pub fn proxy_router(state: Arc<ProxyState>) -> Router {
|
||||
Router::new()
|
||||
.route("/health", get(health_handler))
|
||||
.fallback(proxy_handler)
|
||||
.with_state(state)
|
||||
Router::new().fallback(proxy_handler).with_state(state)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -195,7 +182,6 @@ mod tests {
|
||||
))),
|
||||
http_client: create_http_client(),
|
||||
https_client: create_https_client(),
|
||||
is_https: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -214,46 +200,6 @@ mod tests {
|
||||
req
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn health_path_returns_200_regardless_of_host() {
|
||||
let state = make_proxy_state(vec![SiteConfig {
|
||||
host: "example.com".to_string(),
|
||||
upstream: "127.0.0.1:8080".to_string(),
|
||||
upstream_scheme: "http".to_string(),
|
||||
upstream_connect_timeout_secs: 5,
|
||||
upstream_request_timeout_secs: 60,
|
||||
}]);
|
||||
let router = proxy_router(state);
|
||||
let req = make_request_with_connect_info(
|
||||
"GET",
|
||||
"/health",
|
||||
None,
|
||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12345),
|
||||
);
|
||||
let resp = router.oneshot(req).await.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn health_with_unknown_host_returns_200() {
|
||||
let state = make_proxy_state(vec![SiteConfig {
|
||||
host: "example.com".to_string(),
|
||||
upstream: "127.0.0.1:8080".to_string(),
|
||||
upstream_scheme: "http".to_string(),
|
||||
upstream_connect_timeout_secs: 5,
|
||||
upstream_request_timeout_secs: 60,
|
||||
}]);
|
||||
let router = proxy_router(state);
|
||||
let req = make_request_with_connect_info(
|
||||
"GET",
|
||||
"/health",
|
||||
Some("unknown.host"),
|
||||
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12345),
|
||||
);
|
||||
let resp = router.oneshot(req).await.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn missing_host_returns_400() {
|
||||
let state = make_proxy_state(vec![SiteConfig {
|
||||
|
||||
@@ -18,7 +18,7 @@ pub fn remove_hop_by_hop(headers: &mut HeaderMap) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn inject_proxy_headers(headers: &mut HeaderMap, remote_addr: SocketAddr, is_https: bool) {
|
||||
pub fn inject_proxy_headers(headers: &mut HeaderMap, remote_addr: SocketAddr) {
|
||||
let ip_str = remote_addr.ip().to_string();
|
||||
let ip_value =
|
||||
HeaderValue::from_str(&ip_str).unwrap_or_else(|_| HeaderValue::from_static("0.0.0.0"));
|
||||
@@ -27,12 +27,13 @@ pub fn inject_proxy_headers(headers: &mut HeaderMap, remote_addr: SocketAddr, is
|
||||
|
||||
headers.insert(HeaderName::from_static("x-forwarded-for"), ip_value);
|
||||
|
||||
let proto_value = if is_https {
|
||||
HeaderValue::from_static("https")
|
||||
} else {
|
||||
HeaderValue::from_static("http")
|
||||
};
|
||||
headers.insert(HeaderName::from_static("x-forwarded-proto"), proto_value);
|
||||
// X-Forwarded-Proto is always "https" because this proxy only forwards requests
|
||||
// received on the TLS listener. The HTTP listener redirects to HTTPS and does not
|
||||
// proxy requests, so X-Forwarded-Proto is never set for HTTP connections.
|
||||
headers.insert(
|
||||
HeaderName::from_static("x-forwarded-proto"),
|
||||
HeaderValue::from_static("https"),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -84,7 +85,7 @@ mod tests {
|
||||
fn inject_proxy_headers_sets_x_real_ip() {
|
||||
let mut h = HeaderMap::new();
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 12345);
|
||||
inject_proxy_headers(&mut h, addr, true);
|
||||
inject_proxy_headers(&mut h, addr);
|
||||
assert_eq!(h.get("x-real-ip").unwrap(), "192.168.1.1");
|
||||
}
|
||||
|
||||
@@ -96,32 +97,24 @@ mod tests {
|
||||
HeaderValue::from_static("10.0.0.1, 10.0.0.2"),
|
||||
);
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 12345);
|
||||
inject_proxy_headers(&mut h, addr, true);
|
||||
inject_proxy_headers(&mut h, addr);
|
||||
assert_eq!(h.get("x-forwarded-for").unwrap(), "192.168.1.1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inject_proxy_headers_sets_x_forwarded_proto_https() {
|
||||
fn inject_proxy_headers_sets_x_forwarded_proto_to_https() {
|
||||
let mut h = HeaderMap::new();
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 443);
|
||||
inject_proxy_headers(&mut h, addr, true);
|
||||
inject_proxy_headers(&mut h, addr);
|
||||
assert_eq!(h.get("x-forwarded-proto").unwrap(), "https");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inject_proxy_headers_sets_x_forwarded_proto_http() {
|
||||
let mut h = HeaderMap::new();
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 80);
|
||||
inject_proxy_headers(&mut h, addr, false);
|
||||
assert_eq!(h.get("x-forwarded-proto").unwrap(), "http");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inject_proxy_headers_preserves_host() {
|
||||
let mut h = HeaderMap::new();
|
||||
h.insert("host", HeaderValue::from_static("example.com"));
|
||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 443);
|
||||
inject_proxy_headers(&mut h, addr, true);
|
||||
inject_proxy_headers(&mut h, addr);
|
||||
assert_eq!(h.get("host").unwrap(), "example.com");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user