Skip to content

Commit 2ee67c1

Browse files
committed
Use structured ContentLength parser
1 parent 8682991 commit 2ee67c1

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

src/server/decode.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use std::str::FromStr;
55
use async_dup::{Arc, Mutex};
66
use async_std::io::{BufReader, Read, Write};
77
use async_std::{prelude::*, task};
8-
use http_types::headers::{CONTENT_LENGTH, EXPECT, TRANSFER_ENCODING};
8+
use http_types::content::ContentLength;
9+
use http_types::headers::{EXPECT, TRANSFER_ENCODING};
910
use http_types::{ensure, ensure_eq, format_err};
1011
use http_types::{Body, Method, Request, Url};
1112

@@ -82,9 +83,13 @@ where
8283
req.append_header(header.name, std::str::from_utf8(header.value)?);
8384
}
8485

85-
let content_length = req.header(CONTENT_LENGTH);
86+
let content_length = ContentLength::from_headers(&req)?;
8687
let transfer_encoding = req.header(TRANSFER_ENCODING);
8788

89+
// Return a 400 status if both Content-Length and Transfer-Encoding headers
90+
// are set to prevent request smuggling attacks.
91+
//
92+
// https://tools.ietf.org/html/rfc7230#section-3.3.3
8893
http_types::ensure_status!(
8994
content_length.is_none() || transfer_encoding.is_none(),
9095
400,
@@ -124,11 +129,11 @@ where
124129
req.set_body(Body::from_reader(reader, None));
125130
return Ok(Some((req, BodyReader::Chunked(reader_clone))));
126131
} else if let Some(len) = content_length {
127-
let len = len.last().as_str().parse::<usize>()?;
128-
let reader = Arc::new(Mutex::new(reader.take(len as u64)));
132+
let len = len.len();
133+
let reader = Arc::new(Mutex::new(reader.take(len)));
129134
req.set_body(Body::from_reader(
130135
BufReader::new(ReadNotifier::new(reader.clone(), body_read_sender)),
131-
Some(len),
136+
Some(len as usize),
132137
));
133138
Ok(Some((req, BodyReader::Fixed(reader))))
134139
} else {

0 commit comments

Comments
 (0)