mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
remove unpin from body types (#2152)
This commit is contained in:
parent
ce50cc9523
commit
edd9f14752
@ -1,6 +1,14 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Added
|
||||||
|
* `impl<T: MessageBody> MessageBody for Pin<Box<T>>`. [#2152]
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
* The type parameter of `Response` no longer has a default. [#2152]
|
||||||
|
* The `Message` variant of `body::Body` is now `Pin<Box<dyn MessageBody>>`. [#2152]
|
||||||
|
* `BodyStream` and `SizedStream` are no longer restricted to Unpin types. [#2152]
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
* `cookies` feature flag. [#2065]
|
* `cookies` feature flag. [#2065]
|
||||||
* Top-level `cookies` mod (re-export). [#2065]
|
* Top-level `cookies` mod (re-export). [#2065]
|
||||||
@ -13,6 +21,7 @@
|
|||||||
|
|
||||||
[#2065]: https://github.com/actix/actix-web/pull/2065
|
[#2065]: https://github.com/actix/actix-web/pull/2065
|
||||||
[#2148]: https://github.com/actix/actix-web/pull/2148
|
[#2148]: https://github.com/actix/actix-web/pull/2148
|
||||||
|
[#2152]: https://github.com/actix/actix-web/pull/2152
|
||||||
|
|
||||||
|
|
||||||
## 3.0.0-beta.5 - 2021-04-02
|
## 3.0.0-beta.5 - 2021-04-02
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use std::{env, io};
|
use std::{env, io};
|
||||||
|
|
||||||
use actix_http::http::HeaderValue;
|
use actix_http::{body::Body, http::HeaderValue};
|
||||||
use actix_http::{Error, HttpService, Request, Response};
|
use actix_http::{Error, HttpService, Request, Response};
|
||||||
use actix_server::Server;
|
use actix_server::Server;
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
use futures_util::StreamExt as _;
|
use futures_util::StreamExt as _;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
async fn handle_request(mut req: Request) -> Result<Response, Error> {
|
async fn handle_request(mut req: Request) -> Result<Response<Body>, Error> {
|
||||||
let mut body = BytesMut::new();
|
let mut body = BytesMut::new();
|
||||||
while let Some(item) = req.payload().next().await {
|
while let Some(item) = req.payload().next().await {
|
||||||
body.extend_from_slice(&item?)
|
body.extend_from_slice(&item?)
|
||||||
|
@ -12,15 +12,19 @@ use crate::error::Error;
|
|||||||
use super::{BodySize, BodyStream, MessageBody, SizedStream};
|
use super::{BodySize, BodyStream, MessageBody, SizedStream};
|
||||||
|
|
||||||
/// Represents various types of HTTP message body.
|
/// Represents various types of HTTP message body.
|
||||||
|
// #[deprecated(since = "4.0.0", note = "Use body types directly.")]
|
||||||
pub enum Body {
|
pub enum Body {
|
||||||
/// Empty response. `Content-Length` header is not set.
|
/// Empty response. `Content-Length` header is not set.
|
||||||
None,
|
None,
|
||||||
|
|
||||||
/// Zero sized response body. `Content-Length` header is set to `0`.
|
/// Zero sized response body. `Content-Length` header is set to `0`.
|
||||||
Empty,
|
Empty,
|
||||||
|
|
||||||
/// Specific response body.
|
/// Specific response body.
|
||||||
Bytes(Bytes),
|
Bytes(Bytes),
|
||||||
|
|
||||||
/// Generic message body.
|
/// Generic message body.
|
||||||
Message(Box<dyn MessageBody + Unpin>),
|
Message(Pin<Box<dyn MessageBody>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Body {
|
impl Body {
|
||||||
@ -30,8 +34,8 @@ impl Body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create body from generic message body.
|
/// Create body from generic message body.
|
||||||
pub fn from_message<B: MessageBody + Unpin + 'static>(body: B) -> Body {
|
pub fn from_message<B: MessageBody + 'static>(body: B) -> Body {
|
||||||
Body::Message(Box::new(body))
|
Body::Message(Box::pin(body))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +64,7 @@ impl MessageBody for Body {
|
|||||||
Poll::Ready(Some(Ok(mem::take(bin))))
|
Poll::Ready(Some(Ok(mem::take(bin))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Body::Message(body) => Pin::new(&mut **body).poll_next(cx),
|
Body::Message(body) => body.as_mut().poll_next(cx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,7 +138,7 @@ impl From<BytesMut> for Body {
|
|||||||
|
|
||||||
impl<S> From<SizedStream<S>> for Body
|
impl<S> From<SizedStream<S>> for Body
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, Error>> + Unpin + 'static,
|
S: Stream<Item = Result<Bytes, Error>> + 'static,
|
||||||
{
|
{
|
||||||
fn from(s: SizedStream<S>) -> Body {
|
fn from(s: SizedStream<S>) -> Body {
|
||||||
Body::from_message(s)
|
Body::from_message(s)
|
||||||
@ -143,7 +147,7 @@ where
|
|||||||
|
|
||||||
impl<S, E> From<BodyStream<S>> for Body
|
impl<S, E> From<BodyStream<S>> for Body
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
|
S: Stream<Item = Result<Bytes, E>> + 'static,
|
||||||
E: Into<Error> + 'static,
|
E: Into<Error> + 'static,
|
||||||
{
|
{
|
||||||
fn from(s: BodyStream<S>) -> Body {
|
fn from(s: BodyStream<S>) -> Body {
|
||||||
|
@ -5,21 +5,25 @@ use std::{
|
|||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_core::{ready, Stream};
|
use futures_core::{ready, Stream};
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
use super::{BodySize, MessageBody};
|
use super::{BodySize, MessageBody};
|
||||||
|
|
||||||
/// Streaming response wrapper.
|
pin_project! {
|
||||||
///
|
/// Streaming response wrapper.
|
||||||
/// Response does not contain `Content-Length` header and appropriate transfer encoding is used.
|
///
|
||||||
pub struct BodyStream<S: Unpin> {
|
/// Response does not contain `Content-Length` header and appropriate transfer encoding is used.
|
||||||
stream: S,
|
pub struct BodyStream<S> {
|
||||||
|
#[pin]
|
||||||
|
stream: S,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, E> BodyStream<S>
|
impl<S, E> BodyStream<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, E>> + Unpin,
|
S: Stream<Item = Result<Bytes, E>>,
|
||||||
E: Into<Error>,
|
E: Into<Error>,
|
||||||
{
|
{
|
||||||
pub fn new(stream: S) -> Self {
|
pub fn new(stream: S) -> Self {
|
||||||
@ -29,7 +33,7 @@ where
|
|||||||
|
|
||||||
impl<S, E> MessageBody for BodyStream<S>
|
impl<S, E> MessageBody for BodyStream<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, E>> + Unpin,
|
S: Stream<Item = Result<Bytes, E>>,
|
||||||
E: Into<Error>,
|
E: Into<Error>,
|
||||||
{
|
{
|
||||||
fn size(&self) -> BodySize {
|
fn size(&self) -> BodySize {
|
||||||
@ -46,9 +50,9 @@ where
|
|||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
) -> Poll<Option<Result<Bytes, Error>>> {
|
) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
loop {
|
loop {
|
||||||
let stream = &mut self.as_mut().stream;
|
let stream = self.as_mut().project().stream;
|
||||||
|
|
||||||
let chunk = match ready!(Pin::new(stream).poll_next(cx)) {
|
let chunk = match ready!(stream.poll_next(cx)) {
|
||||||
Some(Ok(ref bytes)) if bytes.is_empty() => continue,
|
Some(Ok(ref bytes)) if bytes.is_empty() => continue,
|
||||||
opt => opt.map(|res| res.map_err(Into::into)),
|
opt => opt.map(|res| res.map_err(Into::into)),
|
||||||
};
|
};
|
||||||
|
@ -52,6 +52,19 @@ impl<T: MessageBody + Unpin> MessageBody for Box<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: MessageBody> MessageBody for Pin<Box<T>> {
|
||||||
|
fn size(&self) -> BodySize {
|
||||||
|
self.as_ref().size()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_next(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
|
self.as_mut().poll_next(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MessageBody for Bytes {
|
impl MessageBody for Bytes {
|
||||||
fn size(&self) -> BodySize {
|
fn size(&self) -> BodySize {
|
||||||
BodySize::Sized(self.len() as u64)
|
BodySize::Sized(self.len() as u64)
|
||||||
|
@ -5,23 +5,27 @@ use std::{
|
|||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_core::{ready, Stream};
|
use futures_core::{ready, Stream};
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
|
||||||
use super::{BodySize, MessageBody};
|
use super::{BodySize, MessageBody};
|
||||||
|
|
||||||
/// Known sized streaming response wrapper.
|
pin_project! {
|
||||||
///
|
/// Known sized streaming response wrapper.
|
||||||
/// This body implementation should be used if total size of stream is known. Data get sent as is
|
///
|
||||||
/// without using transfer encoding.
|
/// This body implementation should be used if total size of stream is known. Data get sent as is
|
||||||
pub struct SizedStream<S: Unpin> {
|
/// without using transfer encoding.
|
||||||
size: u64,
|
pub struct SizedStream<S> {
|
||||||
stream: S,
|
size: u64,
|
||||||
|
#[pin]
|
||||||
|
stream: S,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> SizedStream<S>
|
impl<S> SizedStream<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, Error>> + Unpin,
|
S: Stream<Item = Result<Bytes, Error>>,
|
||||||
{
|
{
|
||||||
pub fn new(size: u64, stream: S) -> Self {
|
pub fn new(size: u64, stream: S) -> Self {
|
||||||
SizedStream { size, stream }
|
SizedStream { size, stream }
|
||||||
@ -30,7 +34,7 @@ where
|
|||||||
|
|
||||||
impl<S> MessageBody for SizedStream<S>
|
impl<S> MessageBody for SizedStream<S>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, Error>> + Unpin,
|
S: Stream<Item = Result<Bytes, Error>>,
|
||||||
{
|
{
|
||||||
fn size(&self) -> BodySize {
|
fn size(&self) -> BodySize {
|
||||||
BodySize::Sized(self.size as u64)
|
BodySize::Sized(self.size as u64)
|
||||||
@ -46,9 +50,9 @@ where
|
|||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
) -> Poll<Option<Result<Bytes, Error>>> {
|
) -> Poll<Option<Result<Bytes, Error>>> {
|
||||||
loop {
|
loop {
|
||||||
let stream = &mut self.as_mut().stream;
|
let stream = self.as_mut().project().stream;
|
||||||
|
|
||||||
let chunk = match ready!(Pin::new(stream).poll_next(cx)) {
|
let chunk = match ready!(stream.poll_next(cx)) {
|
||||||
Some(Ok(ref bytes)) if bytes.is_empty() => continue,
|
Some(Ok(ref bytes)) if bytes.is_empty() => continue,
|
||||||
val => val,
|
val => val,
|
||||||
};
|
};
|
||||||
|
@ -92,7 +92,7 @@ impl<B: MessageBody> Encoder<B> {
|
|||||||
enum EncoderBody<B> {
|
enum EncoderBody<B> {
|
||||||
Bytes(Bytes),
|
Bytes(Bytes),
|
||||||
Stream(#[pin] B),
|
Stream(#[pin] B),
|
||||||
BoxedStream(Box<dyn MessageBody + Unpin>),
|
BoxedStream(Pin<Box<dyn MessageBody>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: MessageBody> MessageBody for EncoderBody<B> {
|
impl<B: MessageBody> MessageBody for EncoderBody<B> {
|
||||||
@ -117,9 +117,7 @@ impl<B: MessageBody> MessageBody for EncoderBody<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
EncoderBodyProj::Stream(b) => b.poll_next(cx),
|
EncoderBodyProj::Stream(b) => b.poll_next(cx),
|
||||||
EncoderBodyProj::BoxedStream(ref mut b) => {
|
EncoderBodyProj::BoxedStream(ref mut b) => b.as_mut().poll_next(cx),
|
||||||
Pin::new(b.as_mut()).poll_next(cx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ pub trait ResponseError: fmt::Debug + fmt::Display {
|
|||||||
/// Create response for error
|
/// Create response for error
|
||||||
///
|
///
|
||||||
/// Internal server error is generated by default.
|
/// Internal server error is generated by default.
|
||||||
fn error_response(&self) -> Response {
|
fn error_response(&self) -> Response<Body> {
|
||||||
let mut resp = Response::new(self.status_code());
|
let mut resp = Response::new(self.status_code());
|
||||||
let mut buf = BytesMut::new();
|
let mut buf = BytesMut::new();
|
||||||
let _ = write!(Writer(&mut buf), "{}", self);
|
let _ = write!(Writer(&mut buf), "{}", self);
|
||||||
@ -111,7 +111,7 @@ impl From<std::convert::Infallible> for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert `Error` to a `Response` instance
|
/// Convert `Error` to a `Response` instance
|
||||||
impl From<Error> for Response {
|
impl From<Error> for Response<Body> {
|
||||||
fn from(err: Error) -> Self {
|
fn from(err: Error) -> Self {
|
||||||
Response::from_error(err)
|
Response::from_error(err)
|
||||||
}
|
}
|
||||||
@ -127,8 +127,8 @@ impl<T: ResponseError + 'static> From<T> for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Convert Response to a Error
|
/// Convert Response to a Error
|
||||||
impl From<Response> for Error {
|
impl From<Response<Body>> for Error {
|
||||||
fn from(res: Response) -> Error {
|
fn from(res: Response<Body>) -> Error {
|
||||||
InternalError::from_response("", res).into()
|
InternalError::from_response("", res).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,7 +454,7 @@ pub struct InternalError<T> {
|
|||||||
|
|
||||||
enum InternalErrorType {
|
enum InternalErrorType {
|
||||||
Status(StatusCode),
|
Status(StatusCode),
|
||||||
Response(RefCell<Option<Response>>),
|
Response(RefCell<Option<Response<Body>>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> InternalError<T> {
|
impl<T> InternalError<T> {
|
||||||
@ -467,7 +467,7 @@ impl<T> InternalError<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create `InternalError` with predefined `Response`.
|
/// Create `InternalError` with predefined `Response`.
|
||||||
pub fn from_response(cause: T, response: Response) -> Self {
|
pub fn from_response(cause: T, response: Response<Body>) -> Self {
|
||||||
InternalError {
|
InternalError {
|
||||||
cause,
|
cause,
|
||||||
status: InternalErrorType::Response(RefCell::new(Some(response))),
|
status: InternalErrorType::Response(RefCell::new(Some(response))),
|
||||||
@ -510,7 +510,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_response(&self) -> Response {
|
fn error_response(&self) -> Response<Body> {
|
||||||
match self.status {
|
match self.status {
|
||||||
InternalErrorType::Status(st) => {
|
InternalErrorType::Status(st) => {
|
||||||
let mut res = Response::new(st);
|
let mut res = Response::new(st);
|
||||||
@ -931,11 +931,11 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_response() {
|
fn test_into_response() {
|
||||||
let resp: Response = ParseError::Incomplete.error_response();
|
let resp: Response<Body> = ParseError::Incomplete.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
let err: HttpError = StatusCode::from_u16(10000).err().unwrap().into();
|
let err: HttpError = StatusCode::from_u16(10000).err().unwrap().into();
|
||||||
let resp: Response = err.error_response();
|
let resp: Response<Body> = err.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,7 +966,7 @@ mod tests {
|
|||||||
fn test_error_http_response() {
|
fn test_error_http_response() {
|
||||||
let orig = io::Error::new(io::ErrorKind::Other, "other");
|
let orig = io::Error::new(io::ErrorKind::Other, "other");
|
||||||
let e = Error::from(orig);
|
let e = Error::from(orig);
|
||||||
let resp: Response = e.into();
|
let resp: Response<Body> = e.into();
|
||||||
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,7 +1023,7 @@ mod tests {
|
|||||||
fn test_internal_error() {
|
fn test_internal_error() {
|
||||||
let err =
|
let err =
|
||||||
InternalError::from_response(ParseError::Method, Response::Ok().into());
|
InternalError::from_response(ParseError::Method, Response::Ok().into());
|
||||||
let resp: Response = err.error_response();
|
let resp: Response<Body> = err.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1039,121 +1039,121 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_helpers() {
|
fn test_error_helpers() {
|
||||||
let r: Response = ErrorBadRequest("err").into();
|
let res: Response<Body> = ErrorBadRequest("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
||||||
|
|
||||||
let r: Response = ErrorUnauthorized("err").into();
|
let res: Response<Body> = ErrorUnauthorized("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::UNAUTHORIZED);
|
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
|
||||||
|
|
||||||
let r: Response = ErrorPaymentRequired("err").into();
|
let res: Response<Body> = ErrorPaymentRequired("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::PAYMENT_REQUIRED);
|
assert_eq!(res.status(), StatusCode::PAYMENT_REQUIRED);
|
||||||
|
|
||||||
let r: Response = ErrorForbidden("err").into();
|
let res: Response<Body> = ErrorForbidden("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::FORBIDDEN);
|
assert_eq!(res.status(), StatusCode::FORBIDDEN);
|
||||||
|
|
||||||
let r: Response = ErrorNotFound("err").into();
|
let res: Response<Body> = ErrorNotFound("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::NOT_FOUND);
|
assert_eq!(res.status(), StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
let r: Response = ErrorMethodNotAllowed("err").into();
|
let res: Response<Body> = ErrorMethodNotAllowed("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::METHOD_NOT_ALLOWED);
|
assert_eq!(res.status(), StatusCode::METHOD_NOT_ALLOWED);
|
||||||
|
|
||||||
let r: Response = ErrorNotAcceptable("err").into();
|
let res: Response<Body> = ErrorNotAcceptable("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::NOT_ACCEPTABLE);
|
assert_eq!(res.status(), StatusCode::NOT_ACCEPTABLE);
|
||||||
|
|
||||||
let r: Response = ErrorProxyAuthenticationRequired("err").into();
|
let res: Response<Body> = ErrorProxyAuthenticationRequired("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::PROXY_AUTHENTICATION_REQUIRED);
|
assert_eq!(res.status(), StatusCode::PROXY_AUTHENTICATION_REQUIRED);
|
||||||
|
|
||||||
let r: Response = ErrorRequestTimeout("err").into();
|
let res: Response<Body> = ErrorRequestTimeout("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::REQUEST_TIMEOUT);
|
assert_eq!(res.status(), StatusCode::REQUEST_TIMEOUT);
|
||||||
|
|
||||||
let r: Response = ErrorConflict("err").into();
|
let res: Response<Body> = ErrorConflict("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::CONFLICT);
|
assert_eq!(res.status(), StatusCode::CONFLICT);
|
||||||
|
|
||||||
let r: Response = ErrorGone("err").into();
|
let res: Response<Body> = ErrorGone("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::GONE);
|
assert_eq!(res.status(), StatusCode::GONE);
|
||||||
|
|
||||||
let r: Response = ErrorLengthRequired("err").into();
|
let res: Response<Body> = ErrorLengthRequired("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::LENGTH_REQUIRED);
|
assert_eq!(res.status(), StatusCode::LENGTH_REQUIRED);
|
||||||
|
|
||||||
let r: Response = ErrorPreconditionFailed("err").into();
|
let res: Response<Body> = ErrorPreconditionFailed("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::PRECONDITION_FAILED);
|
assert_eq!(res.status(), StatusCode::PRECONDITION_FAILED);
|
||||||
|
|
||||||
let r: Response = ErrorPayloadTooLarge("err").into();
|
let res: Response<Body> = ErrorPayloadTooLarge("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::PAYLOAD_TOO_LARGE);
|
assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE);
|
||||||
|
|
||||||
let r: Response = ErrorUriTooLong("err").into();
|
let res: Response<Body> = ErrorUriTooLong("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::URI_TOO_LONG);
|
assert_eq!(res.status(), StatusCode::URI_TOO_LONG);
|
||||||
|
|
||||||
let r: Response = ErrorUnsupportedMediaType("err").into();
|
let res: Response<Body> = ErrorUnsupportedMediaType("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
|
assert_eq!(res.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
|
||||||
|
|
||||||
let r: Response = ErrorRangeNotSatisfiable("err").into();
|
let res: Response<Body> = ErrorRangeNotSatisfiable("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::RANGE_NOT_SATISFIABLE);
|
assert_eq!(res.status(), StatusCode::RANGE_NOT_SATISFIABLE);
|
||||||
|
|
||||||
let r: Response = ErrorExpectationFailed("err").into();
|
let res: Response<Body> = ErrorExpectationFailed("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::EXPECTATION_FAILED);
|
assert_eq!(res.status(), StatusCode::EXPECTATION_FAILED);
|
||||||
|
|
||||||
let r: Response = ErrorImATeapot("err").into();
|
let res: Response<Body> = ErrorImATeapot("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::IM_A_TEAPOT);
|
assert_eq!(res.status(), StatusCode::IM_A_TEAPOT);
|
||||||
|
|
||||||
let r: Response = ErrorMisdirectedRequest("err").into();
|
let res: Response<Body> = ErrorMisdirectedRequest("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::MISDIRECTED_REQUEST);
|
assert_eq!(res.status(), StatusCode::MISDIRECTED_REQUEST);
|
||||||
|
|
||||||
let r: Response = ErrorUnprocessableEntity("err").into();
|
let res: Response<Body> = ErrorUnprocessableEntity("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::UNPROCESSABLE_ENTITY);
|
assert_eq!(res.status(), StatusCode::UNPROCESSABLE_ENTITY);
|
||||||
|
|
||||||
let r: Response = ErrorLocked("err").into();
|
let res: Response<Body> = ErrorLocked("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::LOCKED);
|
assert_eq!(res.status(), StatusCode::LOCKED);
|
||||||
|
|
||||||
let r: Response = ErrorFailedDependency("err").into();
|
let res: Response<Body> = ErrorFailedDependency("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::FAILED_DEPENDENCY);
|
assert_eq!(res.status(), StatusCode::FAILED_DEPENDENCY);
|
||||||
|
|
||||||
let r: Response = ErrorUpgradeRequired("err").into();
|
let res: Response<Body> = ErrorUpgradeRequired("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::UPGRADE_REQUIRED);
|
assert_eq!(res.status(), StatusCode::UPGRADE_REQUIRED);
|
||||||
|
|
||||||
let r: Response = ErrorPreconditionRequired("err").into();
|
let res: Response<Body> = ErrorPreconditionRequired("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::PRECONDITION_REQUIRED);
|
assert_eq!(res.status(), StatusCode::PRECONDITION_REQUIRED);
|
||||||
|
|
||||||
let r: Response = ErrorTooManyRequests("err").into();
|
let res: Response<Body> = ErrorTooManyRequests("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::TOO_MANY_REQUESTS);
|
assert_eq!(res.status(), StatusCode::TOO_MANY_REQUESTS);
|
||||||
|
|
||||||
let r: Response = ErrorRequestHeaderFieldsTooLarge("err").into();
|
let res: Response<Body> = ErrorRequestHeaderFieldsTooLarge("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE);
|
assert_eq!(res.status(), StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE);
|
||||||
|
|
||||||
let r: Response = ErrorUnavailableForLegalReasons("err").into();
|
let res: Response<Body> = ErrorUnavailableForLegalReasons("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS);
|
assert_eq!(res.status(), StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS);
|
||||||
|
|
||||||
let r: Response = ErrorInternalServerError("err").into();
|
let res: Response<Body> = ErrorInternalServerError("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
|
|
||||||
let r: Response = ErrorNotImplemented("err").into();
|
let res: Response<Body> = ErrorNotImplemented("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::NOT_IMPLEMENTED);
|
assert_eq!(res.status(), StatusCode::NOT_IMPLEMENTED);
|
||||||
|
|
||||||
let r: Response = ErrorBadGateway("err").into();
|
let res: Response<Body> = ErrorBadGateway("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::BAD_GATEWAY);
|
assert_eq!(res.status(), StatusCode::BAD_GATEWAY);
|
||||||
|
|
||||||
let r: Response = ErrorServiceUnavailable("err").into();
|
let res: Response<Body> = ErrorServiceUnavailable("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::SERVICE_UNAVAILABLE);
|
assert_eq!(res.status(), StatusCode::SERVICE_UNAVAILABLE);
|
||||||
|
|
||||||
let r: Response = ErrorGatewayTimeout("err").into();
|
let res: Response<Body> = ErrorGatewayTimeout("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::GATEWAY_TIMEOUT);
|
assert_eq!(res.status(), StatusCode::GATEWAY_TIMEOUT);
|
||||||
|
|
||||||
let r: Response = ErrorHttpVersionNotSupported("err").into();
|
let res: Response<Body> = ErrorHttpVersionNotSupported("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::HTTP_VERSION_NOT_SUPPORTED);
|
assert_eq!(res.status(), StatusCode::HTTP_VERSION_NOT_SUPPORTED);
|
||||||
|
|
||||||
let r: Response = ErrorVariantAlsoNegotiates("err").into();
|
let res: Response<Body> = ErrorVariantAlsoNegotiates("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::VARIANT_ALSO_NEGOTIATES);
|
assert_eq!(res.status(), StatusCode::VARIANT_ALSO_NEGOTIATES);
|
||||||
|
|
||||||
let r: Response = ErrorInsufficientStorage("err").into();
|
let res: Response<Body> = ErrorInsufficientStorage("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::INSUFFICIENT_STORAGE);
|
assert_eq!(res.status(), StatusCode::INSUFFICIENT_STORAGE);
|
||||||
|
|
||||||
let r: Response = ErrorLoopDetected("err").into();
|
let res: Response<Body> = ErrorLoopDetected("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::LOOP_DETECTED);
|
assert_eq!(res.status(), StatusCode::LOOP_DETECTED);
|
||||||
|
|
||||||
let r: Response = ErrorNotExtended("err").into();
|
let res: Response<Body> = ErrorNotExtended("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::NOT_EXTENDED);
|
assert_eq!(res.status(), StatusCode::NOT_EXTENDED);
|
||||||
|
|
||||||
let r: Response = ErrorNetworkAuthenticationRequired("err").into();
|
let res: Response<Body> = ErrorNetworkAuthenticationRequired("err").into();
|
||||||
assert_eq!(r.status(), StatusCode::NETWORK_AUTHENTICATION_REQUIRED);
|
assert_eq!(res.status(), StatusCode::NETWORK_AUTHENTICATION_REQUIRED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -407,7 +407,7 @@ where
|
|||||||
}
|
}
|
||||||
// send expect error as response
|
// send expect error as response
|
||||||
Poll::Ready(Err(err)) => {
|
Poll::Ready(Err(err)) => {
|
||||||
let res: Response = err.into().into();
|
let res = Response::from_error(err.into());
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
self.as_mut().send_response(res, body.into_body())?;
|
self.as_mut().send_response(res, body.into_body())?;
|
||||||
}
|
}
|
||||||
@ -456,8 +456,7 @@ where
|
|||||||
// to notify the dispatcher a new state is set and the outer loop
|
// to notify the dispatcher a new state is set and the outer loop
|
||||||
// should be continue.
|
// should be continue.
|
||||||
Poll::Ready(Err(err)) => {
|
Poll::Ready(Err(err)) => {
|
||||||
let err = err.into();
|
let res = Response::from_error(err.into());
|
||||||
let res: Response = err.into();
|
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
return self.send_response(res, body.into_body());
|
return self.send_response(res, body.into_body());
|
||||||
}
|
}
|
||||||
@ -477,7 +476,7 @@ where
|
|||||||
Poll::Pending => Ok(()),
|
Poll::Pending => Ok(()),
|
||||||
// see the comment on ExpectCall state branch's Ready(Err(err)).
|
// see the comment on ExpectCall state branch's Ready(Err(err)).
|
||||||
Poll::Ready(Err(err)) => {
|
Poll::Ready(Err(err)) => {
|
||||||
let res: Response = err.into().into();
|
let res = Response::from_error(err.into());
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
self.send_response(res, body.into_body())
|
self.send_response(res, body.into_body())
|
||||||
}
|
}
|
||||||
@ -979,19 +978,20 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ok_service() -> impl Service<Request, Response = Response, Error = Error> {
|
fn ok_service() -> impl Service<Request, Response = Response<Body>, Error = Error> {
|
||||||
fn_service(|_req: Request| ready(Ok::<_, Error>(Response::Ok().finish())))
|
fn_service(|_req: Request| ready(Ok::<_, Error>(Response::Ok().finish())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn echo_path_service() -> impl Service<Request, Response = Response, Error = Error> {
|
fn echo_path_service(
|
||||||
|
) -> impl Service<Request, Response = Response<Body>, Error = Error> {
|
||||||
fn_service(|req: Request| {
|
fn_service(|req: Request| {
|
||||||
let path = req.path().as_bytes();
|
let path = req.path().as_bytes();
|
||||||
ready(Ok::<_, Error>(Response::Ok().body(Body::from_slice(path))))
|
ready(Ok::<_, Error>(Response::Ok().body(Body::from_slice(path))))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn echo_payload_service() -> impl Service<Request, Response = Response, Error = Error>
|
fn echo_payload_service(
|
||||||
{
|
) -> impl Service<Request, Response = Response<Body>, Error = Error> {
|
||||||
fn_service(|mut req: Request| {
|
fn_service(|mut req: Request| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
use futures_util::stream::StreamExt as _;
|
use futures_util::stream::StreamExt as _;
|
||||||
|
@ -252,8 +252,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(e) => {
|
Err(err) => {
|
||||||
let res: Response = e.into().into();
|
let res = Response::from_error(err.into());
|
||||||
let (res, body) = res.replace_body(());
|
let (res, body) = res.replace_body(());
|
||||||
|
|
||||||
let mut send = send.take().unwrap();
|
let mut send = send.take().unwrap();
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
|
|
||||||
use crate::response::{Response, ResponseBuilder};
|
use crate::{
|
||||||
|
body::Body,
|
||||||
|
response::{Response, ResponseBuilder},
|
||||||
|
};
|
||||||
|
|
||||||
macro_rules! static_resp {
|
macro_rules! static_resp {
|
||||||
($name:ident, $status:expr) => {
|
($name:ident, $status:expr) => {
|
||||||
@ -15,7 +18,7 @@ macro_rules! static_resp {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response<Body> {
|
||||||
static_resp!(Continue, StatusCode::CONTINUE);
|
static_resp!(Continue, StatusCode::CONTINUE);
|
||||||
static_resp!(SwitchingProtocols, StatusCode::SWITCHING_PROTOCOLS);
|
static_resp!(SwitchingProtocols, StatusCode::SWITCHING_PROTOCOLS);
|
||||||
static_resp!(Processing, StatusCode::PROCESSING);
|
static_resp!(Processing, StatusCode::PROCESSING);
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
//! | `openssl` | TLS support via [OpenSSL]. |
|
//! | `openssl` | TLS support via [OpenSSL]. |
|
||||||
//! | `rustls` | TLS support via [rustls]. |
|
//! | `rustls` | TLS support via [rustls]. |
|
||||||
//! | `compress` | Payload compression support. (Deflate, Gzip & Brotli) |
|
//! | `compress` | Payload compression support. (Deflate, Gzip & Brotli) |
|
||||||
//! | `secure-cookies` | Adds for secure cookies. Enables `cookies` feature. |
|
|
||||||
//! | `trust-dns` | Use [trust-dns] as the client DNS resolver. |
|
//! | `trust-dns` | Use [trust-dns] as the client DNS resolver. |
|
||||||
//!
|
//!
|
||||||
//! [OpenSSL]: https://crates.io/crates/openssl
|
//! [OpenSSL]: https://crates.io/crates/openssl
|
||||||
|
@ -22,7 +22,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// An HTTP Response
|
/// An HTTP Response
|
||||||
pub struct Response<B = Body> {
|
pub struct Response<B> {
|
||||||
head: BoxedResponseHead,
|
head: BoxedResponseHead,
|
||||||
body: ResponseBody<B>,
|
body: ResponseBody<B>,
|
||||||
error: Option<Error>,
|
error: Option<Error>,
|
||||||
@ -43,7 +43,7 @@ impl Response<Body> {
|
|||||||
|
|
||||||
/// Constructs a response
|
/// Constructs a response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(status: StatusCode) -> Response {
|
pub fn new(status: StatusCode) -> Response<Body> {
|
||||||
Response {
|
Response {
|
||||||
head: BoxedResponseHead::new(status),
|
head: BoxedResponseHead::new(status),
|
||||||
body: ResponseBody::Body(Body::Empty),
|
body: ResponseBody::Body(Body::Empty),
|
||||||
@ -53,7 +53,7 @@ impl Response<Body> {
|
|||||||
|
|
||||||
/// Constructs an error response
|
/// Constructs an error response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_error(error: Error) -> Response {
|
pub fn from_error(error: Error) -> Response<Body> {
|
||||||
let mut resp = error.as_response_error().error_response();
|
let mut resp = error.as_response_error().error_response();
|
||||||
if resp.head.status == StatusCode::INTERNAL_SERVER_ERROR {
|
if resp.head.status == StatusCode::INTERNAL_SERVER_ERROR {
|
||||||
error!("Internal Server Error: {:?}", error);
|
error!("Internal Server Error: {:?}", error);
|
||||||
@ -238,8 +238,8 @@ impl<B: MessageBody> fmt::Debug for Response<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Future for Response {
|
impl<B: Unpin> Future for Response<B> {
|
||||||
type Output = Result<Response, Error>;
|
type Output = Result<Response<B>, Error>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
Poll::Ready(Ok(Response {
|
Poll::Ready(Ok(Response {
|
||||||
@ -421,7 +421,7 @@ impl ResponseBuilder {
|
|||||||
///
|
///
|
||||||
/// `ResponseBuilder` can not be used after this call.
|
/// `ResponseBuilder` can not be used after this call.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn body<B: Into<Body>>(&mut self, body: B) -> Response {
|
pub fn body<B: Into<Body>>(&mut self, body: B) -> Response<Body> {
|
||||||
self.message_body(body.into())
|
self.message_body(body.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +446,7 @@ impl ResponseBuilder {
|
|||||||
///
|
///
|
||||||
/// `ResponseBuilder` can not be used after this call.
|
/// `ResponseBuilder` can not be used after this call.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn streaming<S, E>(&mut self, stream: S) -> Response
|
pub fn streaming<S, E>(&mut self, stream: S) -> Response<Body>
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
|
S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
|
||||||
E: Into<Error> + 'static,
|
E: Into<Error> + 'static,
|
||||||
@ -458,7 +458,7 @@ impl ResponseBuilder {
|
|||||||
///
|
///
|
||||||
/// `ResponseBuilder` can not be used after this call.
|
/// `ResponseBuilder` can not be used after this call.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn finish(&mut self) -> Response {
|
pub fn finish(&mut self) -> Response<Body> {
|
||||||
self.body(Body::Empty)
|
self.body(Body::Empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,7 +513,7 @@ impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Future for ResponseBuilder {
|
impl Future for ResponseBuilder {
|
||||||
type Output = Result<Response, Error>;
|
type Output = Result<Response<Body>, Error>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
Poll::Ready(Ok(self.finish()))
|
Poll::Ready(Ok(self.finish()))
|
||||||
@ -540,7 +540,7 @@ impl fmt::Debug for ResponseBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Helper converters
|
/// Helper converters
|
||||||
impl<I: Into<Response>, E: Into<Error>> From<Result<I, E>> for Response {
|
impl<I: Into<Response<Body>>, E: Into<Error>> From<Result<I, E>> for Response<Body> {
|
||||||
fn from(res: Result<I, E>) -> Self {
|
fn from(res: Result<I, E>) -> Self {
|
||||||
match res {
|
match res {
|
||||||
Ok(val) => val.into(),
|
Ok(val) => val.into(),
|
||||||
@ -549,13 +549,13 @@ impl<I: Into<Response>, E: Into<Error>> From<Result<I, E>> for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ResponseBuilder> for Response {
|
impl From<ResponseBuilder> for Response<Body> {
|
||||||
fn from(mut builder: ResponseBuilder) -> Self {
|
fn from(mut builder: ResponseBuilder) -> Self {
|
||||||
builder.finish()
|
builder.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static str> for Response {
|
impl From<&'static str> for Response<Body> {
|
||||||
fn from(val: &'static str) -> Self {
|
fn from(val: &'static str) -> Self {
|
||||||
Response::Ok()
|
Response::Ok()
|
||||||
.content_type(mime::TEXT_PLAIN_UTF_8)
|
.content_type(mime::TEXT_PLAIN_UTF_8)
|
||||||
@ -563,7 +563,7 @@ impl From<&'static str> for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&'static [u8]> for Response {
|
impl From<&'static [u8]> for Response<Body> {
|
||||||
fn from(val: &'static [u8]) -> Self {
|
fn from(val: &'static [u8]) -> Self {
|
||||||
Response::Ok()
|
Response::Ok()
|
||||||
.content_type(mime::APPLICATION_OCTET_STREAM)
|
.content_type(mime::APPLICATION_OCTET_STREAM)
|
||||||
@ -571,7 +571,7 @@ impl From<&'static [u8]> for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Response {
|
impl From<String> for Response<Body> {
|
||||||
fn from(val: String) -> Self {
|
fn from(val: String) -> Self {
|
||||||
Response::Ok()
|
Response::Ok()
|
||||||
.content_type(mime::TEXT_PLAIN_UTF_8)
|
.content_type(mime::TEXT_PLAIN_UTF_8)
|
||||||
@ -579,7 +579,7 @@ impl From<String> for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a String> for Response {
|
impl<'a> From<&'a String> for Response<Body> {
|
||||||
fn from(val: &'a String) -> Self {
|
fn from(val: &'a String) -> Self {
|
||||||
Response::Ok()
|
Response::Ok()
|
||||||
.content_type(mime::TEXT_PLAIN_UTF_8)
|
.content_type(mime::TEXT_PLAIN_UTF_8)
|
||||||
@ -587,7 +587,7 @@ impl<'a> From<&'a String> for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Bytes> for Response {
|
impl From<Bytes> for Response<Body> {
|
||||||
fn from(val: Bytes) -> Self {
|
fn from(val: Bytes) -> Self {
|
||||||
Response::Ok()
|
Response::Ok()
|
||||||
.content_type(mime::APPLICATION_OCTET_STREAM)
|
.content_type(mime::APPLICATION_OCTET_STREAM)
|
||||||
@ -595,7 +595,7 @@ impl From<Bytes> for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BytesMut> for Response {
|
impl From<BytesMut> for Response<Body> {
|
||||||
fn from(val: BytesMut) -> Self {
|
fn from(val: BytesMut) -> Self {
|
||||||
Response::Ok()
|
Response::Ok()
|
||||||
.content_type(mime::APPLICATION_OCTET_STREAM)
|
.content_type(mime::APPLICATION_OCTET_STREAM)
|
||||||
@ -653,7 +653,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_response() {
|
fn test_into_response() {
|
||||||
let resp: Response = "test".into();
|
let resp: Response<Body> = "test".into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
@ -662,7 +662,7 @@ mod tests {
|
|||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let resp: Response = b"test".as_ref().into();
|
let resp: Response<Body> = b"test".as_ref().into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
@ -671,7 +671,7 @@ mod tests {
|
|||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let resp: Response = "test".to_owned().into();
|
let resp: Response<Body> = "test".to_owned().into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
@ -680,7 +680,7 @@ mod tests {
|
|||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let resp: Response = (&"test".to_owned()).into();
|
let resp: Response<Body> = (&"test".to_owned()).into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
@ -690,7 +690,7 @@ mod tests {
|
|||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let b = Bytes::from_static(b"test");
|
let b = Bytes::from_static(b"test");
|
||||||
let resp: Response = b.into();
|
let resp: Response<Body> = b.into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
@ -700,7 +700,7 @@ mod tests {
|
|||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let b = Bytes::from_static(b"test");
|
let b = Bytes::from_static(b"test");
|
||||||
let resp: Response = b.into();
|
let resp: Response<Body> = b.into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
@ -710,7 +710,7 @@ mod tests {
|
|||||||
assert_eq!(resp.body().get_ref(), b"test");
|
assert_eq!(resp.body().get_ref(), b"test");
|
||||||
|
|
||||||
let b = BytesMut::from("test");
|
let b = BytesMut::from("test");
|
||||||
let resp: Response = b.into();
|
let resp: Response<Body> = b.into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(CONTENT_TYPE).unwrap(),
|
resp.headers().get(CONTENT_TYPE).unwrap(),
|
||||||
@ -723,7 +723,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_into_builder() {
|
fn test_into_builder() {
|
||||||
let mut resp: Response = "test".into();
|
let mut resp: Response<Body> = "test".into();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
|
||||||
resp.headers_mut().insert(
|
resp.headers_mut().insert(
|
||||||
|
@ -9,8 +9,8 @@ use derive_more::{Display, Error, From};
|
|||||||
use http::{header, Method, StatusCode};
|
use http::{header, Method, StatusCode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::ResponseError, header::HeaderValue, message::RequestHead, response::Response,
|
body::Body, error::ResponseError, header::HeaderValue, message::RequestHead,
|
||||||
ResponseBuilder,
|
response::Response, ResponseBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod codec;
|
mod codec;
|
||||||
@ -99,7 +99,7 @@ pub enum HandshakeError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseError for HandshakeError {
|
impl ResponseError for HandshakeError {
|
||||||
fn error_response(&self) -> Response {
|
fn error_response(&self) -> Response<Body> {
|
||||||
match self {
|
match self {
|
||||||
HandshakeError::GetMethodRequired => Response::MethodNotAllowed()
|
HandshakeError::GetMethodRequired => Response::MethodNotAllowed()
|
||||||
.insert_header((header::ALLOW, "GET"))
|
.insert_header((header::ALLOW, "GET"))
|
||||||
@ -320,17 +320,17 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wserror_http_response() {
|
fn test_wserror_http_response() {
|
||||||
let resp: Response = HandshakeError::GetMethodRequired.error_response();
|
let resp = HandshakeError::GetMethodRequired.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
|
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
|
||||||
let resp: Response = HandshakeError::NoWebsocketUpgrade.error_response();
|
let resp = HandshakeError::NoWebsocketUpgrade.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||||
let resp: Response = HandshakeError::NoConnectionUpgrade.error_response();
|
let resp = HandshakeError::NoConnectionUpgrade.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||||
let resp: Response = HandshakeError::NoVersionHeader.error_response();
|
let resp = HandshakeError::NoVersionHeader.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||||
let resp: Response = HandshakeError::UnsupportedVersion.error_response();
|
let resp = HandshakeError::UnsupportedVersion.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||||
let resp: Response = HandshakeError::BadWebsocketKey.error_response();
|
let resp = HandshakeError::BadWebsocketKey.error_response();
|
||||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,15 @@ extern crate tls_openssl as openssl;
|
|||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use actix_http::error::{ErrorBadRequest, PayloadError};
|
use actix_http::{
|
||||||
use actix_http::http::header::{self, HeaderName, HeaderValue};
|
body::{Body, SizedStream},
|
||||||
use actix_http::http::{Method, StatusCode, Version};
|
error::{ErrorBadRequest, PayloadError},
|
||||||
use actix_http::HttpMessage;
|
http::{
|
||||||
use actix_http::{body, Error, HttpService, Request, Response};
|
header::{self, HeaderName, HeaderValue},
|
||||||
|
Method, StatusCode, Version,
|
||||||
|
},
|
||||||
|
Error, HttpMessage, HttpService, Request, Response,
|
||||||
|
};
|
||||||
use actix_http_test::test_server;
|
use actix_http_test::test_server;
|
||||||
use actix_service::{fn_service, ServiceFactoryExt};
|
use actix_service::{fn_service, ServiceFactoryExt};
|
||||||
use actix_utils::future::{err, ok, ready};
|
use actix_utils::future::{err, ok, ready};
|
||||||
@ -328,7 +332,7 @@ async fn test_h2_body_length() {
|
|||||||
.h2(|_| {
|
.h2(|_| {
|
||||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||||
ok::<_, ()>(
|
ok::<_, ()>(
|
||||||
Response::Ok().body(body::SizedStream::new(STR.len() as u64, body)),
|
Response::Ok().body(SizedStream::new(STR.len() as u64, body)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.openssl(tls_config())
|
.openssl(tls_config())
|
||||||
@ -401,7 +405,7 @@ async fn test_h2_response_http_error_handling() {
|
|||||||
async fn test_h2_service_error() {
|
async fn test_h2_service_error() {
|
||||||
let mut srv = test_server(move || {
|
let mut srv = test_server(move || {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h2(|_| err::<Response, Error>(ErrorBadRequest("error")))
|
.h2(|_| err::<Response<Body>, Error>(ErrorBadRequest("error")))
|
||||||
.openssl(tls_config())
|
.openssl(tls_config())
|
||||||
.map_err(|_| ())
|
.map_err(|_| ())
|
||||||
})
|
})
|
||||||
|
@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
extern crate tls_rustls as rustls;
|
extern crate tls_rustls as rustls;
|
||||||
|
|
||||||
use actix_http::error::PayloadError;
|
use actix_http::{
|
||||||
use actix_http::http::header::{self, HeaderName, HeaderValue};
|
body::{Body, SizedStream},
|
||||||
use actix_http::http::{Method, StatusCode, Version};
|
error::{self, PayloadError},
|
||||||
use actix_http::{body, error, Error, HttpService, Request, Response};
|
http::{
|
||||||
|
header::{self, HeaderName, HeaderValue},
|
||||||
|
Method, StatusCode, Version,
|
||||||
|
},
|
||||||
|
Error, HttpService, Request, Response,
|
||||||
|
};
|
||||||
use actix_http_test::test_server;
|
use actix_http_test::test_server;
|
||||||
use actix_service::{fn_factory_with_config, fn_service};
|
use actix_service::{fn_factory_with_config, fn_service};
|
||||||
use actix_utils::future::{err, ok};
|
use actix_utils::future::{err, ok};
|
||||||
@ -344,7 +349,7 @@ async fn test_h2_body_length() {
|
|||||||
.h2(|_| {
|
.h2(|_| {
|
||||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||||
ok::<_, ()>(
|
ok::<_, ()>(
|
||||||
Response::Ok().body(body::SizedStream::new(STR.len() as u64, body)),
|
Response::Ok().body(SizedStream::new(STR.len() as u64, body)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.rustls(tls_config())
|
.rustls(tls_config())
|
||||||
@ -416,7 +421,7 @@ async fn test_h2_response_http_error_handling() {
|
|||||||
async fn test_h2_service_error() {
|
async fn test_h2_service_error() {
|
||||||
let mut srv = test_server(move || {
|
let mut srv = test_server(move || {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h2(|_| err::<Response, Error>(error::ErrorBadRequest("error")))
|
.h2(|_| err::<Response<Body>, Error>(error::ErrorBadRequest("error")))
|
||||||
.rustls(tls_config())
|
.rustls(tls_config())
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
@ -433,7 +438,7 @@ async fn test_h2_service_error() {
|
|||||||
async fn test_h1_service_error() {
|
async fn test_h1_service_error() {
|
||||||
let mut srv = test_server(move || {
|
let mut srv = test_server(move || {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h1(|_| err::<Response, Error>(error::ErrorBadRequest("error")))
|
.h1(|_| err::<Response<Body>, Error>(error::ErrorBadRequest("error")))
|
||||||
.rustls(tls_config())
|
.rustls(tls_config())
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
@ -13,7 +13,10 @@ use regex::Regex;
|
|||||||
|
|
||||||
use actix_http::HttpMessage;
|
use actix_http::HttpMessage;
|
||||||
use actix_http::{
|
use actix_http::{
|
||||||
body, error, http, http::header, Error, HttpService, KeepAlive, Request, Response,
|
body::{Body, SizedStream},
|
||||||
|
error, http,
|
||||||
|
http::header,
|
||||||
|
Error, HttpService, KeepAlive, Request, Response,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
@ -539,7 +542,7 @@ async fn test_h1_body_length() {
|
|||||||
.h1(|_| {
|
.h1(|_| {
|
||||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||||
ok::<_, ()>(
|
ok::<_, ()>(
|
||||||
Response::Ok().body(body::SizedStream::new(STR.len() as u64, body)),
|
Response::Ok().body(SizedStream::new(STR.len() as u64, body)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.tcp()
|
.tcp()
|
||||||
@ -646,7 +649,7 @@ async fn test_h1_response_http_error_handling() {
|
|||||||
async fn test_h1_service_error() {
|
async fn test_h1_service_error() {
|
||||||
let mut srv = test_server(|| {
|
let mut srv = test_server(|| {
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.h1(|_| err::<Response, _>(error::ErrorBadRequest("error")))
|
.h1(|_| err::<Response<Body>, _>(error::ErrorBadRequest("error")))
|
||||||
.tcp()
|
.tcp()
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use actix_http::{
|
use actix_http::{
|
||||||
|
body::Body,
|
||||||
error::InternalError,
|
error::InternalError,
|
||||||
http::{header::IntoHeaderPair, Error as HttpError, HeaderMap, StatusCode},
|
http::{header::IntoHeaderPair, Error as HttpError, HeaderMap, StatusCode},
|
||||||
};
|
};
|
||||||
@ -65,7 +66,7 @@ impl Responder for HttpResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Responder for actix_http::Response {
|
impl Responder for actix_http::Response<Body> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn respond_to(self, _: &HttpRequest) -> HttpResponse {
|
fn respond_to(self, _: &HttpRequest) -> HttpResponse {
|
||||||
HttpResponse::from(self)
|
HttpResponse::from(self)
|
||||||
|
@ -3,6 +3,7 @@ use std::{
|
|||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
fmt,
|
fmt,
|
||||||
future::Future,
|
future::Future,
|
||||||
|
mem,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
@ -287,18 +288,17 @@ impl<B> From<HttpResponse<B>> for Response<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Future for HttpResponse {
|
impl Future for HttpResponse {
|
||||||
type Output = Result<Response, Error>;
|
type Output = Result<Response<Body>, Error>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
if let Some(err) = self.error.take() {
|
if let Some(err) = self.error.take() {
|
||||||
eprintln!("httpresponse future error");
|
|
||||||
return Poll::Ready(Ok(Response::from_error(err).into_body()));
|
return Poll::Ready(Ok(Response::from_error(err).into_body()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = &mut self.res;
|
Poll::Ready(Ok(mem::replace(
|
||||||
actix_rt::pin!(res);
|
&mut self.res,
|
||||||
|
Response::new(StatusCode::default()),
|
||||||
res.poll(cx)
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,7 +680,7 @@ impl From<HttpResponseBuilder> for HttpResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<HttpResponseBuilder> for Response {
|
impl From<HttpResponseBuilder> for Response<Body> {
|
||||||
fn from(mut builder: HttpResponseBuilder) -> Self {
|
fn from(mut builder: HttpResponseBuilder) -> Self {
|
||||||
builder.finish().into()
|
builder.finish().into()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user