Merge branch 'fix/fix/remove-health-and-hardcode-https'
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(),
|
config: config_arc.clone(),
|
||||||
http_client,
|
http_client,
|
||||||
https_client,
|
https_client,
|
||||||
is_https: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let reload_handle = Arc::new(ConfigReloadHandle::new(
|
let reload_handle = Arc::new(ConfigReloadHandle::new(
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use axum::body::Body;
|
|||||||
use axum::extract::{ConnectInfo, State};
|
use axum::extract::{ConnectInfo, State};
|
||||||
use axum::http::{Request, StatusCode, Uri};
|
use axum::http::{Request, StatusCode, Uri};
|
||||||
use axum::response::{IntoResponse, Response};
|
use axum::response::{IntoResponse, Response};
|
||||||
use axum::routing::get;
|
|
||||||
use axum::Router;
|
use axum::Router;
|
||||||
use hyper_util::client::legacy::connect::HttpConnector;
|
use hyper_util::client::legacy::connect::HttpConnector;
|
||||||
use hyper_util::client::legacy::Client;
|
use hyper_util::client::legacy::Client;
|
||||||
@@ -22,11 +21,6 @@ pub struct ProxyState {
|
|||||||
pub config: Arc<ArcSwap<DynamicConfig>>,
|
pub config: Arc<ArcSwap<DynamicConfig>>,
|
||||||
pub http_client: Client<HttpConnector, Body>,
|
pub http_client: Client<HttpConnector, Body>,
|
||||||
pub https_client: Client<hyper_rustls::HttpsConnector<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(
|
async fn proxy_handler(
|
||||||
@@ -34,10 +28,6 @@ async fn proxy_handler(
|
|||||||
State(state): State<Arc<ProxyState>>,
|
State(state): State<Arc<ProxyState>>,
|
||||||
mut req: Request<Body>,
|
mut req: Request<Body>,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
if req.uri().path() == "/health" {
|
|
||||||
return StatusCode::OK.into_response();
|
|
||||||
}
|
|
||||||
|
|
||||||
let host = req
|
let host = req
|
||||||
.headers()
|
.headers()
|
||||||
.get(axum::http::header::HOST)
|
.get(axum::http::header::HOST)
|
||||||
@@ -55,7 +45,7 @@ async fn proxy_handler(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let host_owned = host.to_string();
|
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());
|
remove_hop_by_hop(req.headers_mut());
|
||||||
|
|
||||||
let upstream_scheme = site.upstream_scheme.clone();
|
let upstream_scheme = site.upstream_scheme.clone();
|
||||||
@@ -165,10 +155,7 @@ fn root_certs() -> rustls::RootCertStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn proxy_router(state: Arc<ProxyState>) -> Router {
|
pub fn proxy_router(state: Arc<ProxyState>) -> Router {
|
||||||
Router::new()
|
Router::new().fallback(proxy_handler).with_state(state)
|
||||||
.route("/health", get(health_handler))
|
|
||||||
.fallback(proxy_handler)
|
|
||||||
.with_state(state)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -195,7 +182,6 @@ mod tests {
|
|||||||
))),
|
))),
|
||||||
http_client: create_http_client(),
|
http_client: create_http_client(),
|
||||||
https_client: create_https_client(),
|
https_client: create_https_client(),
|
||||||
is_https: true,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,46 +200,6 @@ mod tests {
|
|||||||
req
|
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]
|
#[tokio::test]
|
||||||
async fn missing_host_returns_400() {
|
async fn missing_host_returns_400() {
|
||||||
let state = make_proxy_state(vec![SiteConfig {
|
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_str = remote_addr.ip().to_string();
|
||||||
let ip_value =
|
let ip_value =
|
||||||
HeaderValue::from_str(&ip_str).unwrap_or_else(|_| HeaderValue::from_static("0.0.0.0"));
|
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);
|
headers.insert(HeaderName::from_static("x-forwarded-for"), ip_value);
|
||||||
|
|
||||||
let proto_value = if is_https {
|
// X-Forwarded-Proto is always "https" because this proxy only forwards requests
|
||||||
HeaderValue::from_static("https")
|
// received on the TLS listener. The HTTP listener redirects to HTTPS and does not
|
||||||
} else {
|
// proxy requests, so X-Forwarded-Proto is never set for HTTP connections.
|
||||||
HeaderValue::from_static("http")
|
headers.insert(
|
||||||
};
|
HeaderName::from_static("x-forwarded-proto"),
|
||||||
headers.insert(HeaderName::from_static("x-forwarded-proto"), proto_value);
|
HeaderValue::from_static("https"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -84,7 +85,7 @@ mod tests {
|
|||||||
fn inject_proxy_headers_sets_x_real_ip() {
|
fn inject_proxy_headers_sets_x_real_ip() {
|
||||||
let mut h = HeaderMap::new();
|
let mut h = HeaderMap::new();
|
||||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 12345);
|
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");
|
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"),
|
HeaderValue::from_static("10.0.0.1, 10.0.0.2"),
|
||||||
);
|
);
|
||||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1)), 12345);
|
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");
|
assert_eq!(h.get("x-forwarded-for").unwrap(), "192.168.1.1");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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 mut h = HeaderMap::new();
|
||||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 443);
|
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");
|
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]
|
#[test]
|
||||||
fn inject_proxy_headers_preserves_host() {
|
fn inject_proxy_headers_preserves_host() {
|
||||||
let mut h = HeaderMap::new();
|
let mut h = HeaderMap::new();
|
||||||
h.insert("host", HeaderValue::from_static("example.com"));
|
h.insert("host", HeaderValue::from_static("example.com"));
|
||||||
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 443);
|
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");
|
assert_eq!(h.get("host").unwrap(), "example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user