pavex/response/into_response.rs
1use bytes::Bytes;
2use http::StatusCode;
3use http_body_util::Empty;
4
5// Most of this module is an adaptation of the corresponding
6// module in `axum-core`
7//
8// Copyright (c) 2019 Axum Contributors
9//
10// Permission is hereby granted, free of charge, to any
11// person obtaining a copy of this software and associated
12// documentation files (the "Software"), to deal in the
13// Software without restriction, including without
14// limitation the rights to use, copy, modify, merge,
15// publish, distribute, sublicense, and/or sell copies of
16// the Software, and to permit persons to whom the Software
17// is furnished to do so, subject to the following
18// conditions:
19//
20// The above copyright notice and this permission notice
21// shall be included in all copies or substantial portions
22// of the Software.
23//
24// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
25// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
26// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
27// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
28// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
29// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
31// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32// DEALINGS IN THE SOFTWARE.
33use crate::{
34 Response,
35 response::{ResponseBody, ResponseHead},
36};
37
38/// Convert a type into a [`Response`].
39///
40/// Types that implement `IntoResponse` can be returned:
41///
42/// - as the output type of an infallible route handler,
43/// e.g. `fn handler() -> T` where `T: IntoResponse`.
44/// - as the `Ok` variant of the `Result` returned by a fallible route handler,
45/// e.g. `fn handler() -> Result<T, E>` where `T: IntoResponse`.
46//
47// # Implementation notes
48//
49// This is our primary divergence from `axum-core`'s API: we do NOT implement
50// `IntoResponse` for `Result<T, E>` if `T: IntoResponse` and `E: IntoResponse`.
51// It would create ambiguity: how should I handle errors? Do I need to implement
52// `IntoResponse` for `E`? Do I need to specify an error handler in the blueprint?
53// What if I do both, what gets invoked?
54//
55// ## Other divergences
56//
57// We are more conservative in the range of types that we implement `IntoResponse` for.
58// In particular, no tuples, no `()`, no types for which we'd have to infer a status code.
59pub trait IntoResponse {
60 /// Convert `self` into an HTTP response.
61 fn into_response(self) -> Response;
62}
63
64impl<B> IntoResponse for http::Response<B>
65where
66 B: http_body::Body<Data = Bytes> + Send + Sync + 'static,
67 B::Error: Into<Box<dyn std::error::Error + Send + Sync>> + 'static,
68{
69 fn into_response(self) -> Response {
70 let r: Response = self.into();
71 r.into_response()
72 }
73}
74
75impl IntoResponse for Response {
76 fn into_response(self) -> Response {
77 self
78 }
79}
80
81impl IntoResponse for StatusCode {
82 fn into_response(self) -> Response {
83 Response::new(self)
84 }
85}
86
87impl IntoResponse for http::response::Parts {
88 fn into_response(self) -> Response {
89 http::Response::from_parts(self, ResponseBody::new(Empty::new())).into()
90 }
91}
92
93impl IntoResponse for ResponseHead {
94 fn into_response(self) -> Response {
95 Response::from_parts(self, ResponseBody::default())
96 }
97}