|
16 | 16 |
|
17 | 17 | use http::{header, HeaderValue};
|
18 | 18 | use log::warn;
|
| 19 | +use pingora_error::Result; |
19 | 20 | use pingora_http::{HMap, RequestHeader, ResponseHeader};
|
20 | 21 | use std::str;
|
21 | 22 | use std::time::Duration;
|
@@ -243,3 +244,51 @@ pub(super) fn populate_headers(
|
243 | 244 | }
|
244 | 245 | used_header_index
|
245 | 246 | }
|
| 247 | + |
| 248 | +// RFC 7230: |
| 249 | +// If a message is received without Transfer-Encoding and with |
| 250 | +// either multiple Content-Length header fields having differing |
| 251 | +// field-values or a single Content-Length header field having an |
| 252 | +// invalid value, then the message framing is invalid and the |
| 253 | +// recipient MUST treat it as an unrecoverable error. |
| 254 | +pub(super) fn check_dup_content_length(headers: &HMap) -> Result<()> { |
| 255 | + if headers.get(header::TRANSFER_ENCODING).is_some() { |
| 256 | + // If TE header, ignore CL |
| 257 | + return Ok(()); |
| 258 | + } |
| 259 | + let mut cls = headers.get_all(header::CONTENT_LENGTH).into_iter(); |
| 260 | + if cls.next().is_none() { |
| 261 | + // no CL header is fine. |
| 262 | + return Ok(()); |
| 263 | + } |
| 264 | + if cls.next().is_some() { |
| 265 | + // duplicated CL is bad |
| 266 | + return crate::Error::e_explain( |
| 267 | + crate::ErrorType::InvalidHTTPHeader, |
| 268 | + "duplicated Content-Length header", |
| 269 | + ); |
| 270 | + } |
| 271 | + Ok(()) |
| 272 | +} |
| 273 | + |
| 274 | +#[cfg(test)] |
| 275 | +mod test { |
| 276 | + use super::*; |
| 277 | + use http::header::{CONTENT_LENGTH, TRANSFER_ENCODING}; |
| 278 | + |
| 279 | + #[test] |
| 280 | + fn test_check_dup_content_length() { |
| 281 | + let mut headers = HMap::new(); |
| 282 | + |
| 283 | + assert!(check_dup_content_length(&headers).is_ok()); |
| 284 | + |
| 285 | + headers.append(CONTENT_LENGTH, "1".try_into().unwrap()); |
| 286 | + assert!(check_dup_content_length(&headers).is_ok()); |
| 287 | + |
| 288 | + headers.append(CONTENT_LENGTH, "2".try_into().unwrap()); |
| 289 | + assert!(check_dup_content_length(&headers).is_err()); |
| 290 | + |
| 291 | + headers.append(TRANSFER_ENCODING, "chunkeds".try_into().unwrap()); |
| 292 | + assert!(check_dup_content_length(&headers).is_ok()); |
| 293 | + } |
| 294 | +} |
0 commit comments