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