spin_contrib_http/
request.rs1use spin_sdk::http::{HeaderValue, Method, Request};
2
3const HEADER_SPIN_PATH_INFO: &str = "spin-path-info";
4
5pub trait Contrib {
7 fn get_route_segments(&self) -> Option<Vec<&str>>;
30
31 fn is_preflight_request(&self) -> bool;
33
34 fn get_header_value_as_string(&self, header_name: &str) -> String;
36}
37
38impl Contrib for Request {
39 fn get_route_segments(&self) -> Option<Vec<&str>> {
40 let spin_path_header_value = self.header(HEADER_SPIN_PATH_INFO)?;
41 let header_value = spin_path_header_value.as_str()?;
42 if header_value.trim().is_empty() || header_value == "/" {
43 return None;
44 };
45
46 let mut segments = header_value.split('/').collect::<Vec<&str>>();
47 segments.remove(0);
48 Some(segments)
49 }
50
51 fn is_preflight_request(&self) -> bool {
52 self.method() == &Method::Options && self.header(http::header::ORIGIN.as_str()).is_some()
53 }
54
55 fn get_header_value_as_string(&self, header_name: &str) -> String {
56 self.header(header_name)
57 .unwrap_or(&HeaderValue::string(String::default()))
58 .as_str()
59 .unwrap()
60 .to_string()
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use spin_sdk::http::{Method, RequestBuilder};
67
68 use super::*;
69
70 #[test]
71 fn get_route_segments_should_return_provided_segments() {
72 let req = RequestBuilder::new(Method::Get, "http://foo.bar")
73 .header(HEADER_SPIN_PATH_INFO, "/foo/bar/baz")
74 .body(())
75 .build();
76 let segments = req.get_route_segments();
77 assert_eq!(segments.is_some(), true);
78 let segments = segments.unwrap();
79 assert_eq!(segments.len(), 3);
80 assert_eq!(segments[0], "foo");
81 assert_eq!(segments[1], "bar");
82 assert_eq!(segments[2], "baz");
83 }
84
85 #[test]
86 fn get_route_segments_should_empty_vector_for_root_url() {
87 let test_data = vec!["/", "", " "];
88 for data in test_data {
89 let req = RequestBuilder::new(spin_sdk::http::Method::Get, "http://foo.bar")
90 .header(HEADER_SPIN_PATH_INFO, data)
91 .body(())
92 .build();
93
94 assert_eq!(req.get_route_segments(), None);
95 }
96 }
97
98 #[test]
99 fn get_header_value_as_string_should_return_correct_values() {
100 let test_data = vec![
101 ("my-header", "foo", "my-header", "foo"),
102 ("my-header", "", "my-header", ""),
103 ("my-header", "foo", "my-other-header", ""),
104 ("my-header", "", "my-other-header", ""),
105 ];
106 for data in test_data {
107 let req = RequestBuilder::new(spin_sdk::http::Method::Get, "http://foo.bar")
108 .header(data.0, data.1)
109 .body(())
110 .build();
111
112 assert_eq!(req.get_header_value_as_string(data.2), data.3);
113 }
114 }
115}