use super::{IntoResponseParts, Response, ResponseParts}; use crate::{body, BoxError}; use bytes::{buf::Chain, Buf, Bytes, BytesMut}; use http::{ header::{self, HeaderMap, HeaderName, HeaderValue}, StatusCode, }; use http_body::{ combinators::{MapData, MapErr}, Empty, Full, SizeHint, }; use std::{ borrow::Cow, convert::{Infallible, TryInto}, fmt, pin::Pin, task::{Context, Poll}, }; /// Trait for generating responses. /// /// Types that implement `IntoResponse` can be returned from handlers. /// /// # Implementing `IntoResponse` /// /// You generally shouldn't have to implement `IntoResponse` manually, as axum /// provides implementations for many common types. /// /// However it might be necessary if you have a custom error type that you want /// to return from handlers: /// /// ```rust /// use axum::{ /// Router, /// body::{self, Bytes}, /// routing::get, /// http::StatusCode, /// response::{IntoResponse, Response}, /// }; /// /// enum MyError { /// SomethingWentWrong, /// SomethingElseWentWrong, /// } /// /// impl IntoResponse for MyError { /// fn into_response(self) -> Response { /// let body = match self { /// MyError::SomethingWentWrong => "something went wrong", /// MyError::SomethingElseWentWrong => "something else went wrong", /// }; /// /// // its often easiest to implement `IntoResponse` by calling other implementations /// (StatusCode::INTERNAL_SERVER_ERROR, body).into_response() /// } /// } /// /// // `Result` can now be returned from handlers /// let app = Router::new().route("/", get(handler)); /// /// async fn handler() -> Result<(), MyError> { /// Err(MyError::SomethingWentWrong) /// } /// # async { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` /// /// Or if you have a custom body type you'll also need to implement /// `IntoResponse` for it: /// /// ```rust /// use axum::{ /// body, /// routing::get, /// response::{IntoResponse, Response}, /// Router, /// }; /// use http_body::Body; /// use http::HeaderMap; /// use bytes::Bytes; /// use std::{ /// convert::Infallible, /// task::{Poll, Context}, /// pin::Pin, /// }; /// /// struct MyBody; /// /// // First implement `Body` for `MyBody`. This could for example use /// // some custom streaming protocol. /// impl Body for MyBody { /// type Data = Bytes; /// type Error = Infallible; /// /// fn poll_data( /// self: Pin<&mut Self>, /// cx: &mut Context<'_> /// ) -> Poll>> { /// # unimplemented!() /// // ... /// } /// /// fn poll_trailers( /// self: Pin<&mut Self>, /// cx: &mut Context<'_> /// ) -> Poll, Self::Error>> { /// # unimplemented!() /// // ... /// } /// } /// /// // Now we can implement `IntoResponse` directly for `MyBody` /// impl IntoResponse for MyBody { /// fn into_response(self) -> Response { /// Response::new(body::boxed(self)) /// } /// } /// /// // `MyBody` can now be returned from handlers. /// let app = Router::new().route("/", get(|| async { MyBody })); /// # async { /// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap(); /// # }; /// ``` pub trait IntoResponse { /// Create a response. fn into_response(self) -> Response; } impl IntoResponse for StatusCode { fn into_response(self) -> Response { let mut res = ().into_response(); *res.status_mut() = self; res } } impl IntoResponse for () { fn into_response(self) -> Response { Empty::new().into_response() } } impl IntoResponse for Infallible { fn into_response(self) -> Response { match self {} } } impl IntoResponse for Result where T: IntoResponse, E: IntoResponse, { fn into_response(self) -> Response { match self { Ok(value) => value.into_response(), Err(err) => err.into_response(), } } } impl IntoResponse for Response where B: http_body::Body + Send + 'static, B::Error: Into, { fn into_response(self) -> Response { self.map(body::boxed) } } impl IntoResponse for http::response::Parts { fn into_response(self) -> Response { Response::from_parts(self, body::boxed(Empty::new())) } } impl IntoResponse for Full { fn into_response(self) -> Response { Response::new(body::boxed(self)) } } impl IntoResponse for Empty { fn into_response(self) -> Response { Response::new(body::boxed(self)) } } impl IntoResponse for http_body::combinators::BoxBody where E: Into + 'static, { fn into_response(self) -> Response { Response::new(body::boxed(self)) } } impl IntoResponse for http_body::combinators::UnsyncBoxBody where E: Into + 'static, { fn into_response(self) -> Response { Response::new(body::boxed(self)) } } impl IntoResponse for MapData where B: http_body::Body + Send + 'static, F: FnMut(B::Data) -> Bytes + Send + 'static, B::Error: Into, { fn into_response(self) -> Response { Response::new(body::boxed(self)) } } impl IntoResponse for MapErr where B: http_body::Body + Send + 'static, F: FnMut(B::Error) -> E + Send + 'static, E: Into, { fn into_response(self) -> Response { Response::new(body::boxed(self)) } } impl IntoResponse for &'static str { fn into_response(self) -> Response { Cow::Borrowed(self).into_response() } } impl IntoResponse for String { fn into_response(self) -> Response { Cow::<'static, str>::Owned(self).into_response() } } impl IntoResponse for Cow<'static, str> { fn into_response(self) -> Response { let mut res = Full::from(self).into_response(); res.headers_mut().insert( header::CONTENT_TYPE, HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()), ); res } } impl IntoResponse for Bytes { fn into_response(self) -> Response { let mut res = Full::from(self).into_response(); res.headers_mut().insert( header::CONTENT_TYPE, HeaderValue::from_static(mime::APPLICATION_OCTET_STREAM.as_ref()), ); res } } impl IntoResponse for BytesMut { fn into_response(self) -> Response { self.freeze().into_response() } } impl IntoResponse for Chain where T: Buf + Unpin + Send + 'static, U: Buf + Unpin + Send + 'static, { fn into_response(self) -> Response { let (first, second) = self.into_inner(); let mut res = Response::new(body::boxed(BytesChainBody { first: Some(first), second: Some(second), })); res.headers_mut().insert( header::CONTENT_TYPE, HeaderValue::from_static(mime::APPLICATION_OCTET_STREAM.as_ref()), ); res } } struct BytesChainBody { first: Option, second: Option, } impl http_body::Body for BytesChainBody where T: Buf + Unpin, U: Buf + Unpin, { type Data = Bytes; type Error = Infallible; fn poll_data( mut self: Pin<&mut Self>, _cx: &mut Context<'_>, ) -> Poll>> { if let Some(mut buf) = self.first.take() { let bytes = buf.copy_to_bytes(buf.remaining()); return Poll::Ready(Some(Ok(bytes))); } if let Some(mut buf) = self.second.take() { let bytes = buf.copy_to_bytes(buf.remaining()); return Poll::Ready(Some(Ok(bytes))); } Poll::Ready(None) } fn poll_trailers( self: Pin<&mut Self>, _cx: &mut Context<'_>, ) -> Poll, Self::Error>> { Poll::Ready(Ok(None)) } fn is_end_stream(&self) -> bool { self.first.is_none() && self.second.is_none() } fn size_hint(&self) -> SizeHint { match (self.first.as_ref(), self.second.as_ref()) { (Some(first), Some(second)) => { let total_size = first.remaining() + second.remaining(); SizeHint::with_exact(total_size as u64) } (Some(buf), None) => SizeHint::with_exact(buf.remaining() as u64), (None, Some(buf)) => SizeHint::with_exact(buf.remaining() as u64), (None, None) => SizeHint::with_exact(0), } } } impl IntoResponse for &'static [u8] { fn into_response(self) -> Response { Cow::Borrowed(self).into_response() } } impl IntoResponse for Vec { fn into_response(self) -> Response { Cow::<'static, [u8]>::Owned(self).into_response() } } impl IntoResponse for Cow<'static, [u8]> { fn into_response(self) -> Response { let mut res = Full::from(self).into_response(); res.headers_mut().insert( header::CONTENT_TYPE, HeaderValue::from_static(mime::APPLICATION_OCTET_STREAM.as_ref()), ); res } } impl IntoResponse for (StatusCode, R) where R: IntoResponse, { fn into_response(self) -> Response { let mut res = self.1.into_response(); *res.status_mut() = self.0; res } } impl IntoResponse for HeaderMap { fn into_response(self) -> Response { let mut res = ().into_response(); *res.headers_mut() = self; res } } impl IntoResponse for [(K, V); N] where K: TryInto, K::Error: fmt::Display, V: TryInto, V::Error: fmt::Display, { fn into_response(self) -> Response { let mut res = ().into_response(); for (key, value) in self { let key = match key.try_into() { Ok(key) => key, Err(err) => { return (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response() } }; let value = match value.try_into() { Ok(value) => value, Err(err) => { return (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response() } }; res.headers_mut().insert(key, value); } res } } macro_rules! impl_into_response { ( $($ty:ident),* $(,)? ) => { #[allow(non_snake_case)] impl IntoResponse for ($($ty),*, R) where $( $ty: IntoResponseParts, )* R: IntoResponse, { fn into_response(self) -> Response { let ($($ty),*, res) = self; let res = res.into_response(); let parts = ResponseParts { res }; $( let parts = match $ty.into_response_parts(parts) { Ok(parts) => parts, Err(err) => { return err.into_response(); } }; )* parts.res } } #[allow(non_snake_case)] impl IntoResponse for (StatusCode, $($ty),*, R) where $( $ty: IntoResponseParts, )* R: IntoResponse, { fn into_response(self) -> Response { let (status, $($ty),*, res) = self; let res = res.into_response(); let parts = ResponseParts { res }; $( let parts = match $ty.into_response_parts(parts) { Ok(parts) => parts, Err(err) => { return err.into_response(); } }; )* let mut res = parts.res; *res.status_mut() = status; res } } } } all_the_tuples!(impl_into_response);