mirror of https://github.com/fafhrd91/actix-web
responder body type temp
This commit is contained in:
parent
e4e2cef2e1
commit
81d6fb4d65
|
@ -6,8 +6,7 @@ use std::{
|
|||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use actix_web::error::Error;
|
||||
use bytes::Bytes;
|
||||
use actix_web::{error::Error, web::Bytes};
|
||||
use futures_core::{ready, Stream};
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ use std::os::unix::fs::MetadataExt;
|
|||
use actix_http::body::AnyBody;
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_web::{
|
||||
body::BoxBody,
|
||||
dev::{
|
||||
AppService, BodyEncoding, HttpServiceFactory, ResourceDef, ServiceRequest,
|
||||
ServiceResponse, SizedStream,
|
||||
|
@ -394,7 +395,7 @@ impl NamedFile {
|
|||
}
|
||||
|
||||
/// Creates an `HttpResponse` with file as a streaming body.
|
||||
pub fn into_response(self, req: &HttpRequest) -> HttpResponse {
|
||||
pub fn into_response(self, req: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
if self.status_code != StatusCode::OK {
|
||||
let mut res = HttpResponse::build(self.status_code);
|
||||
|
||||
|
@ -598,7 +599,10 @@ impl DerefMut for NamedFile {
|
|||
}
|
||||
|
||||
impl Responder for NamedFile {
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse {
|
||||
// TODO: can be improved
|
||||
type Body = BoxBody;
|
||||
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
self.into_response(req)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,10 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn either_body_works() {
|
||||
let _body = EitherBody::new(());
|
||||
fn type_parameter_inference() {
|
||||
let _body: EitherBody<(), _> = EitherBody::new(());
|
||||
|
||||
let _body: EitherBody<_, ()> = EitherBody::left(());
|
||||
let _body: EitherBody<(), _> = EitherBody::right(());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ use pin_project_lite::pin_project;
|
|||
|
||||
use super::BodySize;
|
||||
|
||||
/// An interface for response bodies.
|
||||
/// An interface types that can converted to bytes and used as response bodies.
|
||||
// TODO: examples
|
||||
pub trait MessageBody {
|
||||
type Error;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ pub enum BodySize {
|
|||
}
|
||||
|
||||
impl BodySize {
|
||||
/// Returns true if size hint indicates no or empty body.
|
||||
/// Returns true if size hint indicates omitted or empty body.
|
||||
///
|
||||
/// Streams will return false because it cannot be known without reading the stream.
|
||||
///
|
||||
|
|
|
@ -109,7 +109,9 @@ impl<T> Responder for InternalError<T>
|
|||
where
|
||||
T: fmt::Debug + fmt::Display + 'static,
|
||||
{
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse {
|
||||
type Body = BoxBody;
|
||||
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
HttpResponse::from_error(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use actix_service::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
body::EitherBody,
|
||||
service::{ServiceRequest, ServiceResponse},
|
||||
Error, FromRequest, HttpResponse, Responder,
|
||||
};
|
||||
|
@ -26,7 +27,13 @@ where
|
|||
|
||||
pub fn handler_service<F, T, R>(
|
||||
handler: F,
|
||||
) -> BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>
|
||||
) -> BoxServiceFactory<
|
||||
(),
|
||||
ServiceRequest,
|
||||
ServiceResponse<EitherBody<<R::Output as Responder>::Body>>,
|
||||
Error,
|
||||
(),
|
||||
>
|
||||
where
|
||||
F: Handler<T, R>,
|
||||
T: FromRequest,
|
||||
|
@ -35,12 +42,21 @@ where
|
|||
{
|
||||
boxed::factory(fn_service(move |req: ServiceRequest| {
|
||||
let handler = handler.clone();
|
||||
|
||||
async move {
|
||||
let (req, mut payload) = req.into_parts();
|
||||
let res = match T::from_request(&req, &mut payload).await {
|
||||
Err(err) => HttpResponse::from_error(err),
|
||||
Ok(data) => handler.call(data).await.respond_to(&req),
|
||||
Err(err) => {
|
||||
HttpResponse::from_error(err).map_body(|_, body| EitherBody::right(body))
|
||||
}
|
||||
|
||||
Ok(data) => handler
|
||||
.call(data)
|
||||
.await
|
||||
.respond_to(&req)
|
||||
.map_body(|_, body| EitherBody::left(body)),
|
||||
};
|
||||
|
||||
Ok(ServiceResponse::new(req, res))
|
||||
}
|
||||
}))
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::rc::Rc;
|
||||
use std::{cell::RefCell, error::Error as StdError, fmt, future::Future, rc::Rc};
|
||||
|
||||
use actix_http::Extensions;
|
||||
use actix_router::{IntoPatterns, Patterns};
|
||||
|
@ -13,6 +10,7 @@ use futures_core::future::LocalBoxFuture;
|
|||
use futures_util::future::join_all;
|
||||
|
||||
use crate::{
|
||||
body::MessageBody,
|
||||
data::Data,
|
||||
dev::{ensure_leading_slash, AppService, ResourceDef},
|
||||
guard::Guard,
|
||||
|
@ -241,6 +239,9 @@ where
|
|||
I: FromRequest + 'static,
|
||||
R: Future + 'static,
|
||||
R::Output: Responder + 'static,
|
||||
<R::Output as Responder>::Body: MessageBody + 'static,
|
||||
<<R::Output as Responder>::Body as MessageBody>::Error:
|
||||
Into<Box<dyn StdError + 'static>>,
|
||||
{
|
||||
self.routes.push(Route::new().to(handler));
|
||||
self
|
||||
|
|
121
src/responder.rs
121
src/responder.rs
|
@ -1,5 +1,7 @@
|
|||
use std::error::Error as StdError;
|
||||
|
||||
use actix_http::{
|
||||
body::BoxBody,
|
||||
body::{BoxBody, EitherBody, MessageBody},
|
||||
http::{header::IntoHeaderPair, Error as HttpError, HeaderMap, StatusCode},
|
||||
};
|
||||
use bytes::{Bytes, BytesMut};
|
||||
|
@ -10,8 +12,10 @@ use crate::{Error, HttpRequest, HttpResponse, HttpResponseBuilder};
|
|||
///
|
||||
/// Any types that implement this trait can be used in the return type of a handler.
|
||||
pub trait Responder {
|
||||
type Body: MessageBody + 'static;
|
||||
|
||||
/// Convert self to `HttpResponse`.
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<BoxBody>;
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<Self::Body>;
|
||||
|
||||
/// Override a status code for a Responder.
|
||||
///
|
||||
|
@ -57,38 +61,56 @@ pub trait Responder {
|
|||
}
|
||||
|
||||
impl Responder for HttpResponse {
|
||||
type Body = BoxBody;
|
||||
|
||||
#[inline]
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for actix_http::Response<BoxBody> {
|
||||
type Body = BoxBody;
|
||||
|
||||
#[inline]
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
HttpResponse::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for HttpResponseBuilder {
|
||||
type Body = BoxBody;
|
||||
|
||||
#[inline]
|
||||
fn respond_to(mut self, _: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
fn respond_to(mut self, _: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
self.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for actix_http::ResponseBuilder {
|
||||
type Body = BoxBody;
|
||||
|
||||
#[inline]
|
||||
fn respond_to(mut self, req: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
fn respond_to(mut self, req: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
self.finish().map_into_boxed_body().respond_to(req)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Responder> Responder for Option<T> {
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
impl<T> Responder for Option<T>
|
||||
where
|
||||
T: Responder,
|
||||
<T::Body as MessageBody>::Error: Into<Box<dyn StdError + 'static>>,
|
||||
{
|
||||
type Body = EitherBody<T::Body>;
|
||||
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
match self {
|
||||
Some(val) => val.respond_to(req),
|
||||
None => HttpResponse::new(StatusCode::NOT_FOUND),
|
||||
Some(val) => val
|
||||
.respond_to(req)
|
||||
.map_body(|_, body| EitherBody::left(body)),
|
||||
|
||||
None => HttpResponse::new(StatusCode::NOT_FOUND)
|
||||
.map_body(|_, body| EitherBody::right(body)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,48 +118,78 @@ impl<T: Responder> Responder for Option<T> {
|
|||
impl<T, E> Responder for Result<T, E>
|
||||
where
|
||||
T: Responder,
|
||||
<T::Body as MessageBody>::Error: Into<Box<dyn StdError + 'static>>,
|
||||
E: Into<Error>,
|
||||
{
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
type Body = EitherBody<T::Body>;
|
||||
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
match self {
|
||||
Ok(val) => val.respond_to(req),
|
||||
Err(e) => HttpResponse::from_error(e.into()),
|
||||
Ok(val) => val
|
||||
.respond_to(req)
|
||||
.map_body(|_, body| EitherBody::left(body)),
|
||||
|
||||
Err(e) => {
|
||||
HttpResponse::from_error(e.into()).map_body(|_, body| EitherBody::right(body))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Responder> Responder for (T, StatusCode) {
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
type Body = T::Body;
|
||||
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
let mut res = self.0.respond_to(req);
|
||||
*res.status_mut() = self.1;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_responder {
|
||||
($res: ty, $ct: path) => {
|
||||
macro_rules! impl_responder_by_forward_into_base_response {
|
||||
($res:ty, $body:ty) => {
|
||||
impl Responder for $res {
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<BoxBody> {
|
||||
HttpResponse::Ok().content_type($ct).body(self)
|
||||
type Body = $body;
|
||||
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
let res: actix_http::Response<_> = self.into();
|
||||
res.into()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
($res:ty) => {
|
||||
impl_responder_by_forward_into_base_response!($res, $res);
|
||||
};
|
||||
}
|
||||
|
||||
impl_responder!(&'static str, mime::TEXT_PLAIN_UTF_8);
|
||||
impl_responder_by_forward_into_base_response!(&'static [u8]);
|
||||
impl_responder_by_forward_into_base_response!(Bytes);
|
||||
impl_responder_by_forward_into_base_response!(BytesMut);
|
||||
|
||||
impl_responder!(String, mime::TEXT_PLAIN_UTF_8);
|
||||
impl_responder_by_forward_into_base_response!(&'static str);
|
||||
impl_responder_by_forward_into_base_response!(String);
|
||||
|
||||
// macro_rules! impl_responder {
|
||||
// ($res:ty, $body:ty, $ct:path) => {
|
||||
// impl Responder for $res {
|
||||
// type Body = $body;
|
||||
|
||||
// fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
// HttpResponse::Ok().content_type($ct).body(self)
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// ($res:ty, $ct:path) => {
|
||||
// impl_responder!($res, $res, $ct);
|
||||
// };
|
||||
// }
|
||||
|
||||
// impl_responder!(&'_ String, mime::TEXT_PLAIN_UTF_8);
|
||||
|
||||
// impl_responder!(Cow<'_, str>, mime::TEXT_PLAIN_UTF_8);
|
||||
|
||||
impl_responder!(&'static [u8], mime::APPLICATION_OCTET_STREAM);
|
||||
|
||||
impl_responder!(Bytes, mime::APPLICATION_OCTET_STREAM);
|
||||
|
||||
impl_responder!(BytesMut, mime::APPLICATION_OCTET_STREAM);
|
||||
|
||||
/// Allows overriding status code and headers for a responder.
|
||||
pub struct CustomResponder<T> {
|
||||
responder: T,
|
||||
|
@ -202,11 +254,20 @@ impl<T: Responder> CustomResponder<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Responder> Responder for CustomResponder<T> {
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse {
|
||||
impl<T> Responder for CustomResponder<T>
|
||||
where
|
||||
T: Responder,
|
||||
<T::Body as MessageBody>::Error: Into<Box<dyn StdError + 'static>>,
|
||||
{
|
||||
type Body = EitherBody<T::Body>;
|
||||
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
let headers = match self.headers {
|
||||
Ok(headers) => headers,
|
||||
Err(err) => return HttpResponse::from_error(Error::from(err)),
|
||||
Err(err) => {
|
||||
return HttpResponse::from_error(Error::from(err))
|
||||
.map_body(|_, body| EitherBody::right(body))
|
||||
}
|
||||
};
|
||||
|
||||
let mut res = self.responder.respond_to(req);
|
||||
|
@ -220,7 +281,7 @@ impl<T: Responder> Responder for CustomResponder<T> {
|
|||
res.headers_mut().insert(k, v);
|
||||
}
|
||||
|
||||
res
|
||||
res.map_body(|_, body| EitherBody::left(body))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -306,7 +306,7 @@ impl HttpResponseBuilder {
|
|||
.extensions_mut()
|
||||
}
|
||||
|
||||
/// Set a body and generate `Response`.
|
||||
/// Set a body and build the `HttpResponse`.
|
||||
///
|
||||
/// `HttpResponseBuilder` can not be used after this call.
|
||||
pub fn body<B>(&mut self, body: B) -> HttpResponse<BoxBody>
|
||||
|
@ -320,7 +320,7 @@ impl HttpResponseBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set a body and generate `Response`.
|
||||
/// Set a body and build the `HttpResponse`.
|
||||
///
|
||||
/// `HttpResponseBuilder` can not be used after this call.
|
||||
pub fn message_body<B>(&mut self, body: B) -> Result<HttpResponse<B>, Error> {
|
||||
|
@ -350,7 +350,7 @@ impl HttpResponseBuilder {
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
/// Set a streaming body and generate `Response`.
|
||||
/// Set a streaming body and build the `HttpResponse`.
|
||||
///
|
||||
/// `HttpResponseBuilder` can not be used after this call.
|
||||
#[inline]
|
||||
|
@ -362,7 +362,7 @@ impl HttpResponseBuilder {
|
|||
self.body(BoxBody::new(BodyStream::new(stream)))
|
||||
}
|
||||
|
||||
/// Set a json body and generate `Response`
|
||||
/// Set a JSON body and build the `HttpResponse`.
|
||||
///
|
||||
/// `HttpResponseBuilder` can not be used after this call.
|
||||
pub fn json(&mut self, value: impl Serialize) -> HttpResponse {
|
||||
|
@ -384,7 +384,7 @@ impl HttpResponseBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Set an empty body and generate `Response`
|
||||
/// Set an empty body and build the `HttpResponse`.
|
||||
///
|
||||
/// `HttpResponseBuilder` can not be used after this call.
|
||||
#[inline]
|
||||
|
|
17
src/route.rs
17
src/route.rs
|
@ -1,6 +1,6 @@
|
|||
#![allow(clippy::rc_buffer)] // inner value is mutated before being shared (`Rc::get_mut`)
|
||||
|
||||
use std::{future::Future, rc::Rc};
|
||||
use std::{error::Error as StdError, future::Future, mem, rc::Rc};
|
||||
|
||||
use actix_http::http::Method;
|
||||
use actix_service::{
|
||||
|
@ -10,6 +10,7 @@ use actix_service::{
|
|||
use futures_core::future::LocalBoxFuture;
|
||||
|
||||
use crate::{
|
||||
body::MessageBody,
|
||||
guard::{self, Guard},
|
||||
handler::{handler_service, Handler},
|
||||
service::{ServiceRequest, ServiceResponse},
|
||||
|
@ -30,13 +31,16 @@ impl Route {
|
|||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> Route {
|
||||
Route {
|
||||
service: handler_service(HttpResponse::NotFound),
|
||||
// TODO: remove double boxing
|
||||
service: boxed::factory(
|
||||
handler_service(HttpResponse::NotFound).map(|res| res.map_into_boxed_body()),
|
||||
),
|
||||
guards: Rc::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn take_guards(&mut self) -> Vec<Box<dyn Guard>> {
|
||||
std::mem::take(Rc::get_mut(&mut self.guards).unwrap())
|
||||
mem::take(Rc::get_mut(&mut self.guards).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,8 +185,13 @@ impl Route {
|
|||
T: FromRequest + 'static,
|
||||
R: Future + 'static,
|
||||
R::Output: Responder + 'static,
|
||||
<R::Output as Responder>::Body: MessageBody + 'static,
|
||||
<<R::Output as Responder>::Body as MessageBody>::Error:
|
||||
Into<Box<dyn StdError + 'static>>,
|
||||
{
|
||||
self.service = handler_service(handler);
|
||||
// TODO: remove double boxing
|
||||
self.service =
|
||||
boxed::factory(handler_service(handler).map(|res| res.map_into_boxed_body()));
|
||||
self
|
||||
}
|
||||
|
||||
|
|
|
@ -656,8 +656,8 @@ fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::T
|
|||
Ok(net::TcpListener::from(socket))
|
||||
}
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
/// Configure `SslAcceptorBuilder` with custom server flags.
|
||||
#[cfg(feature = "openssl")]
|
||||
fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
|
||||
builder.set_alpn_select_callback(|_, protocols| {
|
||||
const H2: &[u8] = b"\x02h2";
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! For either helper, see [`Either`].
|
||||
|
||||
use std::{
|
||||
error::Error as StdError,
|
||||
future::Future,
|
||||
mem,
|
||||
pin::Pin,
|
||||
|
@ -12,7 +13,7 @@ use futures_core::ready;
|
|||
use pin_project_lite::pin_project;
|
||||
|
||||
use crate::{
|
||||
dev,
|
||||
body, dev,
|
||||
web::{Form, Json},
|
||||
Error, FromRequest, HttpRequest, HttpResponse, Responder,
|
||||
};
|
||||
|
@ -144,12 +145,21 @@ impl<L, R> Either<L, R> {
|
|||
impl<L, R> Responder for Either<L, R>
|
||||
where
|
||||
L: Responder,
|
||||
<L::Body as dev::MessageBody>::Error: Into<Box<dyn StdError + 'static>>,
|
||||
R: Responder,
|
||||
<R::Body as dev::MessageBody>::Error: Into<Box<dyn StdError + 'static>>,
|
||||
{
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse {
|
||||
type Body = body::EitherBody<L::Body, R::Body>;
|
||||
|
||||
fn respond_to(self, req: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
match self {
|
||||
Either::Left(a) => a.respond_to(req),
|
||||
Either::Right(b) => b.respond_to(req),
|
||||
Either::Left(a) => a
|
||||
.respond_to(req)
|
||||
.map_body(|_, body| body::EitherBody::left(body)),
|
||||
|
||||
Either::Right(b) => b
|
||||
.respond_to(req)
|
||||
.map_body(|_, body| body::EitherBody::right(body)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,9 @@ use serde::{de::DeserializeOwned, Serialize};
|
|||
#[cfg(feature = "__compress")]
|
||||
use crate::dev::Decompress;
|
||||
use crate::{
|
||||
error::UrlencodedError, extract::FromRequest, http::header::CONTENT_LENGTH, web, Error,
|
||||
HttpMessage, HttpRequest, HttpResponse, Responder,
|
||||
body::EitherBody, error::UrlencodedError, extract::FromRequest,
|
||||
http::header::CONTENT_LENGTH, web, Error, HttpMessage, HttpRequest, HttpResponse,
|
||||
Responder,
|
||||
};
|
||||
|
||||
/// URL encoded payload extractor and responder.
|
||||
|
@ -180,12 +181,22 @@ impl<T: fmt::Display> fmt::Display for Form<T> {
|
|||
|
||||
/// See [here](#responder) for example of usage as a handler return type.
|
||||
impl<T: Serialize> Responder for Form<T> {
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse {
|
||||
type Body = EitherBody<String>;
|
||||
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
match serde_urlencoded::to_string(&self.0) {
|
||||
Ok(body) => HttpResponse::Ok()
|
||||
Ok(body) => match HttpResponse::Ok()
|
||||
.content_type(mime::APPLICATION_WWW_FORM_URLENCODED)
|
||||
.body(body),
|
||||
Err(err) => HttpResponse::from_error(UrlencodedError::Serialize(err)),
|
||||
.message_body(body)
|
||||
{
|
||||
Ok(res) => res.map_body(|_, body| EitherBody::left(body)),
|
||||
Err(err) => {
|
||||
HttpResponse::from_error(err).map_body(|_, body| EitherBody::right(body))
|
||||
}
|
||||
},
|
||||
|
||||
Err(err) => HttpResponse::from_error(UrlencodedError::Serialize(err))
|
||||
.map_body(|_, body| EitherBody::right(body)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ use actix_http::Payload;
|
|||
#[cfg(feature = "__compress")]
|
||||
use crate::dev::Decompress;
|
||||
use crate::{
|
||||
body::EitherBody,
|
||||
error::{Error, JsonPayloadError},
|
||||
extract::FromRequest,
|
||||
http::header::CONTENT_LENGTH,
|
||||
|
@ -116,12 +117,22 @@ impl<T: Serialize> Serialize for Json<T> {
|
|||
///
|
||||
/// If serialization failed
|
||||
impl<T: Serialize> Responder for Json<T> {
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse {
|
||||
type Body = EitherBody<String>;
|
||||
|
||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||
match serde_json::to_string(&self.0) {
|
||||
Ok(body) => HttpResponse::Ok()
|
||||
Ok(body) => match HttpResponse::Ok()
|
||||
.content_type(mime::APPLICATION_JSON)
|
||||
.body(body),
|
||||
Err(err) => HttpResponse::from_error(JsonPayloadError::Serialize(err)),
|
||||
.message_body(body)
|
||||
{
|
||||
Ok(res) => res.map_body(|_, body| EitherBody::left(body)),
|
||||
Err(err) => {
|
||||
HttpResponse::from_error(err).map_body(|_, body| EitherBody::right(body))
|
||||
}
|
||||
},
|
||||
|
||||
Err(err) => HttpResponse::from_error(JsonPayloadError::Serialize(err))
|
||||
.map_body(|_, body| EitherBody::right(body)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
//! Essentials helper functions and types for application registration.
|
||||
|
||||
use std::future::Future;
|
||||
use std::{error::Error as StdError, future::Future};
|
||||
|
||||
use actix_http::http::Method;
|
||||
use actix_router::IntoPatterns;
|
||||
pub use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||
|
||||
use crate::{
|
||||
error::BlockingError, extract::FromRequest, handler::Handler, resource::Resource,
|
||||
responder::Responder, route::Route, scope::Scope, service::WebService,
|
||||
body::MessageBody, error::BlockingError, extract::FromRequest, handler::Handler,
|
||||
resource::Resource, responder::Responder, route::Route, scope::Scope, service::WebService,
|
||||
};
|
||||
|
||||
pub use crate::config::ServiceConfig;
|
||||
|
@ -145,6 +145,8 @@ where
|
|||
I: FromRequest + 'static,
|
||||
R: Future + 'static,
|
||||
R::Output: Responder + 'static,
|
||||
<R::Output as Responder>::Body: MessageBody + 'static,
|
||||
<<R::Output as Responder>::Body as MessageBody>::Error: Into<Box<dyn StdError + 'static>>,
|
||||
{
|
||||
Route::new().to(handler)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue