Skip to content

Commit 24f11a4

Browse files
okreadyseanmonstar
authored andcommitted
fix(http2): allow TE "trailers" request headers
The HTTP/2 spec allows TE headers in requests if the value is "trailers". Other TE headers are still stripped. Closes #1642
1 parent e3dc6c5 commit 24f11a4

File tree

4 files changed

+41
-4
lines changed

4 files changed

+41
-4
lines changed

src/proto/h2/client.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ where
108108
}
109109
let (head, body) = req.into_parts();
110110
let mut req = ::http::Request::from_parts(head, ());
111-
super::strip_connection_headers(req.headers_mut());
111+
super::strip_connection_headers(req.headers_mut(), true);
112112
if let Some(len) = body.content_length() {
113113
headers::set_content_length_if_missing(req.headers_mut(), len);
114114
}

src/proto/h2/mod.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ mod server;
1515
pub(crate) use self::client::Client;
1616
pub(crate) use self::server::Server;
1717

18-
fn strip_connection_headers(headers: &mut HeaderMap) {
18+
fn strip_connection_headers(headers: &mut HeaderMap, is_request: bool) {
1919
// List of connection headers from:
2020
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
21+
//
22+
// TE headers are allowed in HTTP/2 requests as long as the value is "trailers", so they're
23+
// tested separately.
2124
let connection_headers = [
2225
HeaderName::from_lowercase(b"keep-alive").unwrap(),
2326
HeaderName::from_lowercase(b"proxy-connection").unwrap(),
2427
PROXY_AUTHENTICATE,
2528
PROXY_AUTHORIZATION,
26-
TE,
2729
TRAILER,
2830
TRANSFER_ENCODING,
2931
UPGRADE,
@@ -35,6 +37,17 @@ fn strip_connection_headers(headers: &mut HeaderMap) {
3537
}
3638
}
3739

40+
if is_request {
41+
if headers.get(TE).map(|te_header| te_header != "trailers").unwrap_or(false) {
42+
warn!("TE headers not set to \"trailers\" are illegal in HTTP/2 requests");
43+
headers.remove(TE);
44+
}
45+
} else {
46+
if headers.remove(TE).is_some() {
47+
warn!("TE headers illegal in HTTP/2 responses");
48+
}
49+
}
50+
3851
if let Some(header) = headers.remove(CONNECTION) {
3952
warn!(
4053
"Connection header illegal in HTTP/2: {}",

src/proto/h2/server.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ where
192192

193193
let (head, body) = res.into_parts();
194194
let mut res = ::http::Response::from_parts(head, ());
195-
super::strip_connection_headers(res.headers_mut());
195+
super::strip_connection_headers(res.headers_mut(), false);
196196
if let Some(len) = body.content_length() {
197197
headers::set_content_length_if_missing(res.headers_mut(), len);
198198
}

tests/integration.rs

+24
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,30 @@ t! {
184184
;
185185
}
186186

187+
t! {
188+
get_allow_te_trailers_header,
189+
client:
190+
request:
191+
uri: "/",
192+
headers: {
193+
// http2 strips connection headers other than TE "trailers"
194+
"te" => "trailers",
195+
},
196+
;
197+
response:
198+
status: 200,
199+
;
200+
server:
201+
request:
202+
uri: "/",
203+
headers: {
204+
"te" => "trailers",
205+
},
206+
;
207+
response:
208+
;
209+
}
210+
187211
t! {
188212
get_body_chunked,
189213
client:

0 commit comments

Comments
 (0)