1use std::fmt;
4
5use serve_net::{ClientInfo, Envelope, HttpRequest, Method, Scheme};
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
11pub struct RequestId {
12 connection: u64,
13 seq: u32,
14}
15
16impl RequestId {
17 pub(crate) fn of(env: &Envelope) -> Self {
18 Self {
19 connection: env.connection().get(),
20 seq: env.seq().get(),
21 }
22 }
23
24 #[must_use]
26 pub const fn connection(&self) -> u64 {
27 self.connection
28 }
29
30 #[must_use]
32 pub const fn seq(&self) -> u32 {
33 self.seq
34 }
35}
36
37impl fmt::Display for RequestId {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(f, "{:x}-{}", self.connection, self.seq)
40 }
41}
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub struct Ambiguous;
48
49impl fmt::Display for Ambiguous {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 f.write_str("the cookie appears more than once")
52 }
53}
54
55impl std::error::Error for Ambiguous {}
56
57#[derive(Clone, Copy)]
61pub struct Request<'r> {
62 pub(crate) http: &'r HttpRequest<'r>,
63 pub(crate) env: &'r Envelope,
64 pub(crate) path: &'r str,
65 pub(crate) host: &'r str,
66 pub(crate) route: Option<&'r str>,
67 pub(crate) tls: bool,
68 pub(crate) json: bool,
69}
70
71impl<'r> Request<'r> {
72 #[must_use]
74 pub fn method(&self) -> Method {
75 self.http.method()
76 }
77
78 #[must_use]
81 pub fn path(&self) -> &'r str {
82 self.path
83 }
84
85 #[must_use]
88 pub fn query(&self) -> Option<&'r str> {
89 self.http.query()
90 }
91
92 #[must_use]
96 pub fn host(&self) -> &'r str {
97 self.host
98 }
99
100 #[must_use]
102 pub fn header(&self, name: &str) -> Option<&'r [u8]> {
103 self.http.header(name)
104 }
105
106 #[must_use]
108 pub fn header_str(&self, name: &str) -> Option<&'r str> {
109 self.http
110 .header(name)
111 .and_then(|v| core::str::from_utf8(v).ok())
112 }
113
114 pub fn cookie(&self, name: &str) -> Result<Option<&'r str>, Ambiguous> {
123 let mut fields = self.http.head().header_all("cookie");
124 let Some(first) = fields.next() else {
125 return Ok(None);
126 };
127 if fields.next().is_some() {
128 return Err(Ambiguous);
129 }
130 cookie_net::get_unique(first, name).map_err(|_| Ambiguous)
131 }
132
133 #[must_use]
136 pub fn client(&self) -> &'r ClientInfo {
137 self.env.client()
138 }
139
140 #[must_use]
143 pub fn scheme(&self) -> Scheme {
144 self.env.client().scheme()
145 }
146
147 #[must_use]
149 pub fn route(&self) -> Option<&'r str> {
150 self.route
151 }
152
153 #[must_use]
155 pub fn id(&self) -> RequestId {
156 RequestId::of(self.env)
157 }
158
159 #[must_use]
161 pub fn envelope(&self) -> &'r Envelope {
162 self.env
163 }
164
165 #[must_use]
167 pub fn raw(&self) -> &'r HttpRequest<'r> {
168 self.http
169 }
170}
171
172impl fmt::Debug for Request<'_> {
173 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 f.debug_struct("Request")
175 .field("method", &self.method())
176 .field("path", &self.path)
177 .field("route", &self.route)
178 .field("id", &self.id())
179 .finish_non_exhaustive()
180 }
181}