107 lines
3.9 KiB
Rust
107 lines
3.9 KiB
Rust
mod fixtures;
|
|
mod utils;
|
|
|
|
use fixtures::{server, Error, TestServer};
|
|
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
|
use rstest::rstest;
|
|
|
|
#[rstest]
|
|
fn get_file_range(server: TestServer) -> Result<(), Error> {
|
|
let resp = fetch!(b"GET", format!("{}index.html", server.url()))
|
|
.header("range", HeaderValue::from_static("bytes=0-6"))
|
|
.send()?;
|
|
assert_eq!(resp.status(), 206);
|
|
assert_eq!(resp.headers().get("content-range").unwrap(), "bytes 0-6/18");
|
|
assert_eq!(resp.headers().get("accept-ranges").unwrap(), "bytes");
|
|
assert_eq!(resp.headers().get("content-length").unwrap(), "7");
|
|
assert_eq!(resp.text()?, "This is");
|
|
Ok(())
|
|
}
|
|
|
|
#[rstest]
|
|
fn get_file_range_beyond(server: TestServer) -> Result<(), Error> {
|
|
let resp = fetch!(b"GET", format!("{}index.html", server.url()))
|
|
.header("range", HeaderValue::from_static("bytes=12-20"))
|
|
.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(())
|
|
}
|
|
|
|
#[rstest]
|
|
fn get_file_range_invalid(server: TestServer) -> Result<(), Error> {
|
|
let resp = fetch!(b"GET", format!("{}index.html", server.url()))
|
|
.header("range", HeaderValue::from_static("bytes=20-"))
|
|
.send()?;
|
|
assert_eq!(resp.status(), 416);
|
|
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(())
|
|
}
|