fixed #941 - unnecessary port in external URLs

This commit is contained in:
Eugene 2024-07-26 19:33:28 +02:00
parent af65d5a1aa
commit c328127493
No known key found for this signature in database
GPG key ID: 5896FCBBDD1CF4F4
2 changed files with 70 additions and 55 deletions

View file

@ -339,32 +339,33 @@ pub struct WarpgateConfig {
} }
impl WarpgateConfig { impl WarpgateConfig {
pub fn construct_external_url( pub fn _external_host_from_config(&self) -> Option<(Scheme, String, Option<u16>)> {
&self, if let Some(external_host) = self.store.external_host.as_ref() {
for_request: Option<&poem::Request>, #[allow(clippy::unwrap_used)]
) -> Result<Url, WarpgateError> { let external_host = external_host.split(":").next().unwrap();
let trust_forwarded_headers = self.store.http.trust_x_forwarded_headers;
// 1: external_host is not a valid `host[:port]` Some((
let (mut scheme, mut host, mut port) = (
Scheme::HTTPS, Scheme::HTTPS,
self.store.external_host.clone(), external_host.to_owned(),
Some(self.store.http.listen.port()), self.store
); .http
.external_port
// 2: external_host is a valid `host[:port]` .or(Some(self.store.http.listen.port())),
if let Some(external_url) = self ))
.store } else {
.external_host None
.as_ref() }
.and_then(|x| Url::parse(&format!("https://{x}/")).ok())
{
host = external_url.host_str().map(Into::into).or(host);
port = external_url.port();
} }
if let Some(request) = for_request { // Extract external host:port from request headers
// 3: Host header in the request pub fn _external_host_from_request(
&self,
request: &poem::Request,
) -> Option<(Scheme, String, Option<u16>)> {
let (mut scheme, mut host, mut port) = (Scheme::HTTPS, None, None);
let trust_forwarded_headers = self.store.http.trust_x_forwarded_headers;
// Try the Host header first
scheme = request.uri().scheme().cloned().unwrap_or(scheme); scheme = request.uri().scheme().cloned().unwrap_or(scheme);
if let Some(host_header) = request.header(http::header::HOST).map(|x| x.to_string()) { if let Some(host_header) = request.header(http::header::HOST).map(|x| x.to_string()) {
@ -374,7 +375,7 @@ impl WarpgateConfig {
} }
} }
// 4: X-Forwarded-* headers in the request // But prefer X-Forwarded-* headers if enabled
if trust_forwarded_headers { if trust_forwarded_headers {
scheme = request scheme = request
.header("x-forwarded-proto") .header("x-forwarded-proto")
@ -393,15 +394,27 @@ impl WarpgateConfig {
.and_then(|x| x.parse::<u16>().ok()) .and_then(|x| x.parse::<u16>().ok())
.or(port); .or(port);
} }
host.map(|host| (scheme, host, port))
} }
let Some(host) = host else { pub fn construct_external_url(
&self,
for_request: Option<&poem::Request>,
) -> Result<Url, WarpgateError> {
let Some((scheme, host, port)) = self
._external_host_from_config()
.or(for_request.and_then(|r| self._external_host_from_request(r)))
else {
return Err(WarpgateError::ExternalHostNotSet); return Err(WarpgateError::ExternalHostNotSet);
}; };
let mut url = format!("{scheme}://{host}"); let mut url = format!("{scheme}://{host}");
if let Some(port) = port { if let Some(port) = port {
// can't `match` `Scheme`
if scheme == Scheme::HTTP && port != 80 || scheme == Scheme::HTTPS && port != 443 {
url = format!("{url}:{port}"); url = format!("{url}:{port}");
}
}; };
Url::parse(&url).map_err(WarpgateError::UrlParse) Url::parse(&url).map_err(WarpgateError::UrlParse)
} }

View file

@ -192,7 +192,9 @@ impl russh::server::Handler for ServerHandler {
tx, tx,
))?; ))?;
Ok(rx.await.unwrap_or(Auth::Reject { proceed_with_methods: None })) Ok(rx.await.unwrap_or(Auth::Reject {
proceed_with_methods: None,
}))
} }
async fn auth_publickey( async fn auth_publickey(