send x-forwarded-proto header from proxy

This commit is contained in:
Brian Picciano 2023-07-16 17:54:56 +02:00
parent b060cafa8e
commit 8f74757f23
4 changed files with 26 additions and 6 deletions

View File

@ -73,6 +73,7 @@ domain:
#proxy.example.com: #proxy.example.com:
# kind: proxy # kind: proxy
# url: "http://some.other.service.com" # url: "http://some.other.service.com"
# public: false
service: service:

View File

@ -1,4 +1,5 @@
use crate::error::unexpected::{self, Mappable}; use crate::error::unexpected::{self, Mappable};
use http::header::HeaderValue;
use std::{net, str::FromStr}; use std::{net, str::FromStr};
// proxy is a special case because it is so tied to the underlying protocol that a request is // proxy is a special case because it is so tied to the underlying protocol that a request is
@ -9,6 +10,7 @@ pub async fn serve_http_request(
client_ip: net::IpAddr, client_ip: net::IpAddr,
proxy_url: &str, proxy_url: &str,
mut req: hyper::Request<hyper::Body>, mut req: hyper::Request<hyper::Body>,
req_is_https: bool,
) -> unexpected::Result<hyper::Response<hyper::Body>> { ) -> unexpected::Result<hyper::Response<hyper::Body>> {
let parsed_proxy_url = let parsed_proxy_url =
http::Uri::from_str(proxy_url).or_unexpected_while("parsing proxy url")?; http::Uri::from_str(proxy_url).or_unexpected_while("parsing proxy url")?;
@ -34,11 +36,16 @@ pub async fn serve_http_request(
host = host_and_port.as_str(); host = host_and_port.as_str();
}; };
http::header::HeaderValue::from_str(host).or_unexpected()? HeaderValue::from_str(host).or_unexpected()?
}; };
req.headers_mut().insert("host", host); req.headers_mut().insert("host", host);
if req_is_https {
req.headers_mut()
.insert("x-forwarded-proto", HeaderValue::from_static("https"));
}
match hyper_reverse_proxy::call(client_ip, proxy_url, req).await { match hyper_reverse_proxy::call(client_ip, proxy_url, req).await {
Ok(res) => Ok(res), Ok(res) => Ok(res),
// ProxyError doesn't actually implement Error :facepalm: so we have to format the error // ProxyError doesn't actually implement Error :facepalm: so we have to format the error

View File

@ -163,6 +163,7 @@ impl<'svc> Service {
client_ip: net::IpAddr, client_ip: net::IpAddr,
domain: domain::Name, domain: domain::Name,
req: Request<Body>, req: Request<Body>,
req_is_https: bool,
) -> Response<Body> { ) -> Response<Body> {
let mut path_owned; let mut path_owned;
let path = req.uri().path(); let path = req.uri().path();
@ -185,7 +186,7 @@ impl<'svc> Service {
self.render_error_page(404, "File not found") self.render_error_page(404, "File not found")
} }
Err(domain::manager::GetFileError::OriginIsProxy { url }) => { Err(domain::manager::GetFileError::OriginIsProxy { url }) => {
origin::proxy::serve_http_request(client_ip, &url, req) origin::proxy::serve_http_request(client_ip, &url, req, req_is_https)
.await .await
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
self.internal_error(format!("proxying {domain} to {url}: {e}").as_str()) self.internal_error(format!("proxying {domain} to {url}: {e}").as_str())
@ -379,7 +380,12 @@ impl<'svc> Service {
self.render_page("/domains.html", Response { domains }) self.render_page("/domains.html", Response { domains })
} }
async fn handle_request(&self, client_ip: net::IpAddr, req: Request<Body>) -> Response<Body> { async fn handle_request(
&self,
client_ip: net::IpAddr,
req: Request<Body>,
req_is_https: bool,
) -> Response<Body> {
let maybe_host = match ( let maybe_host = match (
req.headers() req.headers()
.get("Host") .get("Host")
@ -428,7 +434,9 @@ impl<'svc> Service {
// If a managed domain was given then serve that from its origin // If a managed domain was given then serve that from its origin
if let Some(domain) = maybe_host { if let Some(domain) = maybe_host {
return self.serve_origin(client_ip, domain, req).await; return self
.serve_origin(client_ip, domain, req, req_is_https)
.await;
} }
// Serve main domani site // Serve main domani site

View File

@ -22,7 +22,9 @@ pub async fn listen_http(
// Create a `Service` for responding to the request. // Create a `Service` for responding to the request.
let hyper_service = hyper::service::service_fn(move |req| { let hyper_service = hyper::service::service_fn(move |req| {
let service = service.clone(); let service = service.clone();
async move { Ok::<_, convert::Infallible>(service.handle_request(client_ip, req).await) } async move {
Ok::<_, convert::Infallible>(service.handle_request(client_ip, req, false).await)
}
}); });
// Return the service to hyper. // Return the service to hyper.
@ -58,7 +60,9 @@ pub async fn listen_https(
// Create a `Service` for responding to the request. // Create a `Service` for responding to the request.
let hyper_service = hyper::service::service_fn(move |req| { let hyper_service = hyper::service::service_fn(move |req| {
let service = service.clone(); let service = service.clone();
async move { Ok::<_, convert::Infallible>(service.handle_request(client_ip, req).await) } async move {
Ok::<_, convert::Infallible>(service.handle_request(client_ip, req, true).await)
}
}); });
// Return the service to hyper. // Return the service to hyper.