Skip to content

Commit b342c38

Browse files
jxsseanmonstar
authored andcommitted
fix(server): skip automatic Content-Length header for HTTP 304 responses
Closes #1797
1 parent 7fde9ba commit b342c38

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

src/proto/h1/role.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -476,14 +476,20 @@ impl Http1Transaction for Server {
476476
},
477477
None |
478478
Some(BodyLength::Known(0)) => {
479-
extend(dst, b"content-length: 0\r\n");
479+
if msg.head.subject != StatusCode::NOT_MODIFIED {
480+
extend(dst, b"content-length: 0\r\n");
481+
}
480482
Encoder::length(0)
481483
},
482484
Some(BodyLength::Known(len)) => {
483-
extend(dst, b"content-length: ");
484-
let _ = ::itoa::write(&mut dst, len);
485-
extend(dst, b"\r\n");
486-
Encoder::length(len)
485+
if msg.head.subject == StatusCode::NOT_MODIFIED {
486+
Encoder::length(0)
487+
} else {
488+
extend(dst, b"content-length: ");
489+
let _ = ::itoa::write(&mut dst, len);
490+
extend(dst, b"\r\n");
491+
Encoder::length(len)
492+
}
487493
},
488494
};
489495
}
@@ -1583,4 +1589,3 @@ mod tests {
15831589
})
15841590
}
15851591
}
1586-

tests/server.rs

+45-1
Original file line numberDiff line numberDiff line change
@@ -1687,6 +1687,51 @@ fn http2_service_poll_ready_error_sends_goaway() {
16871687
assert_eq!(h2_err.reason(), Some(h2::Reason::INADEQUATE_SECURITY));
16881688
}
16891689

1690+
#[test]
1691+
fn skips_content_length_for_304_responses() {
1692+
let server = serve();
1693+
server.reply()
1694+
1695+
.status(hyper::StatusCode::NOT_MODIFIED)
1696+
.body("foo");
1697+
let mut req = connect(server.addr());
1698+
req.write_all(b"\
1699+
GET / HTTP/1.1\r\n\
1700+
Host: example.domain\r\n\
1701+
Connection: close\r\n\
1702+
\r\n\
1703+
").unwrap();
1704+
1705+
let mut response = String::new();
1706+
req.read_to_string(&mut response).unwrap();
1707+
assert!(!response.contains("content-length:"));
1708+
}
1709+
1710+
#[test]
1711+
fn skips_content_length_and_body_for_304_responses() {
1712+
let server = serve();
1713+
server.reply()
1714+
1715+
.status(hyper::StatusCode::NOT_MODIFIED)
1716+
.body("foo");
1717+
let mut req = connect(server.addr());
1718+
req.write_all(b"\
1719+
GET / HTTP/1.1\r\n\
1720+
Host: example.domain\r\n\
1721+
Connection: close\r\n\
1722+
\r\n\
1723+
").unwrap();
1724+
1725+
let mut response = String::new();
1726+
req.read_to_string(&mut response).unwrap();
1727+
assert!(!response.contains("content-length:"));
1728+
let mut lines = response.lines();
1729+
assert_eq!(lines.next(), Some("HTTP/1.1 304 Not Modified"));
1730+
1731+
let mut lines = lines.skip_while(|line| !line.is_empty());
1732+
assert_eq!(lines.next(), Some(""));
1733+
assert_eq!(lines.next(), None);
1734+
}
16901735
// -------------------------------------------------
16911736
// the Server that is used to run all the tests with
16921737
// -------------------------------------------------
@@ -2058,4 +2103,3 @@ impl Drop for Dropped {
20582103
self.0.store(true, Ordering::SeqCst);
20592104
}
20602105
}
2061-

0 commit comments

Comments
 (0)