Skip to main content

http_wasm_guest/host/
request.rs

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