axol_http/
response.rs

1use std::{any::Any, convert::Infallible};
2
3use thiserror::Error;
4
5use crate::{header::HeaderMap, status::StatusCodeError, Body, Extensions, StatusCode, Version};
6
7/// Represents an HTTP response
8///
9/// An HTTP response consists of a head and a potentially optional body. The body
10/// component is generic, enabling arbitrary types to represent the HTTP body.
11/// For example, the body could be `Vec<u8>`, a `Stream` of byte chunks, or a
12/// value that has been deserialized.
13///
14/// Typically you'll work with responses on the client side as the result of
15/// sending a `Request` and on the server you'll be generating a `Response` to
16/// send back to the client.
17///
18/// # Examples
19///
20/// Creating a `Response` to return
21///
22/// ```
23/// use axol_http::{Request, Response, StatusCode};
24///
25/// fn respond_to(req: Request<()>) -> axol_http::Result<Response<()>> {
26///     let mut builder = Response::builder()
27///         .header("Foo", "Bar")
28///         .status(StatusCode::OK);
29///
30///     if req.headers().contains_key("Another-Header") {
31///         builder = builder.header("Another-Header", "Ack");
32///     }
33///
34///     builder.body(())
35/// }
36/// ```
37///
38/// A simple 404 handler
39///
40/// ```
41/// use axol_http::{Request, Response, StatusCode};
42///
43/// fn not_found(_req: Request<()>) -> axol_http::Result<Response<()>> {
44///     Response::builder()
45///         .status(StatusCode::NOT_FOUND)
46///         .body(())
47/// }
48/// ```
49///
50/// Or otherwise inspecting the result of a request:
51///
52/// ```no_run
53/// use axol_http::{Request, Response};
54///
55/// fn get(url: &str) -> axol_http::Result<Response<()>> {
56///     // ...
57/// # panic!()
58/// }
59///
60/// let response = get("https://www.rust-lang.org/").unwrap();
61///
62/// if !response.status().is_success() {
63///     panic!("failed to get a successful response status!");
64/// }
65///
66/// if let Some(date) = response.headers().get("Date") {
67///     // we've got a `Date` header!
68/// }
69///
70/// let body = response.body();
71/// // ...
72/// ```
73///
74/// Deserialize a response of bytes via json:
75///
76/// ```
77/// # extern crate serde;
78/// # extern crate serde_json;
79/// # extern crate http;
80/// use axol_http::Response;
81/// use serde::de;
82///
83/// fn deserialize<T>(res: Response<Vec<u8>>) -> serde_json::Result<Response<T>>
84///     where for<'de> T: de::Deserialize<'de>,
85/// {
86///     let (parts, body) = res.into_parts();
87///     let body = serde_json::from_slice(&body)?;
88///     Ok(Response::from_parts(parts, body))
89/// }
90/// #
91/// # fn main() {}
92/// ```
93///
94/// Or alternatively, serialize the body of a response to json
95///
96/// ```
97/// # extern crate serde;
98/// # extern crate serde_json;
99/// # extern crate http;
100/// use axol_http::Response;
101/// use serde::ser;
102///
103/// fn serialize<T>(res: Response<T>) -> serde_json::Result<Response<Vec<u8>>>
104///     where T: ser::Serialize,
105/// {
106///     let (parts, body) = res.into_parts();
107///     let body = serde_json::to_vec(&body)?;
108///     Ok(Response::from_parts(parts, body))
109/// }
110/// #
111/// # fn main() {}
112/// ```
113#[derive(Debug, Default)]
114pub struct Response {
115    /// The response's status
116    pub status: StatusCode,
117
118    /// The response's version
119    pub version: Version,
120
121    /// The response's headers
122    pub headers: HeaderMap,
123
124    /// The response's extensions
125    pub extensions: Extensions,
126
127    /// The response's body
128    pub body: Body,
129}
130
131/// Component parts of an HTTP `Response`
132///
133/// The HTTP response head consists of a status, version, and a set of
134/// header fields.
135#[derive(Debug, Default)]
136pub struct ResponseParts {
137    /// The response's status
138    pub status: StatusCode,
139
140    /// The response's version
141    pub version: Version,
142
143    /// The response's headers
144    pub headers: HeaderMap,
145
146    /// The response's extensions
147    pub extensions: Extensions,
148}
149
150impl ResponseParts {
151    pub fn as_ref(&mut self) -> ResponsePartsRef<'_> {
152        ResponsePartsRef {
153            status: &mut self.status,
154            version: &mut self.version,
155            headers: &mut self.headers,
156            extensions: &mut self.extensions,
157        }
158    }
159}
160
161impl Response {
162    pub fn parts_mut(&mut self) -> ResponsePartsRef<'_> {
163        ResponsePartsRef {
164            status: &mut self.status,
165            version: &mut self.version,
166            headers: &mut self.headers,
167            extensions: &mut self.extensions,
168        }
169    }
170}
171
172#[derive(Debug)]
173pub struct ResponsePartsRef<'a> {
174    /// The response's status
175    pub status: &'a mut StatusCode,
176
177    /// The response's version
178    pub version: &'a mut Version,
179
180    /// The response's headers
181    pub headers: &'a mut HeaderMap,
182
183    /// The response's extensions
184    pub extensions: &'a mut Extensions,
185}
186
187impl ResponseParts {
188    /// Creates a new default instance of `ResponseParts`
189    pub fn new() -> ResponseParts {
190        Default::default()
191    }
192}
193
194#[derive(Error, Debug)]
195pub enum ResponseBuilderError {
196    #[error("")]
197    Infallible(#[from] Infallible),
198    #[error("status code error: {0}")]
199    StatusCode(#[from] StatusCodeError),
200    // #[error("http error: {0}")]
201    // Http(#[from] HttpError),
202}
203
204/// An HTTP response builder
205///
206/// This type can be used to construct an instance of `Response` through a
207/// builder-like pattern.
208#[derive(Debug)]
209pub struct Builder {
210    inner: Result<Response, ResponseBuilderError>,
211}
212
213impl Response {
214    /// Creates a new builder-style object to manufacture a `Response`
215    ///
216    /// This method returns an instance of `Builder` which can be used to
217    /// create a `Response`.
218    ///
219    /// # Examples
220    ///
221    /// ```
222    /// # use axol_http::*;
223    /// let response = Response::builder()
224    ///     .status(200)
225    ///     .header("X-Custom-Foo", "Bar")
226    ///     .body(())
227    ///     .unwrap();
228    /// ```
229    pub fn builder() -> Builder {
230        Builder::new()
231    }
232
233    /// Creates a new blank `Response` with the body
234    ///
235    /// The component ports of this response will be set to their default, e.g.
236    /// the ok status, no headers, etc.
237    ///
238    /// # Examples
239    ///
240    /// ```
241    /// # use axol_http::*;
242    /// let response = Response::new("hello world");
243    ///
244    /// assert_eq!(response.status(), StatusCode::OK);
245    /// assert_eq!(*response.body(), "hello world");
246    /// ```
247    pub fn new(body: impl Into<Body>) -> Response {
248        Self::from_parts(Default::default(), body)
249    }
250
251    /// Creates a new `Response` with the given head and body
252    ///
253    /// # Examples
254    ///
255    /// ```
256    /// # use axol_http::*;
257    /// let response = Response::new("hello world");
258    /// let (mut parts, body) = response.into_parts();
259    ///
260    /// parts.status = StatusCode::BAD_REQUEST;
261    /// let response = Response::from_parts(parts, body);
262    ///
263    /// assert_eq!(response.status(), StatusCode::BAD_REQUEST);
264    /// assert_eq!(*response.body(), "hello world");
265    /// ```
266    pub fn from_parts(parts: ResponseParts, body: impl Into<Body>) -> Response {
267        Response {
268            status: parts.status,
269            version: parts.version,
270            headers: parts.headers,
271            extensions: parts.extensions,
272            body: body.into(),
273        }
274    }
275
276    /// Consumes the response returning the head and body parts.
277    ///
278    /// # Examples
279    ///
280    /// ```
281    /// # use axol_http::*;
282    /// let response: Response<()> = Response::default();
283    /// let (parts, body) = response.into_parts();
284    /// assert_eq!(parts.status, StatusCode::OK);
285    /// ```
286    pub fn into_parts(self) -> (ResponseParts, Body) {
287        (
288            ResponseParts {
289                status: self.status,
290                version: self.version,
291                headers: self.headers,
292                extensions: self.extensions,
293            },
294            self.body,
295        )
296    }
297
298    /// Sets status code of response
299    pub fn with_status(mut self, status: StatusCode) -> Self {
300        self.status = status;
301        self
302    }
303}
304
305impl Builder {
306    /// Creates a new default instance of `Builder` to construct either a
307    /// `Head` or a `Response`.
308    ///
309    /// # Examples
310    ///
311    /// ```
312    /// # use axol_http::*;
313    ///
314    /// let response = response::Builder::new()
315    ///     .status(200)
316    ///     .body(())
317    ///     .unwrap();
318    /// ```
319    pub fn new() -> Builder {
320        Builder::default()
321    }
322
323    /// Set the HTTP status for this response.
324    ///
325    /// This function will configure the HTTP status code of the `Response` that
326    /// will be returned from `Builder::build`.
327    ///
328    /// By default this is `200`.
329    ///
330    /// # Examples
331    ///
332    /// ```
333    /// # use axol_http::*;
334    ///
335    /// let response = Response::builder()
336    ///     .status(200)
337    ///     .body(())
338    ///     .unwrap();
339    /// ```
340    pub fn status<T>(self, status: T) -> Builder
341    where
342        StatusCode: TryFrom<T>,
343        <StatusCode as TryFrom<T>>::Error: Into<StatusCodeError>,
344    {
345        self.and_then(move |mut head| {
346            head.status = TryFrom::try_from(status).map_err(Into::into)?;
347            Ok(head)
348        })
349    }
350
351    /// Set the HTTP version for this response.
352    ///
353    /// This function will configure the HTTP version of the `Response` that
354    /// will be returned from `Builder::build`.
355    ///
356    /// By default this is HTTP/1.1
357    ///
358    /// # Examples
359    ///
360    /// ```
361    /// # use axol_http::*;
362    ///
363    /// let response = Response::builder()
364    ///     .version(Version::HTTP_2)
365    ///     .body(())
366    ///     .unwrap();
367    /// ```
368    pub fn version(self, version: Version) -> Builder {
369        self.and_then(move |mut head| {
370            head.version = version;
371            Ok(head)
372        })
373    }
374
375    /// Appends a header to this response builder.
376    ///
377    /// This function will append the provided key/value as a header to the
378    /// internal `HeaderMap` being constructed. Essentially this is equivalent
379    /// to calling `HeaderMap::append`.
380    ///
381    /// # Examples
382    ///
383    /// ```
384    /// # use axol_http::*;
385    /// # use axol_http::header::HeaderValue;
386    ///
387    /// let response = Response::builder()
388    ///     .header("Content-Type", "text/html")
389    ///     .header("X-Custom-Foo", "bar")
390    ///     .header("content-length", 0)
391    ///     .body(())
392    ///     .unwrap();
393    /// ```
394    pub fn header(self, name: impl AsRef<str>, value: impl Into<String>) -> Builder {
395        self.and_then(move |mut head| {
396            head.headers.insert(name, value);
397            Ok(head)
398        })
399    }
400
401    /// Get header on this response builder.
402    ///
403    /// When builder has error returns None.
404    ///
405    /// # Example
406    ///
407    /// ```
408    /// # use axol_http::Response;
409    /// # use axol_http::header::HeaderValue;
410    /// let res = Response::builder()
411    ///     .header("Accept", "text/html")
412    ///     .header("X-Custom-Foo", "bar");
413    /// let headers = res.headers_ref().unwrap();
414    /// assert_eq!( headers["Accept"], "text/html" );
415    /// assert_eq!( headers["X-Custom-Foo"], "bar" );
416    /// ```
417    pub fn headers_ref(&self) -> Option<&HeaderMap> {
418        self.inner.as_ref().ok().map(|h| &h.headers)
419    }
420
421    /// Get header on this response builder.
422    /// when builder has error returns None
423    ///
424    /// # Example
425    ///
426    /// ```
427    /// # use axol_http::*;
428    /// # use axol_http::header::HeaderValue;
429    /// # use axol_http::response::Builder;
430    /// let mut res = Response::builder();
431    /// {
432    ///   let headers = res.headers_mut().unwrap();
433    ///   headers.insert("Accept", HeaderValue::from_static("text/html"));
434    ///   headers.insert("X-Custom-Foo", HeaderValue::from_static("bar"));
435    /// }
436    /// let headers = res.headers_ref().unwrap();
437    /// assert_eq!( headers["Accept"], "text/html" );
438    /// assert_eq!( headers["X-Custom-Foo"], "bar" );
439    /// ```
440    pub fn headers_mut(&mut self) -> Option<&mut HeaderMap> {
441        self.inner.as_mut().ok().map(|h| &mut h.headers)
442    }
443
444    /// Adds an extension to this builder
445    ///
446    /// # Examples
447    ///
448    /// ```
449    /// # use axol_http::*;
450    ///
451    /// let response = Response::builder()
452    ///     .extension("My Extension")
453    ///     .body(())
454    ///     .unwrap();
455    ///
456    /// assert_eq!(response.extensions().get::<&'static str>(),
457    ///            Some(&"My Extension"));
458    /// ```
459    pub fn extension<T>(self, extension: T) -> Builder
460    where
461        T: Any + Send + Sync + 'static,
462    {
463        self.and_then(move |head| {
464            head.extensions.insert(extension);
465            Ok(head)
466        })
467    }
468
469    /// Get a reference to the extensions for this response builder.
470    ///
471    /// If the builder has an error, this returns `None`.
472    ///
473    /// # Example
474    ///
475    /// ```
476    /// # use axol_http::Response;
477    /// let res = Response::builder().extension("My Extension").extension(5u32);
478    /// let extensions = res.extensions_ref().unwrap();
479    /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension"));
480    /// assert_eq!(extensions.get::<u32>(), Some(&5u32));
481    /// ```
482    pub fn extensions_ref(&self) -> Option<&Extensions> {
483        self.inner.as_ref().ok().map(|h| &h.extensions)
484    }
485
486    /// Get a mutable reference to the extensions for this response builder.
487    ///
488    /// If the builder has an error, this returns `None`.
489    ///
490    /// # Example
491    ///
492    /// ```
493    /// # use axol_http::Response;
494    /// let mut res = Response::builder().extension("My Extension");
495    /// let mut extensions = res.extensions_mut().unwrap();
496    /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension"));
497    /// extensions.insert(5u32);
498    /// assert_eq!(extensions.get::<u32>(), Some(&5u32));
499    /// ```
500    pub fn extensions_mut(&mut self) -> Option<&mut Extensions> {
501        self.inner.as_mut().ok().map(|h| &mut h.extensions)
502    }
503
504    /// "Consumes" this builder, using the provided `body` to return a
505    /// constructed `Response`.
506    ///
507    /// # Errors
508    ///
509    /// This function may return an error if any previously configured argument
510    /// failed to parse or get converted to the internal representation. For
511    /// example if an invalid `head` was specified via `header("Foo",
512    /// "Bar\r\n")` the error will be returned when this function is called
513    /// rather than when `header` was called.
514    ///
515    /// # Examples
516    ///
517    /// ```
518    /// # use axol_http::*;
519    ///
520    /// let response = Response::builder()
521    ///     .body(())
522    ///     .unwrap();
523    /// ```
524    pub fn body(self, body: impl Into<Body>) -> Result<Response, ResponseBuilderError> {
525        self.inner.map(move |mut head| {
526            head.body = body.into();
527            head
528        })
529    }
530
531    // private
532
533    fn and_then<F>(self, func: F) -> Self
534    where
535        F: FnOnce(Response) -> Result<Response, ResponseBuilderError>,
536    {
537        Builder {
538            inner: self.inner.and_then(func),
539        }
540    }
541}
542
543impl Default for Builder {
544    fn default() -> Builder {
545        Builder {
546            inner: Ok(Default::default()),
547        }
548    }
549}