From 781c3119ab5a92d8e8bd1c765c976a39ee8a7592 Mon Sep 17 00:00:00 2001 From: 45gfg9 <45gfg9@45gfg9.net> Date: Thu, 30 Jan 2025 15:28:31 +0800 Subject: [PATCH] test: multipart ranges --- tests/range.rs | 67 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/tests/range.rs b/tests/range.rs index 511c244..cb56889 100644 --- a/tests/range.rs +++ b/tests/range.rs @@ -2,7 +2,7 @@ mod fixtures; mod utils; use fixtures::{server, Error, TestServer}; -use reqwest::header::HeaderValue; +use reqwest::header::{HeaderMap, HeaderName, HeaderValue}; use rstest::rstest; #[rstest] @@ -39,3 +39,68 @@ fn get_file_range_invalid(server: TestServer) -> Result<(), Error> { assert_eq!(resp.headers().get("content-range").unwrap(), "bytes */18"); Ok(()) } + +fn parse_multipart_body<'a>(body: &'a str, boundary: &str) -> Vec<(HeaderMap, &'a str)> { + body.split(&format!("--{}", boundary)) + .filter(|part| !part.is_empty() && *part != "--\r\n") + .map(|part| { + let (head, body) = part.trim_ascii().split_once("\r\n\r\n").unwrap(); + let headers = head + .split("\r\n") + .fold(HeaderMap::new(), |mut headers, header| { + let (key, value) = header.split_once(":").unwrap(); + let key = HeaderName::from_bytes(key.as_bytes()).unwrap(); + let value = HeaderValue::from_str(value.trim_ascii_start()).unwrap(); + headers.insert(key, value); + headers + }); + (headers, body) + }) + .collect() +} + +#[rstest] +fn get_file_multipart_range(server: TestServer) -> Result<(), Error> { + let resp = fetch!(b"GET", format!("{}index.html", server.url())) + .header("range", HeaderValue::from_static("bytes=0-11, 6-17")) + .send()?; + assert_eq!(resp.status(), 206); + assert_eq!(resp.headers().get("accept-ranges").unwrap(), "bytes"); + + let content_type = resp + .headers() + .get("content-type") + .unwrap() + .to_str()? + .to_string(); + assert!(content_type.starts_with("multipart/byteranges; boundary=")); + + let boundary = content_type.split_once('=').unwrap().1.trim_ascii_start(); + assert!(!boundary.is_empty()); + + let body = resp.text()?; + let parts = parse_multipart_body(&body, boundary); + assert_eq!(parts.len(), 2); + + let (headers, body) = &parts[0]; + assert_eq!(headers.get("content-range").unwrap(), "bytes 0-11/18"); + assert_eq!(*body, "This is inde"); + + let (headers, body) = &parts[1]; + assert_eq!(headers.get("content-range").unwrap(), "bytes 6-17/18"); + assert_eq!(*body, "s index.html"); + + Ok(()) +} + +#[rstest] +fn get_file_multipart_range_invalid(server: TestServer) -> Result<(), Error> { + let resp = fetch!(b"GET", format!("{}index.html", server.url())) + .header("range", HeaderValue::from_static("bytes=0-6, 20-30")) + .send()?; + assert_eq!(resp.status(), 416); + assert_eq!(resp.headers().get("content-range").unwrap(), "bytes */18"); + assert_eq!(resp.headers().get("accept-ranges").unwrap(), "bytes"); + assert_eq!(resp.headers().get("content-length").unwrap(), "0"); + Ok(()) +}