Honor proxied_domains' https_disabled when doing https redirects
This commit is contained in:
parent
0b5b2cb3f3
commit
6cabb9b742
@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use std::{collections, future, net, sync};
|
||||
|
||||
use crate::error::unexpected;
|
||||
use crate::error::unexpected::{self, Mappable};
|
||||
use crate::{domain, service, task_stack};
|
||||
|
||||
#[derive(Serialize)]
|
||||
@ -157,6 +157,39 @@ impl Service {
|
||||
)
|
||||
}
|
||||
|
||||
fn https_redirect(&self, domain: domain::Name, req: Request<Body>) -> Response<Body> {
|
||||
let https_addr = self.config.http.https_addr.unwrap();
|
||||
|
||||
(|| {
|
||||
let mut uri_parts = http::uri::Parts::default();
|
||||
uri_parts.scheme = Some(http::uri::Scheme::HTTPS);
|
||||
uri_parts.authority = Some(
|
||||
http::uri::Authority::from_maybe_shared(format!(
|
||||
"{}:{}",
|
||||
&domain,
|
||||
https_addr.port()
|
||||
))
|
||||
.or_unexpected_while("constructing authority")?,
|
||||
);
|
||||
uri_parts.path_and_query = req.uri().path_and_query().cloned();
|
||||
|
||||
let uri: http::uri::Uri = uri_parts
|
||||
.try_into()
|
||||
.or_unexpected_while("constructing new URI")?;
|
||||
|
||||
Response::builder()
|
||||
.status(http::status::StatusCode::PERMANENT_REDIRECT)
|
||||
.header("Location", uri.to_string())
|
||||
.body(Body::empty())
|
||||
.or_unexpected_while("building redirect")
|
||||
})()
|
||||
.unwrap_or_else(|err| {
|
||||
self.internal_error(
|
||||
format!("failed to redirect from {} to https: {}", req.uri(), err).as_str(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn render_page<T>(&self, name: &str, data: T) -> Response<Body>
|
||||
where
|
||||
T: Serialize,
|
||||
@ -504,51 +537,40 @@ impl Service {
|
||||
}
|
||||
}
|
||||
|
||||
// If HTTPS is enabled then only .well-known endpoints are allowed over HTTP (because they
|
||||
// require it). Otherwise we redirect all HTTP requests to HTTPS.
|
||||
if self.config.http.https_addr.is_some() && !req_is_https {
|
||||
let https_addr = self.config.http.https_addr.unwrap();
|
||||
|
||||
let mut uri_parts = http::uri::Parts::default();
|
||||
uri_parts.scheme = Some(http::uri::Scheme::HTTPS);
|
||||
uri_parts.authority = Some(
|
||||
http::uri::Authority::from_maybe_shared(format!(
|
||||
"{}:{}",
|
||||
&domain,
|
||||
https_addr.port()
|
||||
))
|
||||
.unwrap(),
|
||||
);
|
||||
uri_parts.path_and_query = req.uri().path_and_query().cloned();
|
||||
|
||||
let uri: http::uri::Uri = uri_parts.try_into().unwrap();
|
||||
|
||||
return Response::builder()
|
||||
.status(http::status::StatusCode::PERMANENT_REDIRECT)
|
||||
.header("Location", uri.to_string())
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
}
|
||||
// We only allow HTTP requests when HTTPS is enabled in specific cases:
|
||||
// - /.well-known urls
|
||||
// - proxied domains with https_disabled set on them
|
||||
// everything else must use https if possible.
|
||||
let https_upgradable = self.config.http.https_addr.is_some() && !req_is_https;
|
||||
|
||||
if let Some(config) = self.proxied_domains.get(&domain) {
|
||||
if let Some(ref http_url) = config.http_url {
|
||||
return service::http::proxy::serve_http_request(
|
||||
http_url.original_url.as_str(),
|
||||
&config.http_request_headers.0,
|
||||
client_ip,
|
||||
req,
|
||||
req_is_https,
|
||||
)
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
self.internal_error(
|
||||
format!("serving {domain} via proxy {}: {e}", http_url.original_url)
|
||||
.as_str(),
|
||||
)
|
||||
});
|
||||
} else {
|
||||
if config.http_url.is_none() {
|
||||
return self.render_error_page(404, "Domain not found");
|
||||
}
|
||||
|
||||
let http_url = config.http_url.as_ref().unwrap();
|
||||
|
||||
if https_upgradable && !config.https_disabled {
|
||||
return self.https_redirect(domain, req);
|
||||
}
|
||||
|
||||
return service::http::proxy::serve_http_request(
|
||||
http_url.original_url.as_str(),
|
||||
&config.http_request_headers.0,
|
||||
client_ip,
|
||||
req,
|
||||
req_is_https,
|
||||
)
|
||||
.await
|
||||
.unwrap_or_else(|e| {
|
||||
self.internal_error(
|
||||
format!("serving {domain} via proxy {}: {e}", http_url.original_url).as_str(),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
if https_upgradable {
|
||||
return self.https_redirect(domain, req);
|
||||
}
|
||||
|
||||
if Some(&domain) == self.interface_domain.as_ref() {
|
||||
|
Loading…
Reference in New Issue
Block a user