mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-17 00:00:16 +02:00
Support returning any http_body::Body from IntoResponse (#86)
Adds associated `Body` and `BodyError` types to `IntoResponse`. This is required for returning responses with bodies other than `hyper::Body` from handlers. That wasn't previously possible. This is a breaking change so should be shipped in 0.2.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
use crate::response::IntoResponse;
|
||||
|
||||
use super::{rejection::*, FromRequest, RequestParts};
|
||||
use async_trait::async_trait;
|
||||
use std::ops::Deref;
|
||||
@@ -27,6 +29,7 @@ pub struct ContentLengthLimit<T, const N: u64>(pub T);
|
||||
impl<T, B, const N: u64> FromRequest<B> for ContentLengthLimit<T, N>
|
||||
where
|
||||
T: FromRequest<B>,
|
||||
T::Rejection: IntoResponse,
|
||||
B: Send,
|
||||
{
|
||||
type Rejection = ContentLengthLimitRejection<T::Rejection>;
|
||||
|
||||
+31
-13
@@ -1,7 +1,10 @@
|
||||
//! Rejection response types.
|
||||
|
||||
use super::IntoResponse;
|
||||
use crate::body::Body;
|
||||
use crate::body::{box_body, BoxBody, BoxStdError};
|
||||
use bytes::Bytes;
|
||||
use http_body::Full;
|
||||
use std::convert::Infallible;
|
||||
use tower::BoxError;
|
||||
|
||||
define_rejection! {
|
||||
@@ -141,8 +144,11 @@ impl InvalidUrlParam {
|
||||
}
|
||||
|
||||
impl IntoResponse for InvalidUrlParam {
|
||||
fn into_response(self) -> http::Response<Body> {
|
||||
let mut res = http::Response::new(Body::from(format!(
|
||||
type Body = Full<Bytes>;
|
||||
type BodyError = Infallible;
|
||||
|
||||
fn into_response(self) -> http::Response<Self::Body> {
|
||||
let mut res = http::Response::new(Full::from(format!(
|
||||
"Invalid URL param. Expected something of type `{}`",
|
||||
self.type_name
|
||||
)));
|
||||
@@ -163,8 +169,11 @@ impl InvalidPathParam {
|
||||
}
|
||||
|
||||
impl IntoResponse for InvalidPathParam {
|
||||
fn into_response(self) -> http::Response<Body> {
|
||||
let mut res = http::Response::new(Body::from(format!("Invalid URL param. {}", self.0)));
|
||||
type Body = Full<Bytes>;
|
||||
type BodyError = Infallible;
|
||||
|
||||
fn into_response(self) -> http::Response<Self::Body> {
|
||||
let mut res = http::Response::new(Full::from(format!("Invalid URL param. {}", self.0)));
|
||||
*res.status_mut() = http::StatusCode::BAD_REQUEST;
|
||||
res
|
||||
}
|
||||
@@ -191,8 +200,11 @@ impl FailedToDeserializeQueryString {
|
||||
}
|
||||
|
||||
impl IntoResponse for FailedToDeserializeQueryString {
|
||||
fn into_response(self) -> http::Response<Body> {
|
||||
let mut res = http::Response::new(Body::from(format!(
|
||||
type Body = Full<Bytes>;
|
||||
type BodyError = Infallible;
|
||||
|
||||
fn into_response(self) -> http::Response<Self::Body> {
|
||||
let mut res = http::Response::new(Full::from(format!(
|
||||
"Failed to deserialize query string. Expected something of type `{}`. Error: {}",
|
||||
self.type_name, self.error,
|
||||
)));
|
||||
@@ -317,12 +329,15 @@ impl<T> IntoResponse for ContentLengthLimitRejection<T>
|
||||
where
|
||||
T: IntoResponse,
|
||||
{
|
||||
fn into_response(self) -> http::Response<Body> {
|
||||
type Body = BoxBody;
|
||||
type BodyError = BoxStdError;
|
||||
|
||||
fn into_response(self) -> http::Response<Self::Body> {
|
||||
match self {
|
||||
Self::PayloadTooLarge(inner) => inner.into_response(),
|
||||
Self::LengthRequired(inner) => inner.into_response(),
|
||||
Self::HeadersAlreadyExtracted(inner) => inner.into_response(),
|
||||
Self::Inner(inner) => inner.into_response(),
|
||||
Self::PayloadTooLarge(inner) => inner.into_response().map(box_body),
|
||||
Self::LengthRequired(inner) => inner.into_response().map(box_body),
|
||||
Self::HeadersAlreadyExtracted(inner) => inner.into_response().map(box_body),
|
||||
Self::Inner(inner) => inner.into_response().map(box_body),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -339,7 +354,10 @@ pub struct TypedHeaderRejection {
|
||||
#[cfg(feature = "headers")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "headers")))]
|
||||
impl IntoResponse for TypedHeaderRejection {
|
||||
fn into_response(self) -> http::Response<crate::Body> {
|
||||
type Body = Full<Bytes>;
|
||||
type BodyError = Infallible;
|
||||
|
||||
fn into_response(self) -> http::Response<Self::Body> {
|
||||
let mut res = format!("{} ({})", self.err, self.name).into_response();
|
||||
*res.status_mut() = http::StatusCode::BAD_REQUEST;
|
||||
res
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
use super::{FromRequest, RequestParts};
|
||||
use crate::response::IntoResponse;
|
||||
use crate::{
|
||||
body::{box_body, BoxBody},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use http::Response;
|
||||
use std::convert::Infallible;
|
||||
@@ -29,11 +32,11 @@ macro_rules! impl_from_request {
|
||||
$( $tail: FromRequest<B> + Send, )*
|
||||
B: Send,
|
||||
{
|
||||
type Rejection = Response<crate::body::Body>;
|
||||
type Rejection = Response<BoxBody>;
|
||||
|
||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
let $head = $head::from_request(req).await.map_err(IntoResponse::into_response)?;
|
||||
$( let $tail = $tail::from_request(req).await.map_err(IntoResponse::into_response)?; )*
|
||||
let $head = $head::from_request(req).await.map_err(|err| err.into_response().map(box_body))?;
|
||||
$( let $tail = $tail::from_request(req).await.map_err(|err| err.into_response().map(box_body))?; )*
|
||||
Ok(($head, $($tail,)*))
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -48,10 +48,8 @@ use http::{
|
||||
header::{self, HeaderName, HeaderValue},
|
||||
Method, Response, StatusCode,
|
||||
};
|
||||
use hyper::{
|
||||
upgrade::{OnUpgrade, Upgraded},
|
||||
Body,
|
||||
};
|
||||
use http_body::Full;
|
||||
use hyper::upgrade::{OnUpgrade, Upgraded};
|
||||
use sha1::{Digest, Sha1};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
@@ -256,7 +254,10 @@ where
|
||||
F: FnOnce(WebSocket) -> Fut + Send + 'static,
|
||||
Fut: Future + Send + 'static,
|
||||
{
|
||||
fn into_response(self) -> Response<Body> {
|
||||
type Body = Full<Bytes>;
|
||||
type BodyError = <Self::Body as http_body::Body>::Error;
|
||||
|
||||
fn into_response(self) -> Response<Self::Body> {
|
||||
// check requested protocols
|
||||
let protocol = self
|
||||
.extractor
|
||||
@@ -315,7 +316,7 @@ where
|
||||
builder = builder.header(header::SEC_WEBSOCKET_PROTOCOL, protocol);
|
||||
}
|
||||
|
||||
builder.body(Body::empty()).unwrap()
|
||||
builder.body(Full::default()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user