75 lines
2.5 KiB
Rust
75 lines
2.5 KiB
Rust
//! Tests for the request parser.
|
||
//! 请求解析器的测试。
|
||
//!
|
||
//! They live here rather than inside the module so that `src/` holds no test
|
||
//! code, as it does in `apsis-rs`. An integration test is a separate crate and
|
||
//! reaches only what the library makes public, so the few internal items the
|
||
//! tests need are opened through `apsis_book::testkit`.
|
||
//!
|
||
//! 它们放在这里而不是模块内部,使 `src/` 不含测试代码,与 `apsis-rs` 一致。
|
||
//! 集成测试是独立的 crate,只能触达库公开的部分,因此测试所需的那少数内部条目
|
||
//! 经 `apsis_book::testkit` 开放。
|
||
|
||
use apsis_book::http::request::*;
|
||
|
||
use std::io::Cursor;
|
||
|
||
#[test]
|
||
fn parses_a_get_request() {
|
||
let raw = b"GET /health?verbose=1 HTTP/1.1\r\nHost: localhost\r\nX-Test: a\r\n\r\n";
|
||
let request = read_request(&mut Cursor::new(raw), Limits::default()).unwrap();
|
||
assert_eq!(request.method, Method::Get);
|
||
assert_eq!(request.path, "/health");
|
||
assert_eq!(request.query.as_deref(), Some("verbose=1"));
|
||
assert_eq!(request.header("x-test"), Some("a"));
|
||
assert_eq!(request.header("X-Test"), Some("a"));
|
||
assert_eq!(
|
||
request.query_pairs().get("verbose").map(String::as_str),
|
||
Some("1")
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn parses_a_post_body() {
|
||
let raw = b"POST /api/tools/x HTTP/1.1\r\nContent-Length: 5\r\n\r\nhello";
|
||
let request = read_request(&mut Cursor::new(raw), Limits::default()).unwrap();
|
||
assert_eq!(request.method, Method::Post);
|
||
assert_eq!(request.body_text(), Some("hello"));
|
||
}
|
||
|
||
#[test]
|
||
fn rejects_malformed_input() {
|
||
let cases: &[&[u8]] = &[
|
||
b"GET\r\n\r\n",
|
||
b"GET / HTTP/2.0\r\n\r\n",
|
||
b"GET / HTTP/1.1\r\nbroken\r\n\r\n",
|
||
b"GET / HTTP/1.1\r\nContent-Length: nope\r\n\r\n",
|
||
];
|
||
for case in cases {
|
||
assert!(read_request(&mut Cursor::new(*case), Limits::default()).is_err());
|
||
}
|
||
}
|
||
|
||
#[test]
|
||
fn decodes_percent_escapes() {
|
||
let raw = b"GET /search?q=a%20b+%E2%82%AC HTTP/1.1\r\n\r\n";
|
||
let request = read_request(&mut Cursor::new(raw), Limits::default()).unwrap();
|
||
assert_eq!(
|
||
request.query_pairs().get("q").map(String::as_str),
|
||
Some("a b €")
|
||
);
|
||
}
|
||
|
||
#[test]
|
||
fn rejects_an_oversized_body() {
|
||
let raw = b"POST /x HTTP/1.1\r\nContent-Length: 100\r\n\r\n";
|
||
let limits = Limits {
|
||
max_body_bytes: 4,
|
||
..Limits::default()
|
||
};
|
||
assert!(matches!(
|
||
read_request(&mut Cursor::new(raw), limits),
|
||
Err(RequestError::TooLarge(_))
|
||
));
|
||
}
|