Skip to content

Commit b911766

Browse files
authored
Merge pull request #92 from vkill/client-encode-with-Connect
fix request line url when method is CONNECT
2 parents 0d1ed82 + 8f1c341 commit b911766

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

src/client/encode.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use async_std::io::{self, Read};
22
use async_std::prelude::*;
33
use async_std::task::{Context, Poll};
44
use http_types::format_err;
5-
use http_types::Request;
5+
use http_types::{Method, Request};
66

77
use std::pin::Pin;
88

@@ -41,6 +41,17 @@ impl Encoder {
4141
url.push_str(query);
4242
}
4343

44+
// A client sending a CONNECT request MUST consists of only the host
45+
// name and port number of the tunnel destination, separated by a colon.
46+
// See: https://tools.ietf.org/html/rfc7231#section-4.3.6
47+
if req.method() == Method::Connect {
48+
let host = req.url().host_str();
49+
let host = host.ok_or_else(|| format_err!("Missing hostname"))?;
50+
let port = req.url().port_or_known_default();
51+
let port = port.ok_or_else(|| format_err!("Missing port"))?;
52+
url = format!("{}:{}", host, port);
53+
}
54+
4455
let val = format!("{} {} HTTP/1.1\r\n", req.method(), url);
4556
log::trace!("> {}", &val);
4657
buf.write_all(val.as_bytes()).await?;
@@ -58,6 +69,13 @@ impl Encoder {
5869
log::trace!("> {}", &val);
5970
buf.write_all(val.as_bytes()).await?;
6071

72+
// Insert Proxy-Connection header when method is CONNECT
73+
if req.method() == Method::Connect {
74+
let val = "proxy-connection: keep-alive\r\n".to_owned();
75+
log::trace!("> {}", &val);
76+
buf.write_all(val.as_bytes()).await?;
77+
}
78+
6179
// If the body isn't streaming, we can set the content-length ahead of time. Else we need to
6280
// send all items in chunks.
6381
if let Some(len) = req.len() {

tests/client.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,20 @@ async fn test_response_newlines() {
6767
78
6868
);
6969
}
70+
71+
#[async_std::test]
72+
async fn test_encode_request_with_connect() {
73+
let case = TestCase::new_client(
74+
"fixtures/request-with-connect.txt",
75+
"fixtures/response-with-connect.txt",
76+
)
77+
.await;
78+
79+
let url = Url::parse("https://example.com:443").unwrap();
80+
let req = Request::new(Method::Connect, url);
81+
82+
let res = client::connect(case.clone(), req).await.unwrap();
83+
assert_eq!(res.status(), StatusCode::Ok);
84+
85+
case.assert().await;
86+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CONNECT example.com:443 HTTP/1.1
2+
host: example.com
3+
proxy-connection: keep-alive
4+
content-length: 0
5+
date: {DATE}
6+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
HTTP/1.1 200 Tunnel established
2+

0 commit comments

Comments
 (0)