1use super::*;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct Session(
11 pub String,
13 pub Option<u64>,
15);
16
17impl Session {
18 pub fn with_timeout(id: String, timeout: u64) -> Self {
19 Self(id, Some(timeout))
20 }
21}
22
23impl std::ops::Deref for Session {
24 type Target = str;
25
26 fn deref(&self) -> &Self::Target {
27 &self.0
28 }
29}
30
31impl AsRef<str> for Session {
32 fn as_ref(&self) -> &str {
33 &self.0
34 }
35}
36
37impl<'a> From<&'a str> for Session {
38 fn from(v: &'a str) -> Session {
39 Session(v.into(), None)
40 }
41}
42
43impl From<String> for Session {
44 fn from(v: String) -> Session {
45 Session(v, None)
46 }
47}
48
49impl super::TypedHeader for Session {
50 fn from_headers(headers: impl AsRef<Headers>) -> Result<Option<Self>, HeaderParseError> {
51 let headers = headers.as_ref();
52
53 let header = match headers.get(&SESSION) {
54 None => return Ok(None),
55 Some(header) => header,
56 };
57
58 let mut iter = header.as_str().split(';');
59
60 let session_id = iter.next().ok_or(HeaderParseError)?;
61 let timeout = iter
62 .find_map(|s| s.strip_prefix("timeout="))
63 .map(|s| s.parse::<u64>())
64 .transpose()
65 .map_err(|_| HeaderParseError)?;
66
67 Ok(Some(Session(session_id.into(), timeout)))
68 }
69
70 fn insert_into(&self, mut headers: impl AsMut<Headers>) {
71 let headers = headers.as_mut();
72
73 if let Some(timeout) = self.1 {
74 headers.insert(SESSION, format!("{};timeout={}", self.0, timeout));
75 } else {
76 headers.insert(SESSION, self.0.to_string());
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_from_headers() {
87 let strict_headers = [
88 ("12345678", Some(Session("12345678".to_string(), None))),
89 (
90 "12345678;timeout=60",
91 Some(Session("12345678".to_string(), Some(60))),
92 ),
93 (
94 "lskdjf238742dkjlskjd;timeout=60",
95 Some(Session("lskdjf238742dkjlskjd".to_string(), Some(60))),
96 ),
97 (
98 "alskdjalskjdalskjdalksjd;timeout=60",
99 Some(Session("alskdjalskjdalskjdalksjd".to_string(), Some(60))),
100 ),
101 ];
102
103 let loose_headers = [
104 (
105 "12345678;timeout=60;special",
106 Some(Session("12345678".to_string(), Some(60))),
107 ),
108 (
109 "12345678;timeout=60;393939393",
110 Some(Session("12345678".to_string(), Some(60))),
111 ),
112 (
113 "12345678;timeout=60;393;93;93;93",
114 Some(Session("12345678".to_string(), Some(60))),
115 ),
116 (
117 "12345678;special;timeout=600",
118 Some(Session("12345678".to_string(), Some(600))),
119 ),
120 (
121 "12345678;extra;extra;extra;timeout=600",
122 Some(Session("12345678".to_string(), Some(600))),
123 ),
124 (
125 "wjdl38ek98;timeout=60;special",
126 Some(Session("wjdl38ek98".to_string(), Some(60))),
127 ),
128 (
129 "wjdl38ek98;timeout=60;393939393",
130 Some(Session("wjdl38ek98".to_string(), Some(60))),
131 ),
132 (
133 "wjdl38ek98;timeout=60;393;93;93;93",
134 Some(Session("wjdl38ek98".to_string(), Some(60))),
135 ),
136 (
137 "wjdl38ek98;special;timeout=600",
138 Some(Session("wjdl38ek98".to_string(), Some(600))),
139 ),
140 (
141 "wjdl38ek98;extra;extra;extra;timeout=600",
142 Some(Session("wjdl38ek98".to_string(), Some(600))),
143 ),
144 ];
145
146 let bad_headers = [
147 "12345678;timeout=aa",
148 "12345678;timeout=a6a",
149 "12345678;timeout=!!!",
150 "12345678;timeout=18446744073709551616",
151 "12345678;timeout=18446744073709551616;special",
152 "12345678;special;timeout=18446744073709551616",
153 "12345678;timeout=-1",
154 "12345678;timeout=-2",
155 ];
156
157 let not_session_headers = [(AUTHORIZATION, "blah"), (ACCEPT, "application/sdp")];
158
159 for (header, expected) in strict_headers {
160 let mut test_headers = Headers::new();
161 test_headers.insert(SESSION, header);
162 let from_headers_result =
163 Session::from_headers(test_headers).expect("strict_headers should not error");
164
165 assert_eq!(from_headers_result, expected, "{header}");
166 }
167
168 for (header, expected) in loose_headers {
169 let mut test_headers = Headers::new();
170 test_headers.insert(SESSION, header);
171 let from_headers_result =
172 Session::from_headers(test_headers).expect("loose_errors should not error");
173
174 assert_eq!(from_headers_result, expected, "{header}");
175 }
176
177 for header in bad_headers {
178 let mut test_headers = Headers::new();
179 test_headers.insert(SESSION, header);
180
181 Session::from_headers(test_headers)
182 .expect_err("bad_headers should all give HeaderParserErrors");
183 }
184
185 for (header, value) in not_session_headers {
186 let mut test_headers = Headers::new();
187 test_headers.insert(header.clone(), value);
188 let from_headers_result =
189 Session::from_headers(test_headers).expect("not_session_headers should not error");
190
191 assert_eq!(from_headers_result, None, "{header}:{value}");
192 }
193 }
194}