Skip to content

Commit 169d2a5

Browse files
committed
curl,winrt fix req header override
1 parent d4d073b commit 169d2a5

5 files changed

Lines changed: 92 additions & 3 deletions

File tree

backends/curl/src/request.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ pub fn populate_request<S, H: Handler>(
5050
}
5151
.into_nyquest_result("set CURLOPT_CUSTOMREQUEST")?;
5252
let mut headers = List::new();
53-
for (name, value) in &options.default_headers {
53+
for (name, value) in options.default_headers.iter().filter(|(name, _)| {
54+
// FIXME: This is O(len(additional) * len(default))
55+
!req.additional_headers
56+
.iter()
57+
.any(|(n, _)| n.eq_ignore_ascii_case(name))
58+
}) {
5459
headers
5560
.append(&format!("{name}: {value}"))
5661
.into_nyquest_result("default_headers curl_slist_append")?;

backends/winrt/src/client.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ impl WinrtClient {
5454
}
5555
let mut default_content_headers = vec![];
5656
for (name, value) in options.default_headers {
57-
if is_header_name_content_related(&name) {
57+
if name.eq_ignore_ascii_case("content-type") {
58+
// If a request has a body, the content-type value is required from the user.
59+
// Otherwise if there is no body, the content-type header will never be sent.
60+
// So we can safely ignore the default content-type header.
61+
} else if is_header_name_content_related(&name) {
5862
default_content_headers.push((HSTRING::from(name), HSTRING::from(value)));
5963
} else {
6064
client

backends/winrt/src/request.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl WinrtClient {
3333
.into_nyquest_result()?;
3434
let req_msg = HttpRequestMessage::Create(&method, &uri).into_nyquest_result()?;
3535
// TODO: cache method
36-
if !req.additional_headers.is_empty() || !self.default_content_headers.is_empty() {
36+
if !req.additional_headers.is_empty() {
3737
let headers = req_msg.Headers().into_nyquest_result()?;
3838
for (name, value) in &req.additional_headers {
3939
headers
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
mod chunked_encoding;
2+
mod request_header_override;
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#[cfg(test)]
2+
mod tests {
3+
use http_body_util::Full;
4+
#[cfg(feature = "blocking")]
5+
use nyquest::blocking::Body as NyquestBlockingBody;
6+
#[cfg(feature = "async")]
7+
use nyquest::r#async::Body as NyquestAsyncBody;
8+
use nyquest::Request as NyquestRequest;
9+
10+
use crate::*;
11+
12+
#[test]
13+
fn test_request_header_override() {
14+
const PATH: &str = "scenarios/request_header_override";
15+
const DEFAULT_HEADER_NAME: &str = "x-default-header";
16+
const DEFAULT_HEADER_VALUE: &str = "default";
17+
const EXPECTED_HEADER_VALUE: &str = "expected";
18+
const BODY_TEXT: &str = "Hello, plain text!";
19+
20+
let _handle = crate::add_hyper_fixture(PATH, {
21+
move |req| async move {
22+
let content_type_headers: Vec<_> = req
23+
.headers()
24+
.get_all(DEFAULT_HEADER_NAME)
25+
.iter()
26+
.map(|h| h.to_str().unwrap_or_default())
27+
.collect();
28+
let content_type_headers = content_type_headers.join("; ");
29+
30+
let response_body = Bytes::from(content_type_headers.into_bytes());
31+
let res = Response::new(Full::new(response_body));
32+
33+
(res, Ok(()))
34+
}
35+
});
36+
37+
let assertions = |received_content_type: &str| {
38+
assert_eq!(received_content_type, EXPECTED_HEADER_VALUE);
39+
};
40+
41+
#[cfg(feature = "blocking")]
42+
{
43+
let builder = crate::init_builder_blocking()
44+
.unwrap()
45+
.with_header(DEFAULT_HEADER_NAME, DEFAULT_HEADER_VALUE);
46+
let client = builder.build_blocking().unwrap();
47+
let res = client
48+
.request(
49+
NyquestRequest::post(PATH)
50+
.with_body(NyquestBlockingBody::plain_text(BODY_TEXT))
51+
.with_header(DEFAULT_HEADER_NAME, EXPECTED_HEADER_VALUE),
52+
)
53+
.unwrap();
54+
let content_type = res.text().unwrap();
55+
assertions(&content_type);
56+
}
57+
58+
#[cfg(feature = "async")]
59+
{
60+
let content_type = TOKIO_RT.block_on(async {
61+
let builder = crate::init_builder()
62+
.await
63+
.unwrap()
64+
.with_header(DEFAULT_HEADER_NAME, DEFAULT_HEADER_VALUE);
65+
let client = builder.build_async().await.unwrap();
66+
let res = client
67+
.request(
68+
NyquestRequest::post(PATH)
69+
.with_body(NyquestAsyncBody::plain_text(BODY_TEXT))
70+
.with_header(DEFAULT_HEADER_NAME, EXPECTED_HEADER_VALUE),
71+
)
72+
.await
73+
.unwrap();
74+
res.text().await.unwrap()
75+
});
76+
assertions(&content_type);
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)