ttpkit_http/
response.rs

1//! Response types.
2
3use bytes::BytesMut;
4use tokio_util::codec::{Decoder, Encoder};
5
6use crate::{
7    CodecError, Protocol, Version,
8    header::{FieldIter, HeaderField, HeaderFieldValue, Iter},
9    ttpkit::response::{
10        ResponseHeader as GenericResponseHeader,
11        ResponseHeaderBuilder as GenericResponseHeaderBuilder,
12        ResponseHeaderDecoder as GenericResponseHeaderDecoder,
13        ResponseHeaderEncoder as GenericResponseHeaderEncoder, Status as GenericStatus,
14    },
15};
16
17pub use crate::ttpkit::response::{ResponseHeaderDecoderOptions, StatusMessage};
18
19/// HTTP response status.
20#[repr(transparent)]
21#[derive(Debug, Clone)]
22pub struct Status {
23    inner: GenericStatus,
24}
25
26impl Status {
27    pub const CONTINUE: Self = Self::from_static_str(100, "Continue");
28    pub const SWITCHING_PROTOCOLS: Self = Self::from_static_str(101, "Switching Protocols");
29    pub const OK: Self = Self::from_static_str(200, "OK");
30    pub const CREATED: Self = Self::from_static_str(201, "Created");
31    pub const NO_CONTENT: Self = Self::from_static_str(204, "No Content");
32    pub const MOVED_PERMANENTLY: Self = Self::from_static_str(301, "Moved Permanently");
33    pub const SEE_OTHER: Self = Self::from_static_str(303, "See Other");
34    pub const BAD_REQUEST: Self = Self::from_static_str(400, "Bad Request");
35    pub const UNAUTHORIZED: Self = Self::from_static_str(401, "Unauthorized");
36    pub const FORBIDDEN: Self = Self::from_static_str(403, "Forbidden");
37    pub const NOT_FOUND: Self = Self::from_static_str(404, "Not Found");
38    pub const METHOD_NOT_ALLOWED: Self = Self::from_static_str(405, "Method Not Allowed");
39    pub const EXPECTATION_FAILED: Self = Self::from_static_str(417, "Expectation Failed");
40    pub const INTERNAL_SERVER_ERROR: Self = Self::from_static_str(500, "Internal Server Error");
41    pub const NOT_IMPLEMENTED: Self = Self::from_static_str(501, "Not Implemented");
42    pub const BAD_GATEWAY: Self = Self::from_static_str(502, "Bad Gateway");
43    pub const SERVICE_UNAVAILABLE: Self = Self::from_static_str(503, "Service Unavailable");
44    pub const GATEWAY_TIMEOUT: Self = Self::from_static_str(504, "Gateway Timeout");
45
46    /// Create a new status with a given code and a message.
47    pub fn new<T>(code: u16, msg: T) -> Self
48    where
49        T: Into<StatusMessage>,
50    {
51        Self {
52            inner: GenericStatus::new(code, msg.into()),
53        }
54    }
55
56    /// Create a new status with a given code and a message.
57    #[inline]
58    pub const fn from_static_str(code: u16, msg: &'static str) -> Self {
59        Self {
60            inner: GenericStatus::from_static_str(code, msg),
61        }
62    }
63
64    /// Create a new status with a given code and a message.
65    #[inline]
66    pub const fn from_static_bytes(code: u16, msg: &'static [u8]) -> Self {
67        Self {
68            inner: GenericStatus::from_static_bytes(code, msg),
69        }
70    }
71
72    /// Create a status reference from a generic status reference.
73    #[inline]
74    const fn from_generic_ref(status: &GenericStatus) -> &Self {
75        let ptr = status as *const GenericStatus;
76
77        // SAFETY: `Self` is `repr(transparent)` over `GenericStatus`.
78        unsafe { &*(ptr as *const Self) }
79    }
80
81    /// Get the status code.
82    #[inline]
83    pub fn code(&self) -> u16 {
84        self.inner.code()
85    }
86
87    /// Get the status message.
88    #[inline]
89    pub fn message(&self) -> &StatusMessage {
90        self.inner.message()
91    }
92}
93
94/// HTTP response header.
95pub struct ResponseHeader {
96    inner: GenericResponseHeader<Protocol, Version>,
97}
98
99impl ResponseHeader {
100    /// Create a new header.
101    #[inline]
102    pub(crate) const fn new(inner: GenericResponseHeader<Protocol, Version>) -> Self {
103        Self { inner }
104    }
105
106    /// Get the response status.
107    #[inline]
108    pub fn status(&self) -> &Status {
109        Status::from_generic_ref(self.inner.status())
110    }
111
112    /// Get the status code.
113    #[inline]
114    pub fn status_code(&self) -> u16 {
115        self.inner.status_code()
116    }
117
118    /// Get the status message.
119    #[inline]
120    pub fn status_message(&self) -> &StatusMessage {
121        self.inner.status_message()
122    }
123
124    /// Get all header fields.
125    #[inline]
126    pub fn get_all_header_fields(&self) -> Iter<'_> {
127        self.inner.get_all_header_fields()
128    }
129
130    /// Get header fields corresponding to a given name.
131    pub fn get_header_fields<'a, N>(&'a self, name: &'a N) -> FieldIter<'a>
132    where
133        N: AsRef<[u8]> + ?Sized,
134    {
135        self.inner.get_header_fields(name)
136    }
137
138    /// Get the last header field of a given name.
139    pub fn get_header_field<'a, N>(&'a self, name: &'a N) -> Option<&'a HeaderField>
140    where
141        N: AsRef<[u8]> + ?Sized,
142    {
143        self.inner.get_header_field(name)
144    }
145
146    /// Get value of the last header field with a given name.
147    pub fn get_header_field_value<'a, N>(&'a self, name: &'a N) -> Option<&'a HeaderFieldValue>
148    where
149        N: AsRef<[u8]> + ?Sized,
150    {
151        self.inner.get_header_field_value(name)
152    }
153}
154
155/// HTTP response builder.
156pub struct ResponseBuilder {
157    header: GenericResponseHeaderBuilder<Protocol, Version>,
158}
159
160impl ResponseBuilder {
161    /// Create a new response builder.
162    #[inline]
163    const fn new() -> Self {
164        Self {
165            header: GenericResponseHeader::builder(
166                Protocol,
167                Version::Version11,
168                GenericStatus::from_static_str(200, "OK"),
169            ),
170        }
171    }
172
173    /// Set the HTTP version.
174    #[inline]
175    pub fn set_version(mut self, version: Version) -> Self {
176        self.header = self.header.set_version(version);
177        self
178    }
179
180    /// Set the response status.
181    #[inline]
182    pub fn set_status(mut self, status: Status) -> Self {
183        self.header = self.header.set_status(status.inner);
184        self
185    }
186
187    /// Replace the current header fields having the same name (if any).
188    pub fn set_header_field<T>(mut self, field: T) -> Self
189    where
190        T: Into<HeaderField>,
191    {
192        self.header = self.header.set_header_field(field);
193        self
194    }
195
196    /// Add a given header field.
197    pub fn add_header_field<T>(mut self, field: T) -> Self
198    where
199        T: Into<HeaderField>,
200    {
201        self.header = self.header.add_header_field(field);
202        self
203    }
204
205    /// Remove all header fields with a given name.
206    pub fn remove_header_fields<N>(mut self, name: &N) -> Self
207    where
208        N: AsRef<[u8]> + ?Sized,
209    {
210        self.header = self.header.remove_header_fields(name);
211        self
212    }
213
214    /// Build just the response header.
215    #[inline]
216    pub fn header(self) -> ResponseHeader {
217        ResponseHeader::new(self.header.build())
218    }
219
220    /// Build the response.
221    pub fn body<B>(self, body: B) -> Response<B> {
222        Response::new(self.header(), body)
223    }
224}
225
226impl From<ResponseHeader> for ResponseBuilder {
227    #[inline]
228    fn from(header: ResponseHeader) -> ResponseBuilder {
229        Self {
230            header: header.inner.into(),
231        }
232    }
233}
234
235/// HTTP response.
236pub struct Response<B> {
237    header: ResponseHeader,
238    body: B,
239}
240
241impl Response<()> {
242    /// Get a response builder.
243    #[inline]
244    pub const fn builder() -> ResponseBuilder {
245        ResponseBuilder::new()
246    }
247}
248
249impl<B> Response<B> {
250    /// Create a new response.
251    #[inline]
252    pub(crate) const fn new(header: ResponseHeader, body: B) -> Self {
253        Self { header, body }
254    }
255
256    /// Get the response header.
257    #[inline]
258    pub fn header(&self) -> &ResponseHeader {
259        &self.header
260    }
261
262    /// Get the response status.
263    #[inline]
264    pub fn status(&self) -> &Status {
265        self.header.status()
266    }
267
268    /// Get the status code.
269    #[inline]
270    pub fn status_code(&self) -> u16 {
271        self.header.status_code()
272    }
273
274    /// Get the status message.
275    #[inline]
276    pub fn status_message(&self) -> &StatusMessage {
277        self.header.status_message()
278    }
279
280    /// Get all header fields.
281    #[inline]
282    pub fn get_all_header_fields(&self) -> Iter<'_> {
283        self.header.get_all_header_fields()
284    }
285
286    /// Get header fields corresponding to a given name.
287    pub fn get_header_fields<'a, N>(&'a self, name: &'a N) -> FieldIter<'a>
288    where
289        N: AsRef<[u8]> + ?Sized,
290    {
291        self.header.get_header_fields(name)
292    }
293
294    /// Get the last header field of a given name.
295    pub fn get_header_field<'a, N>(&'a self, name: &'a N) -> Option<&'a HeaderField>
296    where
297        N: AsRef<[u8]> + ?Sized,
298    {
299        self.header.get_header_field(name)
300    }
301
302    /// Get value of the last header field with a given name.
303    pub fn get_header_field_value<'a, N>(&'a self, name: &'a N) -> Option<&'a HeaderFieldValue>
304    where
305        N: AsRef<[u8]> + ?Sized,
306    {
307        self.header.get_header_field_value(name)
308    }
309
310    /// Take the response body.
311    #[inline]
312    pub fn body(self) -> B {
313        self.body
314    }
315
316    /// Deconstruct the response back into a response builder and the body.
317    #[inline]
318    pub fn deconstruct(self) -> (ResponseHeader, B) {
319        (self.header, self.body)
320    }
321}
322
323/// Response header decoder.
324pub struct ResponseHeaderDecoder {
325    inner: GenericResponseHeaderDecoder<Protocol, Version>,
326}
327
328impl ResponseHeaderDecoder {
329    /// Create a new decoder.
330    #[inline]
331    pub fn new(options: ResponseHeaderDecoderOptions) -> Self {
332        Self {
333            inner: GenericResponseHeaderDecoder::new(options),
334        }
335    }
336
337    /// Reset the decoder and make it ready for parsing a new response header.
338    #[inline]
339    pub fn reset(&mut self) {
340        self.inner.reset();
341    }
342
343    /// Decode a given response header chunk.
344    pub fn decode(&mut self, data: &mut BytesMut) -> Result<Option<ResponseHeader>, CodecError> {
345        let res = self.inner.decode(data)?.map(ResponseHeader::new);
346
347        Ok(res)
348    }
349
350    /// Decode a given response header chunk at the end of the stream.
351    pub fn decode_eof(
352        &mut self,
353        data: &mut BytesMut,
354    ) -> Result<Option<ResponseHeader>, CodecError> {
355        let res = self.inner.decode_eof(data)?.map(ResponseHeader::new);
356
357        Ok(res)
358    }
359}
360
361impl Decoder for ResponseHeaderDecoder {
362    type Item = ResponseHeader;
363    type Error = CodecError;
364
365    #[inline]
366    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
367        Self::decode(self, buf)
368    }
369
370    #[inline]
371    fn decode_eof(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
372        Self::decode_eof(self, buf)
373    }
374}
375
376/// Response header encoder.
377pub struct ResponseHeaderEncoder {
378    inner: GenericResponseHeaderEncoder,
379}
380
381impl ResponseHeaderEncoder {
382    /// Create a new encoder.
383    #[inline]
384    pub const fn new() -> Self {
385        Self {
386            inner: GenericResponseHeaderEncoder::new(),
387        }
388    }
389
390    /// Encode a given response header into a given buffer.
391    #[inline]
392    pub fn encode(&mut self, header: &ResponseHeader, dst: &mut BytesMut) {
393        self.inner.encode(&header.inner, dst);
394    }
395}
396
397impl Default for ResponseHeaderEncoder {
398    #[inline]
399    fn default() -> Self {
400        Self::new()
401    }
402}
403
404impl Encoder<&ResponseHeader> for ResponseHeaderEncoder {
405    type Error = CodecError;
406
407    #[inline]
408    fn encode(&mut self, header: &ResponseHeader, dst: &mut BytesMut) -> Result<(), Self::Error> {
409        Self::encode(self, header, dst);
410
411        Ok(())
412    }
413}