Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 53 additions & 34 deletions src/proto/h1/role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ impl Http1Transaction for Server {
let mut decoder = DecodedLength::ZERO;
let mut expect_continue = false;
let mut con_len = None;
let mut is_cl = false;
let mut is_te = false;
let mut is_te_chunked = false;
let mut wants_upgrade = subject.0 == Method::CONNECT;
Expand Down Expand Up @@ -272,6 +273,9 @@ impl Http1Transaction for Server {
return Err(Parse::transfer_encoding_unexpected());
}
is_te = true;
if is_cl && con_len.take().is_some() {
headers.remove(header::CONTENT_LENGTH);
}
if headers::is_chunked_(&value) {
is_te_chunked = true;
decoder = DecodedLength::CHUNKED;
Expand All @@ -280,6 +284,7 @@ impl Http1Transaction for Server {
}
}
header::CONTENT_LENGTH => {
is_cl = true;
if is_te {
continue;
}
Expand Down Expand Up @@ -340,6 +345,10 @@ impl Http1Transaction for Server {
return Err(Parse::transfer_encoding_invalid());
}

if is_te && is_cl {
keep_alive = false;
}

let mut extensions = http::Extensions::default();

if let Some(header_case_map) = header_case_map {
Expand Down Expand Up @@ -2048,45 +2057,55 @@ mod tests {
);

// transfer-encoding and content-length = chunked
assert_eq!(
parse(
"\
POST / HTTP/1.1\r\n\
content-length: 10\r\n\
transfer-encoding: chunked\r\n\
\r\n\
"
)
.decode,
DecodedLength::CHUNKED
let msg = parse(
"\
POST / HTTP/1.1\r\n\
content-length: 10\r\n\
transfer-encoding: chunked\r\n\
\r\n\
",
);
assert_eq!(msg.decode, DecodedLength::CHUNKED);
assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
assert!(!msg.keep_alive);

assert_eq!(
parse(
"\
POST / HTTP/1.1\r\n\
transfer-encoding: chunked\r\n\
content-length: 10\r\n\
\r\n\
"
)
.decode,
DecodedLength::CHUNKED
let msg = parse(
"\
POST / HTTP/1.1\r\n\
transfer-encoding: chunked\r\n\
content-length: 10\r\n\
\r\n\
",
);
assert_eq!(msg.decode, DecodedLength::CHUNKED);
assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
assert!(!msg.keep_alive);

assert_eq!(
parse(
"\
POST / HTTP/1.1\r\n\
transfer-encoding: gzip\r\n\
content-length: 10\r\n\
transfer-encoding: chunked\r\n\
\r\n\
"
)
.decode,
DecodedLength::CHUNKED
let msg = parse(
"\
POST / HTTP/1.1\r\n\
transfer-encoding: gzip\r\n\
content-length: 10\r\n\
transfer-encoding: chunked\r\n\
\r\n\
",
);
assert_eq!(msg.decode, DecodedLength::CHUNKED);
assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
assert!(!msg.keep_alive);

let msg = parse(
"\
POST / HTTP/1.1\r\n\
connection: keep-alive\r\n\
content-length: 10\r\n\
transfer-encoding: chunked\r\n\
\r\n\
",
);
assert_eq!(msg.decode, DecodedLength::CHUNKED);
assert!(!msg.head.headers.contains_key(header::CONTENT_LENGTH));
assert!(!msg.keep_alive);

// multiple content-lengths of same value are fine
assert_eq!(
Expand Down
Loading