#[must_use]
pub fn exotic_methods() -> Vec<&'static str> {
vec![
"PROPFIND",
"PROPPATCH",
"MKCOL",
"COPY",
"MOVE",
"LOCK",
"UNLOCK",
"REPORT",
"ACL",
"SEARCH",
"PURGE",
"BAN",
"REFRESH",
"VERSION-CONTROL",
"MKWORKSPACE",
"UPDATE",
"CHECKIN",
"CHECKOUT",
"MKACTIVITY",
"BASELINE-CONTROL",
"MERGE",
"PATCH",
"TRACE",
"get",
"post",
"put",
"delete",
"GeT",
"PoSt",
"PuT",
"DeLeTe",
" GET",
"\tGET",
" GET ",
]
}
#[must_use]
pub fn absolute_uri_request_line(method: &str, host_in_uri: &str, path: &str) -> String {
format!("{method} http://{host_in_uri}{path} HTTP/1.1")
}
#[must_use]
pub fn absolute_uri_https_request_line(method: &str, host_in_uri: &str, path: &str) -> String {
format!("{method} https://{host_in_uri}{path} HTTP/1.1")
}
#[must_use]
pub fn request_line_with_version(method: &str, path: &str, version: &str) -> String {
format!("{method} {path} {version}")
}
#[must_use]
pub fn request_line_with_whitespace(
method: &str,
method_sep: &str,
path: &str,
path_sep: &str,
version: &str,
) -> String {
format!("{method}{method_sep}{path}{path_sep}{version}")
}
#[must_use]
pub fn asterisk_form_request_line(method: &str) -> String {
format!("{method} * HTTP/1.1")
}
#[must_use]
pub fn authority_form_request_line(method: &str, host: &str, port: u16) -> String {
format!("{method} {host}:{port} HTTP/1.1")
}
pub const REQUEST_LINE_TRICKS: &[&str] = &[
"exotic_methods",
"absolute_uri_request_line",
"absolute_uri_https_request_line",
"request_line_with_version",
"request_line_with_whitespace",
"asterisk_form_request_line",
"authority_form_request_line",
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn exotic_methods_includes_propfind() {
assert!(exotic_methods().contains(&"PROPFIND"));
}
#[test]
fn exotic_methods_includes_purge() {
assert!(exotic_methods().contains(&"PURGE"));
}
#[test]
fn exotic_methods_includes_lowercase() {
assert!(exotic_methods().contains(&"get"));
assert!(exotic_methods().contains(&"post"));
}
#[test]
fn exotic_methods_includes_mixed_case() {
assert!(exotic_methods().contains(&"GeT"));
}
#[test]
fn exotic_methods_includes_whitespace_pad() {
assert!(exotic_methods().iter().any(|m| m.starts_with(' ')));
assert!(exotic_methods().iter().any(|m| m.starts_with('\t')));
}
#[test]
fn exotic_methods_minimum_count() {
assert!(
exotic_methods().len() >= 25,
"regression: lost coverage of exotic-method set"
);
}
#[test]
fn absolute_uri_basic() {
let rl = absolute_uri_request_line("GET", "evil.example", "/admin");
assert_eq!(rl, "GET http://evil.example/admin HTTP/1.1");
}
#[test]
fn absolute_uri_https() {
let rl = absolute_uri_https_request_line("POST", "evil.example", "/api");
assert_eq!(rl, "POST https://evil.example/api HTTP/1.1");
}
#[test]
fn absolute_uri_preserves_query() {
let rl = absolute_uri_request_line("GET", "h", "/a?b=c&d=e");
assert!(rl.contains("?b=c&d=e"));
}
#[test]
fn version_explicit_http_0_9() {
let rl = request_line_with_version("GET", "/", "HTTP/0.9");
assert_eq!(rl, "GET / HTTP/0.9");
}
#[test]
fn version_explicit_http_1_99() {
let rl = request_line_with_version("GET", "/", "HTTP/1.99");
assert_eq!(rl, "GET / HTTP/1.99");
}
#[test]
fn version_explicit_http_2_on_h1_wire() {
let rl = request_line_with_version("GET", "/", "HTTP/2.0");
assert_eq!(rl, "GET / HTTP/2.0");
}
#[test]
fn whitespace_tab_between_tokens() {
let rl = request_line_with_whitespace("GET", "\t", "/", "\t", "HTTP/1.1");
assert_eq!(rl, "GET\t/\tHTTP/1.1");
assert!(!rl.contains(' '), "no SP, only TAB");
}
#[test]
fn whitespace_multiple_spaces() {
let rl = request_line_with_whitespace("GET", " ", "/", " ", "HTTP/1.1");
assert_eq!(rl, "GET / HTTP/1.1");
}
#[test]
fn whitespace_mixed() {
let rl = request_line_with_whitespace("GET", " \t ", "/", "\t \t", "HTTP/1.1");
assert!(rl.contains('\t'));
assert!(rl.contains(' '));
}
#[test]
fn asterisk_form_options() {
let rl = asterisk_form_request_line("OPTIONS");
assert_eq!(rl, "OPTIONS * HTTP/1.1");
}
#[test]
fn asterisk_form_invalid_method_still_produces_string() {
let rl = asterisk_form_request_line("GET");
assert_eq!(rl, "GET * HTTP/1.1");
}
#[test]
fn authority_form_connect() {
let rl = authority_form_request_line("CONNECT", "internal", 8080);
assert_eq!(rl, "CONNECT internal:8080 HTTP/1.1");
}
#[test]
fn authority_form_high_port() {
let rl = authority_form_request_line("CONNECT", "h", u16::MAX);
assert!(rl.ends_with("65535 HTTP/1.1"));
}
#[test]
fn registry_lists_every_function_we_expose() {
assert_eq!(REQUEST_LINE_TRICKS.len(), 7);
}
#[test]
fn no_function_produces_crlf_in_output() {
let candidates = vec![
absolute_uri_request_line("GET", "h", "/p"),
absolute_uri_https_request_line("GET", "h", "/p"),
request_line_with_version("GET", "/", "HTTP/0.9"),
request_line_with_whitespace("GET", " ", "/", " ", "HTTP/1.1"),
asterisk_form_request_line("OPTIONS"),
authority_form_request_line("CONNECT", "h", 443),
];
for c in candidates {
assert!(!c.contains("\r\n"), "no CRLF in request line: {c:?}");
assert!(!c.contains('\n'), "no LF in request line: {c:?}");
}
}
#[test]
fn deterministic_across_calls() {
let a = exotic_methods();
let b = exotic_methods();
assert_eq!(a, b);
}
#[test]
fn adversarial_long_path_no_panic() {
let big = "/a".repeat(10_000);
let _ = absolute_uri_request_line("GET", "h", &big);
let _ = request_line_with_version("GET", &big, "HTTP/1.1");
}
}