Skip to content
Browse files

Allow explicit use of scheme-default ports in proxy URLs

If a proxy URL contains an explicit port spec ":80" (http)
or ":443" (https), Url::parse() will set the port to None, which
is indistinguishable from the case where the port is unspecified,
and will cause the port to be set to 8080.

To avoid this, if the scheme is "http" or "https", it's changed to
"xttp" or "xttps" before parsing the URL, then changed back to
the original. The bogus scheme has no known default port value, so
every explicit value will be kept.
  • Loading branch information...
inejge committed Apr 27, 2019
1 parent eaf90ca commit 33399e1ba23f4f27c2b5aa46c3222f995cb70a46
Showing with 25 additions and 0 deletions.
  1. +25 −0 src/
@@ -163,9 +163,28 @@ impl ProxyUrl {
/// If any of the steps fail, `None` will be returned.
pub fn to_url(self) -> Option<Url> {
let mut orig_scheme = self.0.as_ref().map(|s|
if s.starts_with("http://") {
} else if s.starts_with("https://") {
} else {
if let Some(Ok(mut url)) =|mut s| {
if !s.contains("://") {
s.insert_str(0, "http://");
orig_scheme = Some("http");
if orig_scheme.is_some() {
// In here, the URL string must start with "http".
// Therefore, changing the first byte to 'x' won't change the UTF-8
// invariant.
unsafe {
let bytes = s.as_bytes_mut();
bytes[0] = b'x';
Url::parse(&s).map_err(|e| {
warn!("url parse error: {}", e);
@@ -176,6 +195,12 @@ impl ProxyUrl {
warn!("host part of the URL is empty");
return None;
if let Some(orig_scheme) = orig_scheme {
if url.set_scheme(orig_scheme).is_err() {
warn!("could not set URL scheme back to {}", orig_scheme);
return None;
if url.port().is_some() {
return Some(url);
} else if self.1.is_none() {

0 comments on commit 33399e1

Please sign in to comment.
You can’t perform that action at this time.