1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use crate::host::{Body, Bytes, Header, handler};
/// Handle for accessing and mutating the current HTTP request.
pub struct Request {
header: Header,
body: Body,
}
const KIND_REQ: i32 = 0;
impl Request {
/// Creates a new `Request` instance with header and body handles.
pub(crate) fn new() -> Self {
Self { header: Header::kind(KIND_REQ), body: Body::kind(KIND_REQ) }
}
/// Return the client source address (ip:port) as raw bytes.
///
/// ## Example ##
/// - IPv6 b"[fe80::90f4:16ff:fee0:24b3%enp5s0]:41236"
/// - IPv4 b"1.1.1.1:12345"
///
/// Supported are both IPv4 and IPv6
/// ## Note ##
/// A host who fails to get the remote address will trap (aka panic, "unreachable" instruction).
pub fn source_addr(&self) -> Bytes {
Bytes::from(handler::source_addr())
}
/// Return the HTTP protocol version (for example, `HTTP/1.1`).
pub fn version(&self) -> Bytes {
Bytes::from(handler::version())
}
/// Return the request method (for example, `GET` or `POST`).
pub fn method(&self) -> Bytes {
Bytes::from(handler::method())
}
/// Replace the request method with the provided bytes.
pub fn set_method(&self, method: &[u8]) {
handler::set_method(method);
}
/// Return the request URI as raw bytes.
pub fn uri(&self) -> Bytes {
Bytes::from(handler::uri())
}
/// Replace the request URI with the provided bytes.
pub fn set_uri(&self, uri: &[u8]) {
handler::set_uri(uri);
}
/// Return a handle for accessing and mutating request headers.
pub fn header(&self) -> &Header {
&self.header
}
/// Return a handle for reading or writing the request body.
pub fn body(&self) -> &Body {
&self.body
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn request_method() {
let request = Request::new();
let method = request.method();
// The mock returns "GET"
assert_eq!(&method, b"GET");
}
#[test]
fn request_version() {
let request = Request::new();
let version = request.version();
// The mock returns "HTTP/2.0"
assert!(!version.is_empty());
assert_eq!(version.to_str().unwrap(), "HTTP/2.0");
}
#[test]
fn request_uri() {
let request = Request::new();
let uri = request.uri();
// The mock returns "https://test"
assert!(uri.to_str().unwrap().contains("test"));
}
#[test]
fn request_source_addr() {
let request = Request::new();
let addr = request.source_addr();
// The mock returns "192.168.1.1"
assert_eq!(addr.to_str().unwrap(), "192.168.1.1");
}
#[test]
fn request_header_access() {
let request = Request::new();
let header = request.header();
// The mock provides headers: X-FOO, x-bar, x-baz
let names: Vec<_> = header.names_iter().collect();
assert_eq!(names.len(), 3);
}
#[test]
fn request_body_access() {
let request = Request::new();
let body = request.body();
let content = body.read();
// The mock returns "<html><body>test</body>"
assert!(content.to_str().unwrap().contains("html"));
}
#[test]
fn request_set_method() {
let request = Request::new();
// Should not panic - mock accepts any method
request.set_method(b"POST");
}
#[test]
fn request_set_uri() {
let request = Request::new();
// Should not panic - mock accepts any URI
request.set_uri(b"/new/path?query=value");
}
}