under/
response.rs

1use std::convert::TryFrom;
2
3#[derive(Debug)]
4#[must_use]
5/// An HTTP response.
6///
7/// An HTTP Response consists of a head (a status code and some headers), and
8/// a body (which may be empty).  This type offers convenient helpers for
9/// constructing HTTP responses for you for common use-cases.
10///
11/// # Examples
12///
13/// ```rust
14/// use under::{Request, Response, HttpEntity};
15///
16/// // Here, we're defining an endpoint for our server.
17/// async fn handle_get(request: Request) -> Result<Response, anyhow::Error> {
18///     let target = request.fragment_str("target").unwrap_or("world");
19///     Ok(Response::text(format!("hello, {}", target)))
20/// }
21///
22/// # #[tokio::main]
23/// # async fn main() -> Result<(), anyhow::Error> {
24/// let mut http = under::http();
25/// http
26///     .at("/hello").get(handle_get)
27///     .at("/hello/{target}").get(handle_get);
28/// http.prepare();
29/// let mut response = http.handle(Request::get("/hello")?).await?;
30/// assert_eq!(response.status(), http::StatusCode::OK);
31/// let body = response.data(512).into_text().await?;
32/// assert_eq!(body, "hello, world");
33/// # Ok(())
34/// # }
35/// ```
36pub struct Response(http::Response<hyper::Body>);
37
38macro_rules! forward {
39    () => {};
40    (
41        $(#[$m:meta])* $v:vis fn $name:ident(&self $(, $pn:ident: $pt:ty)*) -> $ret:ty;
42        $($tail:tt)*
43    ) => {
44        $(#[$m])* $v fn $name(&self $(, $pn: $pt)*) -> $ret {
45            (self.0).$name($($pn),*)
46        }
47
48        forward! { $($tail)* }
49    };
50
51    (
52        $(#[$m:meta])* $v:vis fn $name:ident(&mut self $(, $pn:ident: $pt:ty)*) -> $ret:ty;
53        $($tail:tt)*
54    ) => {
55        $(#[$m])* $v fn $name(&mut self $(, $pn: $pt)*) -> $ret {
56            (self.0).$name($($pn),*)
57        }
58
59        forward! { $($tail)* }
60    }
61}
62
63impl Response {
64    /// Creates an empty response with a status code of 200.
65    ///
66    /// See [`Response::empty_status`] for more information.
67    ///
68    /// # Example
69    /// ```rust
70    /// # use under::*;
71    /// let response = Response::empty_200();
72    /// assert_eq!(response.status(), http::StatusCode::OK);
73    /// ```
74    pub fn empty_200() -> Self {
75        Self::empty_status(http::StatusCode::OK)
76    }
77
78    /// Creates an empty response with a status code of 204.
79    ///
80    /// See [`Response::empty_status`] for more information.
81    ///
82    /// # Examples
83    /// ```rust
84    /// # use under::*;
85    /// let response = Response::empty_204();
86    /// assert_eq!(response.status(), http::StatusCode::NO_CONTENT);
87    /// ```
88    pub fn empty_204() -> Self {
89        Response::empty_status(http::StatusCode::NO_CONTENT)
90    }
91
92    /// Creates an empty response with a status code of 404.
93    ///
94    /// See [`Response::empty_status`] for more information.
95    ///
96    /// # Examples
97    /// ```rust
98    /// # use under::*;
99    /// let response = Response::empty_404();
100    /// assert_eq!(response.status(), http::StatusCode::NOT_FOUND);
101    /// ```
102    pub fn empty_404() -> Self {
103        Response::empty_status(http::StatusCode::NOT_FOUND)
104    }
105
106    /// Creates an empty response with a status code of 500.
107    ///
108    /// See [`Response::empty_status`] for more information.
109    ///
110    /// # Examples
111    /// ```rust
112    /// # use under::*;
113    /// let response = Response::empty_500();
114    /// assert_eq!(response.status(), http::StatusCode::INTERNAL_SERVER_ERROR);
115    /// ```
116    pub fn empty_500() -> Self {
117        Response::empty_status(http::StatusCode::INTERNAL_SERVER_ERROR)
118    }
119
120    /// Creates a redirect (using See Other) to the given location.
121    ///
122    /// # Errors
123    /// This attempts to convert the location into a [`http::HeaderValue`];
124    /// however, the conversion may fail (for reasons specified on
125    /// [`http::HeaderValue::from_str`]).  It may also fail to construct the
126    /// underlying response.
127    ///
128    /// # Examples
129    /// ```rust
130    /// # use under::*;
131    /// let response = Response::see_other("/foo").unwrap();
132    /// assert_eq!(response.status(), http::StatusCode::SEE_OTHER);
133    /// ```
134    pub fn see_other<T>(location: T) -> Result<Self, http::Error>
135    where
136        http::HeaderValue: TryFrom<T>,
137        <http::HeaderValue as TryFrom<T>>::Error: Into<http::Error>,
138    {
139        Ok(Response(
140            http::Response::builder()
141                .status(http::StatusCode::SEE_OTHER)
142                .header(http::header::LOCATION, location)
143                .body(hyper::Body::empty())?,
144        ))
145    }
146
147    /// Creates a permanent redirect to the given location.
148    ///
149    /// # Errors
150    /// This attempts to convert the location into a
151    /// [`http::HeaderValue`]; however, the conversion may fail (for
152    /// reasons specified on [`http::HeaderValue::from_str`]).  It may also
153    /// fail to construct the underlying response.
154    ///
155    /// # Examples
156    /// ```rust
157    /// # use under::*;
158    /// let response = Response::permanent_redirect("/foo").unwrap();
159    /// assert_eq!(response.status(), http::StatusCode::PERMANENT_REDIRECT);
160    /// ```
161    pub fn permanent_redirect<T>(location: T) -> Result<Self, http::Error>
162    where
163        http::HeaderValue: TryFrom<T>,
164        <http::HeaderValue as TryFrom<T>>::Error: Into<http::Error>,
165    {
166        Ok(Response(
167            http::Response::builder()
168                .status(http::StatusCode::PERMANENT_REDIRECT)
169                .header(http::header::LOCATION, location)
170                .body(hyper::Body::empty())?,
171        ))
172    }
173
174    /// Creates a temporary redirect to the given location.
175    ///
176    /// # Errors
177    /// This attempts to convert the location into a
178    /// [`http::HeaderValue`]; however, the conversion may fail (for
179    /// reasons specified on [`http::HeaderValue::from_str`]).  It may also
180    /// fail to construct the underlying response.
181    ///
182    /// # Examples
183    /// ```rust
184    /// # use under::*;
185    /// let response = Response::temporary_redirect("/foo").unwrap();
186    /// assert_eq!(response.status(), http::StatusCode::TEMPORARY_REDIRECT);
187    /// ```
188    pub fn temporary_redirect<T>(location: T) -> Result<Self, http::Error>
189    where
190        http::HeaderValue: TryFrom<T>,
191        <http::HeaderValue as TryFrom<T>>::Error: Into<http::Error>,
192    {
193        Ok(Response(
194            http::Response::builder()
195                .status(http::StatusCode::TEMPORARY_REDIRECT)
196                .header(http::header::LOCATION, location)
197                .body(hyper::Body::empty())?,
198        ))
199    }
200
201    /// Creates a response with an empty body and a set status.  The
202    /// Content-Type is not set.
203    ///
204    /// # Examples
205    /// ```rust
206    /// # use under::*;
207    /// let response = Response::empty_status(http::StatusCode::NOT_FOUND);
208    /// assert_eq!(response.status(), http::StatusCode::NOT_FOUND);
209    /// ```
210    #[allow(clippy::missing_panics_doc)]
211    pub fn empty_status(status: http::StatusCode) -> Self {
212        // This shouldn't panic, as the headers are garenteed to be valid.
213        Response(
214            http::Response::builder()
215                .status(status)
216                .body(hyper::Body::empty())
217                .unwrap(),
218        )
219    }
220
221    /// Creates a response with the given text body.  The returned response
222    /// has a `Content-Type` of `text/plain; charset=utf-8`.
223    ///
224    /// # Examples
225    /// ```rust
226    /// # use under::*;
227    /// let response = Response::text("hello, world");
228    /// ```
229    #[allow(clippy::missing_panics_doc)]
230    pub fn text<V: Into<String>>(body: V) -> Self {
231        // This shouldn't panic, as the headers are garenteed to be valid.
232        Response(
233            http::Response::builder()
234                .header(http::header::CONTENT_TYPE, "text/plain; charset=utf-8")
235                .body(body.into().into())
236                .unwrap(),
237        )
238    }
239
240    /// Creates a response with the given JSON body.  The returned response
241    /// has a `Content-Type` of `application/json; charset=utf-8`.
242    ///
243    /// # Errors
244    /// This errors if the underlying JSON serialization fails; and it will
245    /// return that exact error.
246    ///
247    /// # Examples
248    /// ```rust
249    /// # use under::*;
250    /// let response = Response::json(&serde_json::json!({ "hello": "world" }))?;
251    /// # Ok::<(), anyhow::Error>(())
252    /// ```
253    #[cfg(feature = "json")]
254    #[allow(clippy::missing_panics_doc)]
255    pub fn json<V: serde::Serialize>(body: &V) -> Result<Self, serde_json::Error> {
256        let value = serde_json::to_string(body)?;
257        // This shouldn't panic, as the value is a valid JSON string, and the
258        // headers are garenteed to be valid.
259        Ok(Response(
260            http::Response::builder()
261                .header(
262                    http::header::CONTENT_TYPE,
263                    "application/json; charset=utf-8",
264                )
265                .body(value.into())
266                .unwrap(),
267        ))
268    }
269
270    /// Sets the current responses's status code.
271    ///
272    /// # Examples
273    /// ```rust
274    /// # use under::*;
275    /// let mut response = Response::empty_404();
276    /// response.set_status(http::StatusCode::OK);
277    /// assert_eq!(response.status(), http::StatusCode::OK);
278    /// ```
279    pub fn set_status<S: Into<http::StatusCode>>(&mut self, status: S) {
280        *self.0.status_mut() = status.into();
281    }
282
283    /// Returns a response with the new status code.
284    ///
285    /// # Examples
286    /// ```rust
287    /// # use under::*;
288    /// let response = Response::empty_404();
289    /// let response = response.with_status(http::StatusCode::OK);
290    /// assert_eq!(response.status(), http::StatusCode::OK);
291    /// ```
292    pub fn with_status<S: Into<http::StatusCode>>(mut self, status: S) -> Self {
293        *self.0.status_mut() = status.into();
294        Response(self.0)
295    }
296
297    /// Returns state information provided by the
298    /// [`crate::middleware::StateMiddleware`] middleware.  This is a
299    /// shortcut to retrieving the [`crate::middleware::State`]
300    /// extension from the response.
301    ///
302    /// # Examples
303    /// ```rust
304    /// # use under::*;
305    /// use under::middleware::State;
306    /// let mut response = Response::empty_200();
307    /// response.extensions_mut().insert(State(123u32));
308    /// assert_eq!(response.state::<u32>(), Some(&123u32));
309    /// ```
310    pub fn state<T: Send + Sync + 'static>(&self) -> Option<&T> {
311        self.ext::<crate::middleware::State<T>>().map(|v| &v.0)
312    }
313
314    /// Retrieves a specific extension from the extensions map.  This is
315    /// the same as calling [`Self::extensions`].`get` wit the given
316    /// type parameter.
317    ///
318    /// # Examples
319    /// ```rust
320    /// # use under::*;
321    /// let mut response = Response::empty_200();
322    /// assert_eq!(response.ext::<u32>(), None);
323    /// ```
324    pub fn ext<T: Send + Sync + 'static>(&self) -> Option<&T> {
325        self.extensions().get::<T>()
326    }
327
328    /// Retrieves a mutable reference to the specific extension from the
329    /// extensions map.  This is the same as calling
330    /// [`Self::extensions_mut`].`get_mut` with the given type
331    /// parameter.
332    ///
333    /// # Examples
334    /// ```rust
335    /// # use under::*;
336    /// let mut response = Response::empty_200();
337    /// assert_eq!(response.ext_mut::<u32>(), None);
338    /// ```
339    pub fn ext_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
340        self.extensions_mut().get_mut::<T>()
341    }
342
343    /// Sets the value of the specific extension in the extensions map.
344    /// This is the same as calling [`Self::extensions_mut`].`insert`
345    /// with the given parameter.
346    ///
347    /// # Examples
348    /// ```rust
349    /// # use under::*;
350    /// let mut response = Response::empty_200();
351    /// response.set_ext(123u32);
352    /// assert_eq!(response.ext::<u32>(), Some(&123u32));
353    /// ```
354    pub fn set_ext<T: Send + Sync + 'static>(&mut self, value: T) -> &mut Self {
355        self.extensions_mut().insert(value);
356        self
357    }
358
359    /// Sets the value of the specific extension in the extensions map,
360    /// consuming `self`, and then returning the new value.  This is
361    /// the same as calling [`Self::set_ext`], but it consumes `self`.
362    ///
363    /// # Examples
364    /// ```rust
365    /// # use under::*;
366    /// let response = Response::empty_200();
367    /// let response = response.with_ext(123u32);
368    /// assert_eq!(response.ext::<u32>(), Some(&123u32));
369    /// ```
370    pub fn with_ext<T: Send + Sync + 'static>(mut self, value: T) -> Self {
371        self.set_ext(value);
372        self
373    }
374
375    /// Removes the specific extension from the extensions map.  This is
376    /// the same as calling [`Self::extensions_mut`].`remove` with the
377    /// given type parameter.
378    ///
379    /// # Examples
380    /// ```rust
381    /// # use under::*;
382    /// let mut response = Response::empty_200()
383    ///     .with_ext(123u32);
384    /// assert_eq!(response.ext::<u32>(), Some(&123u32));
385    /// response.remove_ext::<u32>();
386    /// assert_eq!(response.ext::<u32>(), None);
387    /// ```
388    pub fn remove_ext<T: Send + Sync + 'static>(&mut self) -> Option<T> {
389        self.extensions_mut().remove::<T>()
390    }
391
392    /// Removes the specific extension from the extensions map,
393    /// consuming `self`, and then returning the removed value.  This
394    /// is the same as calling [`Self::remove_ext`], but it consumes
395    /// `self`.
396    ///
397    /// # Examples
398    /// ```rust
399    /// # use under::*;
400    /// let response = Response::empty_200()
401    ///     .with_ext(123u32);
402    /// assert_eq!(response.ext::<u32>(), Some(&123u32));
403    /// let response = response.without_ext::<u32>();
404    /// assert_eq!(response.ext::<u32>(), None);
405    /// ```
406    pub fn without_ext<T: Send + Sync + 'static>(mut self) -> Self {
407        self.remove_ext::<T>();
408        self
409    }
410
411    forward! {
412        /// Returns the [`http::StatusCode`].
413        ///
414        /// # Examples
415        ///
416        /// ```rust
417        /// # use under::*;
418        /// let response = Response::default();
419        /// assert_eq!(response.status(), http::StatusCode::OK);
420        /// ```
421        pub fn status(&self) -> http::StatusCode;
422        /// Returns a reference to the associated extensions.
423        ///
424        /// # Examples
425        ///
426        /// ```rust
427        /// # use under::*;
428        /// let response = Response::default();
429        /// assert!(response.extensions().get::<i32>().is_none());
430        /// ```
431        pub fn extensions(&self) -> &http::Extensions;
432        /// Returns a mutable reference to the associated extensions.
433        ///
434        /// # Examples
435        ///
436        /// ```rust
437        /// # use under::*;
438        /// let mut response = Response::default();
439        /// response.extensions_mut().insert("hello");
440        /// assert_eq!(response.extensions().get(), Some(&"hello"));
441        /// ```
442        pub fn extensions_mut(&mut self) -> &mut http::Extensions;
443        /// Returns a reference to the associated header field map.
444        ///
445        /// # Examples
446        ///
447        /// ```rust
448        /// # use under::*;
449        /// let response = Response::default();
450        /// assert!(response.headers().is_empty());
451        /// ```
452        pub fn headers(&self) -> &http::HeaderMap<http::HeaderValue>;
453        /// Returns a mutable reference to the associated header field map.
454        ///
455        /// # Examples
456        ///
457        /// ```
458        /// # use under::*;
459        /// # use http::header::*;
460        /// let mut response = Response::default();
461        /// response.headers_mut().insert(HOST, HeaderValue::from_static("world"));
462        /// assert!(!response.headers().is_empty());
463        /// ```
464        pub fn headers_mut(&mut self) -> &mut http::HeaderMap<http::HeaderValue>;
465    }
466}
467
468impl crate::HttpEntity for Response {
469    #[inline]
470    fn body_mut(&mut self) -> &mut hyper::Body {
471        self.0.body_mut()
472    }
473    #[inline]
474    fn headers(&self) -> &http::HeaderMap<http::HeaderValue> {
475        self.0.headers()
476    }
477    #[inline]
478    fn headers_mut(&mut self) -> &mut http::HeaderMap<http::HeaderValue> {
479        self.0.headers_mut()
480    }
481}
482
483impl Default for Response {
484    fn default() -> Self {
485        Response(
486            http::Response::builder()
487                .body(hyper::Body::empty())
488                .unwrap(),
489        )
490    }
491}
492
493impl From<http::Response<hyper::Body>> for Response {
494    fn from(hy: http::Response<hyper::Body>) -> Self {
495        Response(hy)
496    }
497}
498
499impl From<Response> for http::Response<hyper::Body> {
500    fn from(this: Response) -> Self {
501        this.0
502    }
503}
504
505impl std::borrow::Borrow<http::Response<hyper::Body>> for Response {
506    fn borrow(&self) -> &http::Response<hyper::Body> {
507        &self.0
508    }
509}
510
511impl std::borrow::BorrowMut<http::Response<hyper::Body>> for Response {
512    fn borrow_mut(&mut self) -> &mut http::Response<hyper::Body> {
513        &mut self.0
514    }
515}
516
517/// Converts the current type into a [`crate::Response`].
518///
519/// This assumes that the conversion into a response is fallible
520/// (as it often is).  This is used instead of `TryFrom` because
521/// `TryFrom<Result<T, E>>` is not implemented for `Result<T, E>`.
522///
523/// This uses `anyhow::Error` as the error type for a few reasons:
524///
525/// 1. [`anyhow::Error`] does not implement [`std::error::Error`].
526/// 2. [`std::convert::Infallible`]/[`!`] does not implement
527///    `Into<T>`/`From<T>`.
528/// 3. I can't figure out how to reconcile the two such that
529///    `IntoResponse` can be implemented for `Result<R, E>` where
530///    `R: IntoResponse`; especially if `R` is `Response`, as the
531///    `IntoResponse` implementation for that would have the error
532///    type be `Infallible`.
533pub trait IntoResponse {
534    /// Converts the current type into a response.
535    ///
536    /// # Errors
537    /// This can error if the conversion into a response fails.
538    /// This can fail if the current type is a `Result`, or if
539    /// e.g. the response fails to serialize.
540    fn into_response(self) -> Result<Response, anyhow::Error>;
541}
542
543impl IntoResponse for Response {
544    fn into_response(self) -> Result<Response, anyhow::Error> {
545        Ok(self)
546    }
547}
548
549impl<R, E> IntoResponse for Result<R, E>
550where
551    R: IntoResponse,
552    E: Into<anyhow::Error>,
553{
554    fn into_response(self) -> Result<Response, anyhow::Error> {
555        self.map_err(Into::into)
556            .and_then(|r| r.into_response().map_err(Into::into))
557    }
558}
559
560impl IntoResponse for std::convert::Infallible {
561    fn into_response(self) -> Result<Response, anyhow::Error> {
562        match self {}
563    }
564}
565
566#[cfg(test)]
567mod tests {
568    use super::*;
569
570    #[test]
571    fn convert_response() {
572        let response = Response::empty_500();
573
574        assert!(Ok::<_, std::convert::Infallible>(response)
575            .into_response()
576            .is_ok());
577    }
578}