Skip to content

Commit

Permalink
Merge pull request #76 from rmja/no-content
Browse files Browse the repository at this point in the history
Handle no-content status code 204
  • Loading branch information
lulf committed May 22, 2024
2 parents c9762fe + 5a9338d commit c13a2e8
Showing 1 changed file with 44 additions and 1 deletion.
45 changes: 44 additions & 1 deletion src/response/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ where
let mut response = httparse::Response::new(&mut headers);
response.parse(&header_buf[..header_len]).unwrap();

let status = response.code.unwrap().into();
let status: StatusCode = response.code.unwrap().into();
let mut content_type = None;
let mut content_length = None;
let mut transfer_encoding = Vec::new();
Expand All @@ -106,6 +106,16 @@ where
}
}

if status.is_informational() || status == Status::NoContent {
// According to https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2
// A server MUST NOT send a Content-Length header field in any response
// with a status code of 1xx (Informational) or 204 (No Content)
if content_length.unwrap_or_default() != 0 {
return Err(Error::Codec);
}
content_length = Some(0);
}

// The number of bytes that we have read into the body part of the response
let raw_body_read = pos - header_len;

Expand Down Expand Up @@ -533,6 +543,39 @@ mod tests {
Error, TryBufRead,
};

#[tokio::test]
async fn can_read_no_content() {
let mut conn = FakeSingleReadConnection::new(b"HTTP/1.1 204 No Content\r\n\r\n");
let mut response_buf = [0; 200];
let response = Response::read(&mut conn, Method::POST, &mut response_buf)
.await
.unwrap();

assert_eq!(b"", response.body().read_to_end().await.unwrap());
assert!(conn.is_exhausted());
}

#[tokio::test]
async fn can_read_no_content_with_zero_content_length() {
let mut conn = FakeSingleReadConnection::new(b"HTTP/1.1 204 No Content\r\nContent-Length: 0\r\n\r\n");
let mut response_buf = [0; 200];
let response = Response::read(&mut conn, Method::POST, &mut response_buf)
.await
.unwrap();

assert_eq!(b"", response.body().read_to_end().await.unwrap());
assert!(conn.is_exhausted());
}

#[tokio::test]
async fn cannot_read_no_content_with_nonzero_content_length() {
let mut conn = FakeSingleReadConnection::new(b"HTTP/1.1 204 No Content\r\nContent-Length: 5\r\n\r\nHELLO");
let mut response_buf = [0; 200];
let response = Response::read(&mut conn, Method::POST, &mut response_buf).await;

assert!(matches!(response, Err(Error::Codec)));
}

#[tokio::test]
async fn can_read_with_content_length_with_same_buffer() {
let mut conn = FakeSingleReadConnection::new(b"HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nHELLO WORLD");
Expand Down

0 comments on commit c13a2e8

Please sign in to comment.