mirror of https://github.com/rwf2/Rocket.git
Strip body and content-length on 204, body on 304.
This works-around an issue where hyper incorrectly removes the body on 204 responses without removing the content-length or setting it to zero. Resolves #2821.
This commit is contained in:
parent
d3323391ab
commit
9496b70e8c
|
@ -134,12 +134,17 @@ impl Rocket<Orbit> {
|
||||||
// Run the response fairings.
|
// Run the response fairings.
|
||||||
self.fairings.handle_response(request, &mut response).await;
|
self.fairings.handle_response(request, &mut response).await;
|
||||||
|
|
||||||
// Strip the body if this is a `HEAD` request.
|
// Strip the body if this is a `HEAD` request or a 304 response.
|
||||||
if was_head_request {
|
if was_head_request || response.status() == Status::NotModified {
|
||||||
response.strip_body();
|
response.strip_body();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(size) = response.body_mut().size().await {
|
// If the response status is 204, strip the body and its size (no
|
||||||
|
// content-length header). Otherwise, check if the body is sized and use
|
||||||
|
// that size to set the content-length headr appropriately.
|
||||||
|
if response.status() == Status::NoContent {
|
||||||
|
*response.body_mut() = crate::response::Body::unsized_none();
|
||||||
|
} else if let Some(size) = response.body_mut().size().await {
|
||||||
response.set_raw_header("Content-Length", size.to_string());
|
response.set_raw_header("Content-Length", size.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,14 @@ impl<'r> Body<'r> {
|
||||||
/// The present value is `4096`.
|
/// The present value is `4096`.
|
||||||
pub const DEFAULT_MAX_CHUNK: usize = 4096;
|
pub const DEFAULT_MAX_CHUNK: usize = 4096;
|
||||||
|
|
||||||
|
pub(crate) fn unsized_none() -> Self {
|
||||||
|
Body {
|
||||||
|
size: None,
|
||||||
|
inner: Inner::None,
|
||||||
|
max_chunk: Body::DEFAULT_MAX_CHUNK,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn with_sized<T>(body: T, preset_size: Option<usize>) -> Self
|
pub(crate) fn with_sized<T>(body: T, preset_size: Option<usize>) -> Self
|
||||||
where T: AsyncReadSeek + Send + 'r
|
where T: AsyncReadSeek + Send + 'r
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,3 +7,4 @@ pub mod mtls;
|
||||||
pub mod sni_resolver;
|
pub mod sni_resolver;
|
||||||
pub mod tracing;
|
pub mod tracing;
|
||||||
pub mod tls;
|
pub mod tls;
|
||||||
|
pub mod no_content;
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
//! Ensure that responses with a status of 204 or 304 do not have a body, and
|
||||||
|
//! for the former, do not have a Content-Length header.
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use rocket::http::Status;
|
||||||
|
|
||||||
|
#[get("/<code>")]
|
||||||
|
fn status(code: u16) -> (Status, &'static [u8]) {
|
||||||
|
(Status::new(code), &[1, 2, 3, 4])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn test_no_content() -> Result<()> {
|
||||||
|
let server = spawn!(Rocket::default().mount("/", routes![status]))?;
|
||||||
|
|
||||||
|
let client = Client::default();
|
||||||
|
let response = client.get(&server, "/204")?.send()?;
|
||||||
|
assert_eq!(response.status(), 204);
|
||||||
|
assert!(response.headers().get("Content-Length").is_none());
|
||||||
|
assert!(response.bytes()?.is_empty());
|
||||||
|
|
||||||
|
let response = client.get(&server, "/304")?.send()?;
|
||||||
|
assert_eq!(response.status(), 304);
|
||||||
|
assert_eq!(response.headers().get("Content-Length").unwrap(), "4");
|
||||||
|
assert!(response.bytes()?.is_empty());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
register!(test_no_content);
|
Loading…
Reference in New Issue