Skip to content

Commit dd5fb13

Browse files
committed
Improve clarity of Transfer-Encoding errors. Don't error on identity TE
1 parent 51f313d commit dd5fb13

File tree

1 file changed

+112
-10
lines changed

1 file changed

+112
-10
lines changed

spansy/src/http/span.rs

Lines changed: 112 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,23 @@ fn request_body_len(request: &Request) -> Result<usize, ParseError> {
222222
// the Transfer-Encoding overrides the Content-Length
223223
if request
224224
.headers_with_name("Transfer-Encoding")
225-
.next()
226-
.is_some()
225+
.any(|h| {
226+
std::str::from_utf8(h.value.0.as_bytes())
227+
.unwrap_or("")
228+
.split(',')
229+
.any(|v| v.trim() != "identity")
230+
})
227231
{
228-
Err(ParseError(
229-
"Transfer-Encoding not supported yet".to_string(),
230-
))
232+
let bad_values = request
233+
.headers_with_name("Transfer-Encoding")
234+
.map(|h| std::str::from_utf8(h.value.0.as_bytes()).unwrap_or(""))
235+
.collect::<Vec<_>>()
236+
.join(", ");
237+
238+
Err(ParseError(format!(
239+
"Transfer-Encoding other than identity not supported yet: {:?}",
240+
bad_values
241+
)))
231242
} else if let Some(h) = request.headers_with_name("Content-Length").next() {
232243
// If a valid Content-Length header field is present without Transfer-Encoding, its decimal value
233244
// defines the expected message body length in octets.
@@ -258,12 +269,23 @@ fn response_body_len(response: &Response) -> Result<usize, ParseError> {
258269

259270
if response
260271
.headers_with_name("Transfer-Encoding")
261-
.next()
262-
.is_some()
272+
.any(|h| {
273+
std::str::from_utf8(h.value.0.as_bytes())
274+
.unwrap_or("")
275+
.split(',')
276+
.any(|v| v.trim() != "identity")
277+
})
263278
{
264-
Err(ParseError(
265-
"Transfer-Encoding not supported yet".to_string(),
266-
))
279+
let bad_values = response
280+
.headers_with_name("Transfer-Encoding")
281+
.map(|h| std::str::from_utf8(h.value.0.as_bytes()).unwrap_or(""))
282+
.collect::<Vec<_>>()
283+
.join(", ");
284+
285+
Err(ParseError(format!(
286+
"Transfer-Encoding other than identity not supported yet: {:?}",
287+
bad_values
288+
)))
267289
} else if let Some(h) = response.headers_with_name("Content-Length").next() {
268290
// If a valid Content-Length header field is present without Transfer-Encoding, its decimal value
269291
// defines the expected message body length in octets.
@@ -363,6 +385,46 @@ mod tests {
363385
Content-Length: 14\r\n\r\n\
364386
{\"foo\": \"bar\"}";
365387

388+
const TEST_REQUEST_TRANSFER_ENCODING_IDENTITY: &[u8] = b"\
389+
POST / HTTP/1.1\r\n\
390+
Transfer-Encoding: identity\r\n\
391+
Content-Length: 12\r\n\r\n\
392+
Hello World!";
393+
394+
const TEST_RESPONSE_TRANSFER_ENCODING_IDENTITY: &[u8] = b"\
395+
HTTP/1.1 200 OK\r\n\
396+
Transfer-Encoding: identity\r\n\
397+
Content-Length: 12\r\n\r\n\
398+
Hello World!";
399+
400+
const TEST_REQUEST_TRANSFER_ENCODING_CHUNKED: &[u8] = b"\
401+
POST / HTTP/1.1\r\n\
402+
Transfer-Encoding: chunked\r\n\r\n\
403+
a\r\n\
404+
Hello World!\r\n\
405+
0\r\n\r\n";
406+
407+
const TEST_RESPONSE_TRANSFER_ENCODING_CHUNKED: &[u8] = b"\
408+
HTTP/1.1 200 OK\r\n\
409+
Transfer-Encoding: chunked\r\n\r\n\
410+
a\r\n\
411+
Hello World!\r\n\
412+
0\r\n\r\n";
413+
414+
const TEST_REQUEST_TRANSFER_ENCODING_MULTIPLE: &[u8] = b"\
415+
POST / HTTP/1.1\r\n\
416+
Transfer-Encoding: chunked, identity\r\n\r\n\
417+
a\r\n\
418+
Hello World!\r\n\
419+
0\r\n\r\n";
420+
421+
const TEST_RESPONSE_TRANSFER_ENCODING_MULTIPLE: &[u8] = b"\
422+
HTTP/1.1 200 OK\r\n\
423+
Transfer-Encoding: chunked, identity\r\n\r\n\
424+
a\r\n\
425+
Hello World!\r\n\
426+
0\r\n\r\n";
427+
366428
#[test]
367429
fn test_parse_request() {
368430
let req = parse_request(TEST_REQUEST).unwrap();
@@ -496,4 +558,44 @@ mod tests {
496558

497559
assert_eq!(value.span(), "{\"foo\": \"bar\"}");
498560
}
561+
562+
#[test]
563+
fn test_parse_request_transfer_encoding_identity() {
564+
let req = parse_request(TEST_REQUEST_TRANSFER_ENCODING_IDENTITY).unwrap();
565+
assert_eq!(req.body.unwrap().span(), b"Hello World!".as_slice());
566+
}
567+
568+
#[test]
569+
fn test_parse_response_transfer_encoding_identity() {
570+
let res = parse_response(TEST_RESPONSE_TRANSFER_ENCODING_IDENTITY).unwrap();
571+
assert_eq!(res.body.unwrap().span(), b"Hello World!".as_slice());
572+
}
573+
574+
#[test]
575+
fn test_parse_request_transfer_encoding_chunked() {
576+
let err = parse_request(TEST_REQUEST_TRANSFER_ENCODING_CHUNKED).unwrap_err();
577+
assert!(matches!(err, ParseError(_)));
578+
assert!(err.to_string().contains("Transfer-Encoding other than identity not supported yet"));
579+
}
580+
581+
#[test]
582+
fn test_parse_response_transfer_encoding_chunked() {
583+
let err = parse_response(TEST_RESPONSE_TRANSFER_ENCODING_CHUNKED).unwrap_err();
584+
assert!(matches!(err, ParseError(_)));
585+
assert!(err.to_string().contains("Transfer-Encoding other than identity not supported yet"));
586+
}
587+
588+
#[test]
589+
fn test_parse_request_transfer_encoding_multiple() {
590+
let err = parse_request(TEST_REQUEST_TRANSFER_ENCODING_MULTIPLE).unwrap_err();
591+
assert!(matches!(err, ParseError(_)));
592+
assert!(err.to_string().contains("Transfer-Encoding other than identity not supported yet"));
593+
}
594+
595+
#[test]
596+
fn test_parse_response_transfer_encoding_multiple() {
597+
let err = parse_response(TEST_RESPONSE_TRANSFER_ENCODING_MULTIPLE).unwrap_err();
598+
assert!(matches!(err, ParseError(_)));
599+
assert!(err.to_string().contains("Transfer-Encoding other than identity not supported yet"));
600+
}
499601
}

0 commit comments

Comments
 (0)