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