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}
69
70impl<'r> Request<'r> {
71 #[must_use]
73 pub fn method(&self) -> Method {
74 self.http.method()
75 }
76
77 #[must_use]
80 pub fn path(&self) -> &'r str {
81 self.path
82 }
83
84 #[must_use]
87 pub fn query(&self) -> Option<&'r str> {
88 self.http.query()
89 }
90
91 #[must_use]
95 pub fn host(&self) -> &'r str {
96 self.host
97 }
98
99 #[must_use]
101 pub fn header(&self, name: &str) -> Option<&'r [u8]> {
102 self.http.header(name)
103 }
104
105 #[must_use]
107 pub fn header_str(&self, name: &str) -> Option<&'r str> {
108 self.http
109 .header(name)
110 .and_then(|v| core::str::from_utf8(v).ok())
111 }
112
113 pub fn cookie(&self, name: &str) -> Result<Option<&'r str>, Ambiguous> {
122 let mut fields = self.http.head().header_all("cookie");
123 let Some(first) = fields.next() else {
124 return Ok(None);
125 };
126 if fields.next().is_some() {
127 return Err(Ambiguous);
128 }
129 cookie_net::get_unique(first, name).map_err(|_| Ambiguous)
130 }
131
132 #[must_use]
135 pub fn client(&self) -> &'r ClientInfo {
136 self.env.client()
137 }
138
139 #[must_use]
142 pub fn scheme(&self) -> Scheme {
143 self.env.client().scheme()
144 }
145
146 #[must_use]
148 pub fn route(&self) -> Option<&'r str> {
149 self.route
150 }
151
152 #[must_use]
154 pub fn id(&self) -> RequestId {
155 RequestId::of(self.env)
156 }
157
158 #[must_use]
160 pub fn envelope(&self) -> &'r Envelope {
161 self.env
162 }
163
164 #[must_use]
166 pub fn raw(&self) -> &'r HttpRequest<'r> {
167 self.http
168 }
169}
170
171impl fmt::Debug for Request<'_> {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 f.debug_struct("Request")
174 .field("method", &self.method())
175 .field("path", &self.path)
176 .field("route", &self.route)
177 .field("id", &self.id())
178 .finish_non_exhaustive()
179 }
180}