use ehttpd::bytes::{Data, Source};
use ehttpd::http::Request;
use std::io::Read;
#[test]
fn request_header_is_parsed() {
let mut source = Source::from(concat! {
"POST /resource HTTP/1.1\r\n",
"Host: example.test\r\n",
"\r\n",
});
let request: Request =
Request::from_stream(&mut source).expect("failed to parse request").expect("request is missing");
assert_eq!(request.method, b"POST");
assert_eq!(request.target, b"/resource");
assert_eq!(request.version, b"HTTP/1.1");
assert_eq!(request.field("host").expect("host field is missing").as_ref(), b"example.test");
}
#[test]
fn closed_connection_has_no_request() {
let mut source = Source::default();
let request: Option<Request> = Request::from_stream(&mut source).expect("failed to parse request");
assert!(request.is_none());
}
#[test]
fn oversized_header_is_rejected() {
let mut source = Source::from(concat! {
"GET / HTTP/1.1\r\n",
"\r\n",
});
let request: Result<Option<Request<16>>, _> = Request::from_stream(&mut source);
let error = request.expect_err("oversized header was accepted");
assert_eq!(error.error, "HTTP header is too large");
}
#[test]
fn body_with_content_length_is_read() {
let mut source = Source::from(concat! {
"POST / HTTP/1.1\r\n",
"Content-Length: 6\r\n",
"\r\n",
"<BODY>",
});
let mut request: Request =
Request::from_stream(&mut source).expect("failed to parse request").expect("request is missing");
let body = request.read_body_data(6).expect("failed to read request body");
assert_eq!(body, Some(Data::new_static(b"<BODY>")));
}
#[test]
fn body_without_content_length_is_not_read() {
let mut source = Source::from(concat! {
"POST / HTTP/1.1\r\n",
"\r\n",
"<BODY>",
});
let mut request: Request =
Request::from_stream(&mut source).expect("failed to parse request").expect("request is missing");
let body = request.read_body_data(6).expect("failed to inspect request body");
assert!(body.is_none());
let mut unread = [0; 6];
request.stream.read_exact(&mut unread).expect("failed to read remaining body");
assert_eq!(unread, *b"<BODY>");
}
#[test]
fn chunked_body_is_not_read() {
let mut source = Source::from(concat! {
"POST / HTTP/1.1\r\n",
"Transfer-Encoding: chunked\r\n",
"\r\n",
"6\r\n",
"<BODY>\r\n",
"0\r\n",
"\r\n",
});
let mut request: Request =
Request::from_stream(&mut source).expect("failed to parse request").expect("request is missing");
let body = request.read_body_data(6).expect("failed to inspect request body");
assert!(body.is_none());
}
#[test]
fn body_over_limit_is_rejected() {
let mut source = Source::from(concat! {
"POST / HTTP/1.1\r\n",
"Content-Length: 6\r\n",
"\r\n",
"<BODY>",
});
let mut request: Request =
Request::from_stream(&mut source).expect("failed to parse request").expect("request is missing");
let body = request.read_body_data(5);
let error = body.expect_err("oversized body was accepted");
assert_eq!(error.error, "HTTP body is too large");
}
#[test]
fn truncated_body_is_rejected() {
let mut source = Source::from(concat! {
"POST / HTTP/1.1\r\n",
"Content-Length: 7\r\n",
"\r\n",
"<BODY>",
});
let mut request: Request =
Request::from_stream(&mut source).expect("failed to parse request").expect("request is missing");
let body = request.read_body_data(7);
let error = body.expect_err("truncated body was accepted");
assert_eq!(error.error, "Truncated HTTP body");
}
#[test]
fn connection_close_is_recognized_inside_a_token_list() {
let mut source = Source::from(concat! {
"GET / HTTP/1.1\r\n",
"Host: example.test\r\n",
"Connection: keep-alive, Close, upgrade\r\n",
"\r\n",
});
let request: Request =
Request::from_stream(&mut source).expect("failed to parse request").expect("request is missing");
assert!(request.has_connection_close());
}