Skip to content

Commit 33a385c

Browse files
committed
feat(client): add Config::set_host option
If set to false, the `Client` will no longer automatically set the `Host` header if absent.
1 parent 3e87eb4 commit 33a385c

File tree

2 files changed

+98
-2
lines changed

2 files changed

+98
-2
lines changed

src/client/mod.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub struct Client<C, B = proto::Body> {
4646
h1_writev: bool,
4747
pool: Pool<HyperClient<B>>,
4848
retry_canceled_requests: bool,
49+
set_host: bool,
4950
}
5051

5152
impl Client<HttpConnector, proto::Body> {
@@ -101,6 +102,7 @@ impl<C, B> Client<C, B> {
101102
h1_writev: config.h1_writev,
102103
pool: Pool::new(config.keep_alive, config.keep_alive_timeout),
103104
retry_canceled_requests: config.retry_canceled_requests,
105+
set_host: config.set_host,
104106
}
105107
}
106108
}
@@ -147,7 +149,7 @@ where C: Connect,
147149
))));
148150
}
149151
};
150-
if !req.headers().has::<Host>() {
152+
if self.set_host && !req.headers().has::<Host>() {
151153
let host = Host::new(
152154
domain.host().expect("authority implies host").to_owned(),
153155
domain.port(),
@@ -289,6 +291,7 @@ impl<C, B> Clone for Client<C, B> {
289291
h1_writev: self.h1_writev,
290292
pool: self.pool.clone(),
291293
retry_canceled_requests: self.retry_canceled_requests,
294+
set_host: self.set_host,
292295
}
293296
}
294297
}
@@ -413,6 +416,7 @@ pub struct Config<C, B> {
413416
//TODO: make use of max_idle config
414417
max_idle: usize,
415418
retry_canceled_requests: bool,
419+
set_host: bool,
416420
}
417421

418422
/// Phantom type used to signal that `Config` should create a `HttpConnector`.
@@ -429,6 +433,7 @@ impl Default for Config<UseDefaultConnector, proto::Body> {
429433
h1_writev: true,
430434
max_idle: 5,
431435
retry_canceled_requests: true,
436+
set_host: true,
432437
}
433438
}
434439
}
@@ -453,6 +458,7 @@ impl<C, B> Config<C, B> {
453458
h1_writev: self.h1_writev,
454459
max_idle: self.max_idle,
455460
retry_canceled_requests: self.retry_canceled_requests,
461+
set_host: self.set_host,
456462
}
457463
}
458464

@@ -467,6 +473,7 @@ impl<C, B> Config<C, B> {
467473
h1_writev: self.h1_writev,
468474
max_idle: self.max_idle,
469475
retry_canceled_requests: self.retry_canceled_requests,
476+
set_host: self.set_host,
470477
}
471478
}
472479

@@ -521,6 +528,18 @@ impl<C, B> Config<C, B> {
521528
self
522529
}
523530

531+
/// Set whether to automatically add the `Host` header to requests.
532+
///
533+
/// If true, and a request does not include a `Host` header, one will be
534+
/// added automatically, derived from the authority of the `Uri`.
535+
///
536+
/// Default is `true`.
537+
#[inline]
538+
pub fn set_host(mut self, val: bool) -> Config<C, B> {
539+
self.set_host = val;
540+
self
541+
}
542+
524543
#[doc(hidden)]
525544
#[deprecated(since="0.11.11", note="no_proto is always enabled")]
526545
pub fn no_proto(self) -> Config<C, B> {
@@ -573,6 +592,7 @@ impl<C, B> fmt::Debug for Config<C, B> {
573592
.field("keep_alive_timeout", &self.keep_alive_timeout)
574593
.field("http1_writev", &self.h1_writev)
575594
.field("max_idle", &self.max_idle)
595+
.field("set_host", &self.set_host)
576596
.finish()
577597
}
578598
}

tests/client.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,45 @@ macro_rules! test {
4545
headers: [ $($response_headers:expr,)* ],
4646
body: $response_body:expr,
4747
) => (
48+
test! {
49+
name: $name,
50+
server:
51+
expected: $server_expected,
52+
reply: $server_reply,
53+
client:
54+
set_host: true,
55+
request:
56+
method: $client_method,
57+
url: $client_url,
58+
headers: [ $($request_headers,)* ],
59+
body: $request_body,
60+
proxy: $request_proxy,
61+
62+
response:
63+
status: $client_status,
64+
headers: [ $($response_headers,)* ],
65+
body: $response_body,
66+
}
67+
);
68+
(
69+
name: $name:ident,
70+
server:
71+
expected: $server_expected:expr,
72+
reply: $server_reply:expr,
73+
client:
74+
set_host: $set_host:expr,
75+
request:
76+
method: $client_method:ident,
77+
url: $client_url:expr,
78+
headers: [ $($request_headers:expr,)* ],
79+
body: $request_body:expr,
80+
proxy: $request_proxy:expr,
81+
82+
response:
83+
status: $client_status:ident,
84+
headers: [ $($response_headers:expr,)* ],
85+
body: $response_body:expr,
86+
) => (
4887
#[test]
4988
fn $name() {
5089
#![allow(unused)]
@@ -60,6 +99,7 @@ macro_rules! test {
6099
expected: $server_expected,
61100
reply: $server_reply,
62101
client:
102+
set_host: $set_host,
63103
request:
64104
method: $client_method,
65105
url: $client_url,
@@ -111,6 +151,7 @@ macro_rules! test {
111151
expected: $server_expected,
112152
reply: $server_reply,
113153
client:
154+
set_host: true,
114155
request:
115156
method: $client_method,
116157
url: $client_url,
@@ -132,6 +173,7 @@ macro_rules! test {
132173
expected: $server_expected:expr,
133174
reply: $server_reply:expr,
134175
client:
176+
set_host: $set_host:expr,
135177
request:
136178
method: $client_method:ident,
137179
url: $client_url:expr,
@@ -142,7 +184,12 @@ macro_rules! test {
142184
let server = TcpListener::bind("127.0.0.1:0").unwrap();
143185
let addr = server.local_addr().unwrap();
144186
let mut core = $core;
145-
let client = client(&core.handle());
187+
188+
let mut config = Client::configure();
189+
if !$set_host {
190+
config = config.set_host(false);
191+
}
192+
let client = config.build(&core.handle());
146193
let mut req = Request::new(Method::$client_method, format!($client_url, addr=addr).parse().unwrap());
147194
$(
148195
req.headers_mut().set($request_headers);
@@ -545,6 +592,35 @@ test! {
545592

546593
}
547594

595+
test! {
596+
name: client_set_host_false,
597+
598+
server:
599+
// {addr} is here because format! requires it to exist in the string
600+
expected: "\
601+
GET /no-host/{addr} HTTP/1.1\r\n\
602+
\r\n\
603+
",
604+
reply: "\
605+
HTTP/1.1 200 OK\r\n\
606+
Content-Length: 0\r\n\
607+
\r\n\
608+
",
609+
610+
client:
611+
set_host: false,
612+
request:
613+
method: Get,
614+
url: "http://{addr}/no-host/{addr}",
615+
headers: [],
616+
body: None,
617+
proxy: false,
618+
response:
619+
status: Ok,
620+
headers: [],
621+
body: None,
622+
}
623+
548624
#[test]
549625
fn client_keep_alive() {
550626
let server = TcpListener::bind("127.0.0.1:0").unwrap();

0 commit comments

Comments
 (0)