diff --git a/src/client/request.rs b/src/client/request.rs index 67f7c45fe2..31b7104e09 100644 --- a/src/client/request.rs +++ b/src/client/request.rs @@ -16,6 +16,7 @@ pub struct Request { version: HttpVersion, headers: Headers, body: Option, + is_proxy: bool, } impl Request { @@ -28,6 +29,7 @@ impl Request { version: HttpVersion::default(), headers: Headers::new(), body: None, + is_proxy: false, } } @@ -66,6 +68,13 @@ impl Request { /// Set the body of the request. #[inline] pub fn set_body>(&mut self, body: T) { self.body = Some(body.into()); } + + /// Set that the URI should use the absolute form. + /// + /// This is only needed when talking to HTTP/1 proxies to URLs not + /// protected by TLS. + #[inline] + pub fn set_proxy(&mut self, is_proxy: bool) { self.is_proxy = is_proxy; } } impl fmt::Debug for Request { @@ -80,7 +89,11 @@ impl fmt::Debug for Request { } pub fn split(req: Request) -> (RequestHead, Option) { - let uri = Uri::from_str(&req.url[::url::Position::BeforePath..::url::Position::AfterQuery]).expect("url is uri"); + let uri = if req.is_proxy { + Uri::from(req.url) + } else { + Uri::from_str(&req.url[::url::Position::BeforePath..::url::Position::AfterQuery]).expect("url is not uri") + }; let head = RequestHead { subject: ::http::RequestLine(req.method, uri), headers: req.headers, diff --git a/tests/client.rs b/tests/client.rs index 233f009b3d..94a2d31827 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -37,6 +37,7 @@ macro_rules! test { url: $client_url:expr, headers: [ $($request_headers:expr,)* ], body: $request_body:expr, + proxy: $request_proxy:expr, response: status: $client_status:ident, @@ -61,6 +62,8 @@ macro_rules! test { let body: &'static str = body; req.set_body(body); } + req.set_proxy($request_proxy); + let res = client.request(req); let (tx, rx) = oneshot::channel(); @@ -109,6 +112,7 @@ test! { url: "http://{addr}/", headers: [], body: None, + proxy: false, response: status: Ok, headers: [ @@ -130,6 +134,7 @@ test! { url: "http://{addr}/foo?key=val#dont_send_me", headers: [], body: None, + proxy: false, response: status: Ok, headers: [ @@ -159,6 +164,7 @@ test! { ContentLength(7), ], body: Some("foo bar"), + proxy: false, response: status: Ok, headers: [], @@ -188,6 +194,31 @@ test! { TransferEncoding::chunked(), ], body: Some("foo bar baz"), + proxy: false, + response: + status: Ok, + headers: [], + body: None, +} + +test! { + name: client_http_proxy, + + server: + expected: "\ + GET http://{addr}/proxy HTTP/1.1\r\n\ + Host: {addr}\r\n\ + \r\n\ + ", + reply: REPLY_OK, + + client: + request: + method: Get, + url: "http://{addr}/proxy", + headers: [], + body: None, + proxy: true, response: status: Ok, headers: [],