1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-11-27 03:51:10 +00:00

simplify payload api; add missing http error helper functions

This commit is contained in:
Nikolay Kim 2019-02-07 11:06:05 -08:00
parent fcace161c7
commit cd83553db7
21 changed files with 442 additions and 175 deletions

View file

@ -75,7 +75,6 @@ openssl = { version="0.10", optional = true }
[dev-dependencies] [dev-dependencies]
actix-rt = "0.1.0" actix-rt = "0.1.0"
actix-web = "0.7"
actix-server = { version="0.2", features=["ssl"] } actix-server = { version="0.2", features=["ssl"] }
actix-connector = { version="0.2.0", features=["ssl"] } actix-connector = { version="0.2.0", features=["ssl"] }
actix-utils = "0.2.1" actix-utils = "0.2.1"

View file

@ -18,8 +18,8 @@ fn main() {
.client_timeout(1000) .client_timeout(1000)
.client_disconnect(1000) .client_disconnect(1000)
.server_hostname("localhost") .server_hostname("localhost")
.finish(|_req: Request| { .finish(|mut req: Request| {
_req.body().limit(512).and_then(|bytes: Bytes| { req.body().limit(512).and_then(|bytes: Bytes| {
info!("request body: {:?}", bytes); info!("request body: {:?}", bytes);
let mut res = Response::Ok(); let mut res = Response::Ok();
res.header("x-head", HeaderValue::from_static("dummy value!")); res.header("x-head", HeaderValue::from_static("dummy value!"));

View file

@ -8,8 +8,8 @@ use futures::Future;
use log::info; use log::info;
use std::env; use std::env;
fn handle_request(_req: Request) -> impl Future<Item = Response, Error = Error> { fn handle_request(mut req: Request) -> impl Future<Item = Response, Error = Error> {
_req.body().limit(512).from_err().and_then(|bytes: Bytes| { req.body().limit(512).from_err().and_then(|bytes: Bytes| {
info!("request body: {:?}", bytes); info!("request body: {:?}", bytes);
let mut res = Response::Ok(); let mut res = Response::Ok();
res.header("x-head", HeaderValue::from_static("dummy value!")); res.header("x-head", HeaderValue::from_static("dummy value!"));

View file

@ -50,14 +50,14 @@ where
.into_future() .into_future()
.map_err(|(e, _)| SendRequestError::from(e)) .map_err(|(e, _)| SendRequestError::from(e))
.and_then(|(item, framed)| { .and_then(|(item, framed)| {
if let Some(res) = item { if let Some(mut res) = item {
match framed.get_codec().message_type() { match framed.get_codec().message_type() {
h1::MessageType::None => { h1::MessageType::None => {
let force_close = !framed.get_codec().keepalive(); let force_close = !framed.get_codec().keepalive();
release_connection(framed, force_close) release_connection(framed, force_close)
} }
_ => { _ => {
*res.payload.borrow_mut() = Some(Payload::stream(framed)) res.set_payload(Payload::stream(framed));
} }
} }
ok(res) ok(res)
@ -199,27 +199,10 @@ where
} }
} }
struct EmptyPayload;
impl Stream for EmptyPayload {
type Item = Bytes;
type Error = PayloadError;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
Ok(Async::Ready(None))
}
}
pub(crate) struct Payload<Io> { pub(crate) struct Payload<Io> {
framed: Option<Framed<Io, h1::ClientPayloadCodec>>, framed: Option<Framed<Io, h1::ClientPayloadCodec>>,
} }
impl Payload<()> {
pub fn empty() -> PayloadStream {
Box::new(EmptyPayload)
}
}
impl<Io: ConnectionLifetime> Payload<Io> { impl<Io: ConnectionLifetime> Payload<Io> {
pub fn stream(framed: Framed<Io, h1::ClientCodec>) -> PayloadStream { pub fn stream(framed: Framed<Io, h1::ClientCodec>) -> PayloadStream {
Box::new(Payload { Box::new(Payload {

View file

@ -1,4 +1,3 @@
use std::cell::RefCell;
use std::time; use std::time;
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
@ -111,7 +110,7 @@ where
Ok(ClientResponse { Ok(ClientResponse {
head, head,
payload: RefCell::new(Some(Box::new(Payload::new(body)))), payload: Some(Box::new(Payload::new(body))),
}) })
}) })
.from_err() .from_err()

View file

@ -268,10 +268,9 @@ impl ClientRequestBuilder {
/// ///
/// ```rust /// ```rust
/// # extern crate mime; /// # extern crate mime;
/// # extern crate actix_web; /// # extern crate actix_http;
/// # use actix_web::client::*;
/// # /// #
/// use actix_web::{client, http}; /// use actix_http::{client, http};
/// ///
/// fn main() { /// fn main() {
/// let req = client::ClientRequest::build() /// let req = client::ClientRequest::build()
@ -299,16 +298,14 @@ impl ClientRequestBuilder {
/// To override header use `set_header()` method. /// To override header use `set_header()` method.
/// ///
/// ```rust /// ```rust
/// # extern crate http; /// # extern crate actix_http;
/// # extern crate actix_web;
/// # use actix_web::client::*;
/// # /// #
/// use http::header; /// use actix_http::{client, http};
/// ///
/// fn main() { /// fn main() {
/// let req = ClientRequest::build() /// let req = client::ClientRequest::build()
/// .header("X-TEST", "value") /// .header("X-TEST", "value")
/// .header(header::CONTENT_TYPE, "application/json") /// .header(http::header::CONTENT_TYPE, "application/json")
/// .finish() /// .finish()
/// .unwrap(); /// .unwrap();
/// } /// }
@ -427,8 +424,8 @@ impl ClientRequestBuilder {
/// Set a cookie /// Set a cookie
/// ///
/// ```rust /// ```rust
/// # extern crate actix_web; /// # extern crate actix_http;
/// use actix_web::{client, http}; /// use actix_http::{client, http};
/// ///
/// fn main() { /// fn main() {
/// let req = client::ClientRequest::build() /// let req = client::ClientRequest::build()

View file

@ -1,4 +1,3 @@
use std::cell::RefCell;
use std::fmt; use std::fmt;
use bytes::Bytes; use bytes::Bytes;
@ -10,13 +9,11 @@ use crate::error::PayloadError;
use crate::httpmessage::HttpMessage; use crate::httpmessage::HttpMessage;
use crate::message::{Head, ResponseHead}; use crate::message::{Head, ResponseHead};
use super::h1proto::Payload;
/// Client Response /// Client Response
#[derive(Default)] #[derive(Default)]
pub struct ClientResponse { pub struct ClientResponse {
pub(crate) head: ResponseHead, pub(crate) head: ResponseHead,
pub(crate) payload: RefCell<Option<PayloadStream>>, pub(crate) payload: Option<PayloadStream>,
} }
impl HttpMessage for ClientResponse { impl HttpMessage for ClientResponse {
@ -27,12 +24,8 @@ impl HttpMessage for ClientResponse {
} }
#[inline] #[inline]
fn payload(self) -> Self::Stream { fn payload(&mut self) -> Option<Self::Stream> {
if let Some(payload) = self.payload.borrow_mut().take() { self.payload.take()
payload
} else {
Payload::empty()
}
} }
} }
@ -41,7 +34,7 @@ impl ClientResponse {
pub fn new() -> ClientResponse { pub fn new() -> ClientResponse {
ClientResponse { ClientResponse {
head: ResponseHead::default(), head: ResponseHead::default(),
payload: RefCell::new(None), payload: None,
} }
} }
@ -84,6 +77,11 @@ impl ClientResponse {
pub fn keep_alive(&self) -> bool { pub fn keep_alive(&self) -> bool {
self.head().keep_alive() self.head().keep_alive()
} }
/// Set response payload
pub fn set_payload(&mut self, payload: PayloadStream) {
self.payload = Some(payload);
}
} }
impl Stream for ClientResponse { impl Stream for ClientResponse {
@ -91,7 +89,7 @@ impl Stream for ClientResponse {
type Error = PayloadError; type Error = PayloadError;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
if let Some(ref mut payload) = &mut *self.payload.borrow_mut() { if let Some(ref mut payload) = self.payload {
payload.poll() payload.poll()
} else { } else {
Ok(Async::Ready(None)) Ok(Async::Ready(None))

View file

@ -344,7 +344,7 @@ pub enum PayloadError {
UnknownLength, UnknownLength,
/// Http2 payload error /// Http2 payload error
#[display(fmt = "{}", _0)] #[display(fmt = "{}", _0)]
H2Payload(h2::Error), Http2Payload(h2::Error),
} }
impl From<io::Error> for PayloadError { impl From<io::Error> for PayloadError {
@ -642,6 +642,16 @@ where
InternalError::new(err, StatusCode::UNAUTHORIZED).into() InternalError::new(err, StatusCode::UNAUTHORIZED).into()
} }
/// Helper function that creates wrapper of any error and generate
/// *PAYMENT_REQUIRED* response.
#[allow(non_snake_case)]
pub fn ErrorPaymentRequired<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::PAYMENT_REQUIRED).into()
}
/// Helper function that creates wrapper of any error and generate *FORBIDDEN* /// Helper function that creates wrapper of any error and generate *FORBIDDEN*
/// response. /// response.
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -672,6 +682,26 @@ where
InternalError::new(err, StatusCode::METHOD_NOT_ALLOWED).into() InternalError::new(err, StatusCode::METHOD_NOT_ALLOWED).into()
} }
/// Helper function that creates wrapper of any error and generate *NOT
/// ACCEPTABLE* response.
#[allow(non_snake_case)]
pub fn ErrorNotAcceptable<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::NOT_ACCEPTABLE).into()
}
/// Helper function that creates wrapper of any error and generate *PROXY
/// AUTHENTICATION REQUIRED* response.
#[allow(non_snake_case)]
pub fn ErrorProxyAuthenticationRequired<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::PROXY_AUTHENTICATION_REQUIRED).into()
}
/// Helper function that creates wrapper of any error and generate *REQUEST /// Helper function that creates wrapper of any error and generate *REQUEST
/// TIMEOUT* response. /// TIMEOUT* response.
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -702,6 +732,116 @@ where
InternalError::new(err, StatusCode::GONE).into() InternalError::new(err, StatusCode::GONE).into()
} }
/// Helper function that creates wrapper of any error and generate *LENGTH
/// REQUIRED* response.
#[allow(non_snake_case)]
pub fn ErrorLengthRequired<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::LENGTH_REQUIRED).into()
}
/// Helper function that creates wrapper of any error and generate
/// *PAYLOAD TOO LARGE* response.
#[allow(non_snake_case)]
pub fn ErrorPayloadTooLarge<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::PAYLOAD_TOO_LARGE).into()
}
/// Helper function that creates wrapper of any error and generate
/// *URI TOO LONG* response.
#[allow(non_snake_case)]
pub fn ErrorUriTooLong<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::URI_TOO_LONG).into()
}
/// Helper function that creates wrapper of any error and generate
/// *UNSUPPORTED MEDIA TYPE* response.
#[allow(non_snake_case)]
pub fn ErrorUnsupportedMediaType<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::UNSUPPORTED_MEDIA_TYPE).into()
}
/// Helper function that creates wrapper of any error and generate
/// *RANGE NOT SATISFIABLE* response.
#[allow(non_snake_case)]
pub fn ErrorRangeNotSatisfiable<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::RANGE_NOT_SATISFIABLE).into()
}
/// Helper function that creates wrapper of any error and generate
/// *IM A TEAPOT* response.
#[allow(non_snake_case)]
pub fn ErrorImATeapot<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::IM_A_TEAPOT).into()
}
/// Helper function that creates wrapper of any error and generate
/// *MISDIRECTED REQUEST* response.
#[allow(non_snake_case)]
pub fn ErrorMisdirectedRequest<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::MISDIRECTED_REQUEST).into()
}
/// Helper function that creates wrapper of any error and generate
/// *UNPROCESSABLE ENTITY* response.
#[allow(non_snake_case)]
pub fn ErrorUnprocessableEntity<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::UNPROCESSABLE_ENTITY).into()
}
/// Helper function that creates wrapper of any error and generate
/// *LOCKED* response.
#[allow(non_snake_case)]
pub fn ErrorLocked<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::LOCKED).into()
}
/// Helper function that creates wrapper of any error and generate
/// *FAILED DEPENDENCY* response.
#[allow(non_snake_case)]
pub fn ErrorFailedDependency<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::FAILED_DEPENDENCY).into()
}
/// Helper function that creates wrapper of any error and generate
/// *UPGRADE REQUIRED* response.
#[allow(non_snake_case)]
pub fn ErrorUpgradeRequired<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::UPGRADE_REQUIRED).into()
}
/// Helper function that creates wrapper of any error and generate /// Helper function that creates wrapper of any error and generate
/// *PRECONDITION FAILED* response. /// *PRECONDITION FAILED* response.
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -712,6 +852,46 @@ where
InternalError::new(err, StatusCode::PRECONDITION_FAILED).into() InternalError::new(err, StatusCode::PRECONDITION_FAILED).into()
} }
/// Helper function that creates wrapper of any error and generate
/// *PRECONDITION REQUIRED* response.
#[allow(non_snake_case)]
pub fn ErrorPreconditionRequired<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::PRECONDITION_REQUIRED).into()
}
/// Helper function that creates wrapper of any error and generate
/// *TOO MANY REQUESTS* response.
#[allow(non_snake_case)]
pub fn ErrorTooManyRequests<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::TOO_MANY_REQUESTS).into()
}
/// Helper function that creates wrapper of any error and generate
/// *REQUEST HEADER FIELDS TOO LARGE* response.
#[allow(non_snake_case)]
pub fn ErrorRequestHeaderFieldsTooLarge<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE).into()
}
/// Helper function that creates wrapper of any error and generate
/// *UNAVAILABLE FOR LEGAL REASONS* response.
#[allow(non_snake_case)]
pub fn ErrorUnavailableForLegalReasons<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS).into()
}
/// Helper function that creates wrapper of any error and generate /// Helper function that creates wrapper of any error and generate
/// *EXPECTATION FAILED* response. /// *EXPECTATION FAILED* response.
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -772,6 +952,66 @@ where
InternalError::new(err, StatusCode::GATEWAY_TIMEOUT).into() InternalError::new(err, StatusCode::GATEWAY_TIMEOUT).into()
} }
/// Helper function that creates wrapper of any error and
/// generate *HTTP VERSION NOT SUPPORTED* response.
#[allow(non_snake_case)]
pub fn ErrorHttpVersionNotSupported<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::HTTP_VERSION_NOT_SUPPORTED).into()
}
/// Helper function that creates wrapper of any error and
/// generate *VARIANT ALSO NEGOTIATES* response.
#[allow(non_snake_case)]
pub fn ErrorVariantAlsoNegotiates<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::VARIANT_ALSO_NEGOTIATES).into()
}
/// Helper function that creates wrapper of any error and
/// generate *INSUFFICIENT STORAGE* response.
#[allow(non_snake_case)]
pub fn ErrorInsufficientStorage<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::INSUFFICIENT_STORAGE).into()
}
/// Helper function that creates wrapper of any error and
/// generate *LOOP DETECTED* response.
#[allow(non_snake_case)]
pub fn ErrorLoopDetected<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::LOOP_DETECTED).into()
}
/// Helper function that creates wrapper of any error and
/// generate *NOT EXTENDED* response.
#[allow(non_snake_case)]
pub fn ErrorNotExtended<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::NOT_EXTENDED).into()
}
/// Helper function that creates wrapper of any error and
/// generate *NETWORK AUTHENTICATION REQUIRED* response.
#[allow(non_snake_case)]
pub fn ErrorNetworkAuthenticationRequired<T>(err: T) -> Error
where
T: fmt::Debug + fmt::Display + 'static,
{
InternalError::new(err, StatusCode::NETWORK_AUTHENTICATION_REQUIRED).into()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -926,6 +1166,9 @@ mod tests {
let r: Response = ErrorUnauthorized("err").into(); let r: Response = ErrorUnauthorized("err").into();
assert_eq!(r.status(), StatusCode::UNAUTHORIZED); assert_eq!(r.status(), StatusCode::UNAUTHORIZED);
let r: Response = ErrorPaymentRequired("err").into();
assert_eq!(r.status(), StatusCode::PAYMENT_REQUIRED);
let r: Response = ErrorForbidden("err").into(); let r: Response = ErrorForbidden("err").into();
assert_eq!(r.status(), StatusCode::FORBIDDEN); assert_eq!(r.status(), StatusCode::FORBIDDEN);
@ -935,6 +1178,12 @@ mod tests {
let r: Response = ErrorMethodNotAllowed("err").into(); let r: Response = ErrorMethodNotAllowed("err").into();
assert_eq!(r.status(), StatusCode::METHOD_NOT_ALLOWED); assert_eq!(r.status(), StatusCode::METHOD_NOT_ALLOWED);
let r: Response = ErrorNotAcceptable("err").into();
assert_eq!(r.status(), StatusCode::NOT_ACCEPTABLE);
let r: Response = ErrorProxyAuthenticationRequired("err").into();
assert_eq!(r.status(), StatusCode::PROXY_AUTHENTICATION_REQUIRED);
let r: Response = ErrorRequestTimeout("err").into(); let r: Response = ErrorRequestTimeout("err").into();
assert_eq!(r.status(), StatusCode::REQUEST_TIMEOUT); assert_eq!(r.status(), StatusCode::REQUEST_TIMEOUT);
@ -944,12 +1193,57 @@ mod tests {
let r: Response = ErrorGone("err").into(); let r: Response = ErrorGone("err").into();
assert_eq!(r.status(), StatusCode::GONE); assert_eq!(r.status(), StatusCode::GONE);
let r: Response = ErrorLengthRequired("err").into();
assert_eq!(r.status(), StatusCode::LENGTH_REQUIRED);
let r: Response = ErrorPreconditionFailed("err").into(); let r: Response = ErrorPreconditionFailed("err").into();
assert_eq!(r.status(), StatusCode::PRECONDITION_FAILED); assert_eq!(r.status(), StatusCode::PRECONDITION_FAILED);
let r: Response = ErrorPayloadTooLarge("err").into();
assert_eq!(r.status(), StatusCode::PAYLOAD_TOO_LARGE);
let r: Response = ErrorUriTooLong("err").into();
assert_eq!(r.status(), StatusCode::URI_TOO_LONG);
let r: Response = ErrorUnsupportedMediaType("err").into();
assert_eq!(r.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
let r: Response = ErrorRangeNotSatisfiable("err").into();
assert_eq!(r.status(), StatusCode::RANGE_NOT_SATISFIABLE);
let r: Response = ErrorExpectationFailed("err").into(); let r: Response = ErrorExpectationFailed("err").into();
assert_eq!(r.status(), StatusCode::EXPECTATION_FAILED); assert_eq!(r.status(), StatusCode::EXPECTATION_FAILED);
let r: Response = ErrorImATeapot("err").into();
assert_eq!(r.status(), StatusCode::IM_A_TEAPOT);
let r: Response = ErrorMisdirectedRequest("err").into();
assert_eq!(r.status(), StatusCode::MISDIRECTED_REQUEST);
let r: Response = ErrorUnprocessableEntity("err").into();
assert_eq!(r.status(), StatusCode::UNPROCESSABLE_ENTITY);
let r: Response = ErrorLocked("err").into();
assert_eq!(r.status(), StatusCode::LOCKED);
let r: Response = ErrorFailedDependency("err").into();
assert_eq!(r.status(), StatusCode::FAILED_DEPENDENCY);
let r: Response = ErrorUpgradeRequired("err").into();
assert_eq!(r.status(), StatusCode::UPGRADE_REQUIRED);
let r: Response = ErrorPreconditionRequired("err").into();
assert_eq!(r.status(), StatusCode::PRECONDITION_REQUIRED);
let r: Response = ErrorTooManyRequests("err").into();
assert_eq!(r.status(), StatusCode::TOO_MANY_REQUESTS);
let r: Response = ErrorRequestHeaderFieldsTooLarge("err").into();
assert_eq!(r.status(), StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE);
let r: Response = ErrorUnavailableForLegalReasons("err").into();
assert_eq!(r.status(), StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS);
let r: Response = ErrorInternalServerError("err").into(); let r: Response = ErrorInternalServerError("err").into();
assert_eq!(r.status(), StatusCode::INTERNAL_SERVER_ERROR); assert_eq!(r.status(), StatusCode::INTERNAL_SERVER_ERROR);
@ -964,5 +1258,23 @@ mod tests {
let r: Response = ErrorGatewayTimeout("err").into(); let r: Response = ErrorGatewayTimeout("err").into();
assert_eq!(r.status(), StatusCode::GATEWAY_TIMEOUT); assert_eq!(r.status(), StatusCode::GATEWAY_TIMEOUT);
let r: Response = ErrorHttpVersionNotSupported("err").into();
assert_eq!(r.status(), StatusCode::HTTP_VERSION_NOT_SUPPORTED);
let r: Response = ErrorVariantAlsoNegotiates("err").into();
assert_eq!(r.status(), StatusCode::VARIANT_ALSO_NEGOTIATES);
let r: Response = ErrorInsufficientStorage("err").into();
assert_eq!(r.status(), StatusCode::INSUFFICIENT_STORAGE);
let r: Response = ErrorLoopDetected("err").into();
assert_eq!(r.status(), StatusCode::LOOP_DETECTED);
let r: Response = ErrorNotExtended("err").into();
assert_eq!(r.status(), StatusCode::NOT_EXTENDED);
let r: Response = ErrorNetworkAuthenticationRequired("err").into();
assert_eq!(r.status(), StatusCode::NETWORK_AUTHENTICATION_REQUIRED);
} }
} }

View file

@ -14,11 +14,11 @@ use crate::body::{Body, BodyLength, MessageBody, ResponseBody};
use crate::config::ServiceConfig; use crate::config::ServiceConfig;
use crate::error::DispatchError; use crate::error::DispatchError;
use crate::error::{ParseError, PayloadError}; use crate::error::{ParseError, PayloadError};
use crate::payload::{Payload, PayloadSender, PayloadStatus, PayloadWriter};
use crate::request::Request; use crate::request::Request;
use crate::response::Response; use crate::response::Response;
use super::codec::Codec; use super::codec::Codec;
use super::payload::{Payload, PayloadSender, PayloadStatus, PayloadWriter};
use super::{H1ServiceResult, Message, MessageType}; use super::{H1ServiceResult, Message, MessageType};
const MAX_PIPELINED_MESSAGES: usize = 16; const MAX_PIPELINED_MESSAGES: usize = 16;

View file

@ -9,11 +9,13 @@ mod codec;
mod decoder; mod decoder;
mod dispatcher; mod dispatcher;
mod encoder; mod encoder;
mod payload;
mod service; mod service;
pub use self::client::{ClientCodec, ClientPayloadCodec}; pub use self::client::{ClientCodec, ClientPayloadCodec};
pub use self::codec::Codec; pub use self::codec::Codec;
pub use self::dispatcher::Dispatcher; pub use self::dispatcher::Dispatcher;
pub use self::payload::{Payload, PayloadBuffer};
pub use self::service::{H1Service, H1ServiceHandler, OneRequest}; pub use self::service::{H1Service, H1ServiceHandler, OneRequest};
use crate::request::Request; use crate::request::Request;

View file

@ -54,6 +54,7 @@ impl Response {
STATIC_RESP!(Gone, StatusCode::GONE); STATIC_RESP!(Gone, StatusCode::GONE);
STATIC_RESP!(LengthRequired, StatusCode::LENGTH_REQUIRED); STATIC_RESP!(LengthRequired, StatusCode::LENGTH_REQUIRED);
STATIC_RESP!(PreconditionFailed, StatusCode::PRECONDITION_FAILED); STATIC_RESP!(PreconditionFailed, StatusCode::PRECONDITION_FAILED);
STATIC_RESP!(PreconditionRequired, StatusCode::PRECONDITION_REQUIRED);
STATIC_RESP!(PayloadTooLarge, StatusCode::PAYLOAD_TOO_LARGE); STATIC_RESP!(PayloadTooLarge, StatusCode::PAYLOAD_TOO_LARGE);
STATIC_RESP!(UriTooLong, StatusCode::URI_TOO_LONG); STATIC_RESP!(UriTooLong, StatusCode::URI_TOO_LONG);
STATIC_RESP!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE); STATIC_RESP!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE);

View file

@ -25,7 +25,7 @@ pub trait HttpMessage: Sized {
fn headers(&self) -> &HeaderMap; fn headers(&self) -> &HeaderMap;
/// Message payload stream /// Message payload stream
fn payload(self) -> Self::Stream; fn payload(&mut self) -> Option<Self::Stream>;
#[doc(hidden)] #[doc(hidden)]
/// Get a header /// Get a header
@ -128,7 +128,7 @@ pub trait HttpMessage: Sized {
/// } /// }
/// # fn main() {} /// # fn main() {}
/// ``` /// ```
fn body(self) -> MessageBody<Self> { fn body(&mut self) -> MessageBody<Self> {
MessageBody::new(self) MessageBody::new(self)
} }
@ -162,7 +162,7 @@ pub trait HttpMessage: Sized {
/// } /// }
/// # fn main() {} /// # fn main() {}
/// ``` /// ```
fn urlencoded<T: DeserializeOwned>(self) -> UrlEncoded<Self, T> { fn urlencoded<T: DeserializeOwned>(&mut self) -> UrlEncoded<Self, T> {
UrlEncoded::new(self) UrlEncoded::new(self)
} }
@ -198,19 +198,19 @@ pub trait HttpMessage: Sized {
/// } /// }
/// # fn main() {} /// # fn main() {}
/// ``` /// ```
fn json<T: DeserializeOwned>(self) -> JsonBody<Self, T> { fn json<T: DeserializeOwned>(&mut self) -> JsonBody<Self, T> {
JsonBody::new(self) JsonBody::new(self)
} }
/// Return stream of lines. /// Return stream of lines.
fn readlines(self) -> Readlines<Self> { fn readlines(&mut self) -> Readlines<Self> {
Readlines::new(self) Readlines::new(self)
} }
} }
/// Stream to read request line by line. /// Stream to read request line by line.
pub struct Readlines<T: HttpMessage> { pub struct Readlines<T: HttpMessage> {
stream: T::Stream, stream: Option<T::Stream>,
buff: BytesMut, buff: BytesMut,
limit: usize, limit: usize,
checked_buff: bool, checked_buff: bool,
@ -220,7 +220,7 @@ pub struct Readlines<T: HttpMessage> {
impl<T: HttpMessage> Readlines<T> { impl<T: HttpMessage> Readlines<T> {
/// Create a new stream to read request line by line. /// Create a new stream to read request line by line.
fn new(req: T) -> Self { fn new(req: &mut T) -> Self {
let encoding = match req.encoding() { let encoding = match req.encoding() {
Ok(enc) => enc, Ok(enc) => enc,
Err(err) => return Self::err(req, err.into()), Err(err) => return Self::err(req, err.into()),
@ -242,7 +242,7 @@ impl<T: HttpMessage> Readlines<T> {
self self
} }
fn err(req: T, err: ReadlinesError) -> Self { fn err(req: &mut T, err: ReadlinesError) -> Self {
Readlines { Readlines {
stream: req.payload(), stream: req.payload(),
buff: BytesMut::new(), buff: BytesMut::new(),
@ -292,61 +292,65 @@ impl<T: HttpMessage + 'static> Stream for Readlines<T> {
self.checked_buff = true; self.checked_buff = true;
} }
// poll req for more bytes // poll req for more bytes
match self.stream.poll() { if let Some(ref mut stream) = self.stream {
Ok(Async::Ready(Some(mut bytes))) => { match stream.poll() {
// check if there is a newline in bytes Ok(Async::Ready(Some(mut bytes))) => {
let mut found: Option<usize> = None; // check if there is a newline in bytes
for (ind, b) in bytes.iter().enumerate() { let mut found: Option<usize> = None;
if *b == b'\n' { for (ind, b) in bytes.iter().enumerate() {
found = Some(ind); if *b == b'\n' {
break; found = Some(ind);
break;
}
} }
if let Some(ind) = found {
// check if line is longer than limit
if ind + 1 > self.limit {
return Err(ReadlinesError::LimitOverflow);
}
let enc: *const Encoding = self.encoding as *const Encoding;
let line = if enc == UTF_8 {
str::from_utf8(&bytes.split_to(ind + 1))
.map_err(|_| ReadlinesError::EncodingError)?
.to_owned()
} else {
self.encoding
.decode(&bytes.split_to(ind + 1), DecoderTrap::Strict)
.map_err(|_| ReadlinesError::EncodingError)?
};
// extend buffer with rest of the bytes;
self.buff.extend_from_slice(&bytes);
self.checked_buff = false;
return Ok(Async::Ready(Some(line)));
}
self.buff.extend_from_slice(&bytes);
Ok(Async::NotReady)
} }
if let Some(ind) = found { Ok(Async::NotReady) => Ok(Async::NotReady),
// check if line is longer than limit Ok(Async::Ready(None)) => {
if ind + 1 > self.limit { if self.buff.is_empty() {
return Ok(Async::Ready(None));
}
if self.buff.len() > self.limit {
return Err(ReadlinesError::LimitOverflow); return Err(ReadlinesError::LimitOverflow);
} }
let enc: *const Encoding = self.encoding as *const Encoding; let enc: *const Encoding = self.encoding as *const Encoding;
let line = if enc == UTF_8 { let line = if enc == UTF_8 {
str::from_utf8(&bytes.split_to(ind + 1)) str::from_utf8(&self.buff)
.map_err(|_| ReadlinesError::EncodingError)? .map_err(|_| ReadlinesError::EncodingError)?
.to_owned() .to_owned()
} else { } else {
self.encoding self.encoding
.decode(&bytes.split_to(ind + 1), DecoderTrap::Strict) .decode(&self.buff, DecoderTrap::Strict)
.map_err(|_| ReadlinesError::EncodingError)? .map_err(|_| ReadlinesError::EncodingError)?
}; };
// extend buffer with rest of the bytes; self.buff.clear();
self.buff.extend_from_slice(&bytes); Ok(Async::Ready(Some(line)))
self.checked_buff = false;
return Ok(Async::Ready(Some(line)));
} }
self.buff.extend_from_slice(&bytes); Err(e) => Err(ReadlinesError::from(e)),
Ok(Async::NotReady)
} }
Ok(Async::NotReady) => Ok(Async::NotReady), } else {
Ok(Async::Ready(None)) => { Ok(Async::Ready(None))
if self.buff.is_empty() {
return Ok(Async::Ready(None));
}
if self.buff.len() > self.limit {
return Err(ReadlinesError::LimitOverflow);
}
let enc: *const Encoding = self.encoding as *const Encoding;
let line = if enc == UTF_8 {
str::from_utf8(&self.buff)
.map_err(|_| ReadlinesError::EncodingError)?
.to_owned()
} else {
self.encoding
.decode(&self.buff, DecoderTrap::Strict)
.map_err(|_| ReadlinesError::EncodingError)?
};
self.buff.clear();
Ok(Async::Ready(Some(line)))
}
Err(e) => Err(ReadlinesError::from(e)),
} }
} }
} }
@ -362,7 +366,7 @@ pub struct MessageBody<T: HttpMessage> {
impl<T: HttpMessage> MessageBody<T> { impl<T: HttpMessage> MessageBody<T> {
/// Create `MessageBody` for request. /// Create `MessageBody` for request.
pub fn new(req: T) -> MessageBody<T> { pub fn new(req: &mut T) -> MessageBody<T> {
let mut len = None; let mut len = None;
if let Some(l) = req.headers().get(header::CONTENT_LENGTH) { if let Some(l) = req.headers().get(header::CONTENT_LENGTH) {
if let Ok(s) = l.to_str() { if let Ok(s) = l.to_str() {
@ -379,7 +383,7 @@ impl<T: HttpMessage> MessageBody<T> {
MessageBody { MessageBody {
limit: 262_144, limit: 262_144,
length: len, length: len,
stream: Some(req.payload()), stream: req.payload(),
fut: None, fut: None,
err: None, err: None,
} }
@ -424,6 +428,10 @@ where
} }
} }
if self.stream.is_none() {
return Ok(Async::Ready(Bytes::new()));
}
// future // future
let limit = self.limit; let limit = self.limit;
self.fut = Some(Box::new( self.fut = Some(Box::new(
@ -457,7 +465,7 @@ pub struct UrlEncoded<T: HttpMessage, U> {
impl<T: HttpMessage, U> UrlEncoded<T, U> { impl<T: HttpMessage, U> UrlEncoded<T, U> {
/// Create a new future to URL encode a request /// Create a new future to URL encode a request
pub fn new(req: T) -> UrlEncoded<T, U> { pub fn new(req: &mut T) -> UrlEncoded<T, U> {
// check content type // check content type
if req.content_type().to_lowercase() != "application/x-www-form-urlencoded" { if req.content_type().to_lowercase() != "application/x-www-form-urlencoded" {
return Self::err(UrlencodedError::ContentType); return Self::err(UrlencodedError::ContentType);
@ -482,7 +490,7 @@ impl<T: HttpMessage, U> UrlEncoded<T, U> {
UrlEncoded { UrlEncoded {
encoding, encoding,
stream: Some(req.payload()), stream: req.payload(),
limit: 262_144, limit: 262_144,
length: len, length: len,
fut: None, fut: None,
@ -694,7 +702,7 @@ mod tests {
#[test] #[test]
fn test_urlencoded_error() { fn test_urlencoded_error() {
let req = TestRequest::with_header( let mut req = TestRequest::with_header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
"application/x-www-form-urlencoded", "application/x-www-form-urlencoded",
) )
@ -705,7 +713,7 @@ mod tests {
UrlencodedError::UnknownLength UrlencodedError::UnknownLength
); );
let req = TestRequest::with_header( let mut req = TestRequest::with_header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
"application/x-www-form-urlencoded", "application/x-www-form-urlencoded",
) )
@ -716,7 +724,7 @@ mod tests {
UrlencodedError::Overflow UrlencodedError::Overflow
); );
let req = TestRequest::with_header(header::CONTENT_TYPE, "text/plain") let mut req = TestRequest::with_header(header::CONTENT_TYPE, "text/plain")
.header(header::CONTENT_LENGTH, "10") .header(header::CONTENT_LENGTH, "10")
.finish(); .finish();
assert_eq!( assert_eq!(
@ -727,7 +735,7 @@ mod tests {
#[test] #[test]
fn test_urlencoded() { fn test_urlencoded() {
let req = TestRequest::with_header( let mut req = TestRequest::with_header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
"application/x-www-form-urlencoded", "application/x-www-form-urlencoded",
) )
@ -743,7 +751,7 @@ mod tests {
}) })
); );
let req = TestRequest::with_header( let mut req = TestRequest::with_header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
"application/x-www-form-urlencoded; charset=utf-8", "application/x-www-form-urlencoded; charset=utf-8",
) )
@ -762,19 +770,20 @@ mod tests {
#[test] #[test]
fn test_message_body() { fn test_message_body() {
let req = TestRequest::with_header(header::CONTENT_LENGTH, "xxxx").finish(); let mut req = TestRequest::with_header(header::CONTENT_LENGTH, "xxxx").finish();
match req.body().poll().err().unwrap() { match req.body().poll().err().unwrap() {
PayloadError::UnknownLength => (), PayloadError::UnknownLength => (),
_ => unreachable!("error"), _ => unreachable!("error"),
} }
let req = TestRequest::with_header(header::CONTENT_LENGTH, "1000000").finish(); let mut req =
TestRequest::with_header(header::CONTENT_LENGTH, "1000000").finish();
match req.body().poll().err().unwrap() { match req.body().poll().err().unwrap() {
PayloadError::Overflow => (), PayloadError::Overflow => (),
_ => unreachable!("error"), _ => unreachable!("error"),
} }
let req = TestRequest::default() let mut req = TestRequest::default()
.set_payload(Bytes::from_static(b"test")) .set_payload(Bytes::from_static(b"test"))
.finish(); .finish();
match req.body().poll().ok().unwrap() { match req.body().poll().ok().unwrap() {
@ -782,7 +791,7 @@ mod tests {
_ => unreachable!("error"), _ => unreachable!("error"),
} }
let req = TestRequest::default() let mut req = TestRequest::default()
.set_payload(Bytes::from_static(b"11111111111111")) .set_payload(Bytes::from_static(b"11111111111111"))
.finish(); .finish();
match req.body().limit(5).poll().err().unwrap() { match req.body().limit(5).poll().err().unwrap() {
@ -793,14 +802,14 @@ mod tests {
#[test] #[test]
fn test_readlines() { fn test_readlines() {
let req = TestRequest::default() let mut req = TestRequest::default()
.set_payload(Bytes::from_static( .set_payload(Bytes::from_static(
b"Lorem Ipsum is simply dummy text of the printing and typesetting\n\ b"Lorem Ipsum is simply dummy text of the printing and typesetting\n\
industry. Lorem Ipsum has been the industry's standard dummy\n\ industry. Lorem Ipsum has been the industry's standard dummy\n\
Contrary to popular belief, Lorem Ipsum is not simply random text.", Contrary to popular belief, Lorem Ipsum is not simply random text.",
)) ))
.finish(); .finish();
let mut r = Readlines::new(req); let mut r = Readlines::new(&mut req);
match r.poll().ok().unwrap() { match r.poll().ok().unwrap() {
Async::Ready(Some(s)) => assert_eq!( Async::Ready(Some(s)) => assert_eq!(
s, s,

View file

@ -50,7 +50,7 @@ pub struct JsonBody<T: HttpMessage, U: DeserializeOwned> {
impl<T: HttpMessage, U: DeserializeOwned> JsonBody<T, U> { impl<T: HttpMessage, U: DeserializeOwned> JsonBody<T, U> {
/// Create `JsonBody` for request. /// Create `JsonBody` for request.
pub fn new(req: T) -> Self { pub fn new(req: &mut T) -> Self {
// check content-type // check content-type
let json = if let Ok(Some(mime)) = req.mime_type() { let json = if let Ok(Some(mime)) = req.mime_type() {
mime.subtype() == mime::JSON || mime.suffix() == Some(mime::JSON) mime.subtype() == mime::JSON || mime.suffix() == Some(mime::JSON)
@ -79,7 +79,7 @@ impl<T: HttpMessage, U: DeserializeOwned> JsonBody<T, U> {
JsonBody { JsonBody {
limit: 262_144, limit: 262_144,
length: len, length: len,
stream: Some(req.payload()), stream: req.payload(),
fut: None, fut: None,
err: None, err: None,
} }
@ -164,11 +164,11 @@ mod tests {
#[test] #[test]
fn test_json_body() { fn test_json_body() {
let req = TestRequest::default().finish(); let mut req = TestRequest::default().finish();
let mut json = req.json::<MyObject>(); let mut json = req.json::<MyObject>();
assert_eq!(json.poll().err().unwrap(), JsonPayloadError::ContentType); assert_eq!(json.poll().err().unwrap(), JsonPayloadError::ContentType);
let req = TestRequest::default() let mut req = TestRequest::default()
.header( .header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
header::HeaderValue::from_static("application/text"), header::HeaderValue::from_static("application/text"),
@ -177,7 +177,7 @@ mod tests {
let mut json = req.json::<MyObject>(); let mut json = req.json::<MyObject>();
assert_eq!(json.poll().err().unwrap(), JsonPayloadError::ContentType); assert_eq!(json.poll().err().unwrap(), JsonPayloadError::ContentType);
let req = TestRequest::default() let mut req = TestRequest::default()
.header( .header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"), header::HeaderValue::from_static("application/json"),
@ -190,7 +190,7 @@ mod tests {
let mut json = req.json::<MyObject>().limit(100); let mut json = req.json::<MyObject>().limit(100);
assert_eq!(json.poll().err().unwrap(), JsonPayloadError::Overflow); assert_eq!(json.poll().err().unwrap(), JsonPayloadError::Overflow);
let req = TestRequest::default() let mut req = TestRequest::default()
.header( .header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"), header::HeaderValue::from_static("application/json"),

View file

@ -78,7 +78,6 @@ mod httpcodes;
mod httpmessage; mod httpmessage;
mod json; mod json;
mod message; mod message;
mod payload;
mod request; mod request;
mod response; mod response;
mod service; mod service;
@ -111,7 +110,6 @@ pub mod dev {
pub use crate::httpmessage::{MessageBody, Readlines, UrlEncoded}; pub use crate::httpmessage::{MessageBody, Readlines, UrlEncoded};
pub use crate::json::JsonBody; pub use crate::json::JsonBody;
pub use crate::payload::{Payload, PayloadBuffer};
pub use crate::response::ResponseBuilder; pub use crate::response::ResponseBuilder;
} }

View file

@ -10,7 +10,8 @@ use crate::error::PayloadError;
use crate::extensions::Extensions; use crate::extensions::Extensions;
use crate::httpmessage::HttpMessage; use crate::httpmessage::HttpMessage;
use crate::message::{Message, MessagePool, RequestHead}; use crate::message::{Message, MessagePool, RequestHead};
use crate::payload::Payload;
use crate::h1::Payload;
/// Request /// Request
pub struct Request<P = Payload> { pub struct Request<P = Payload> {
@ -29,8 +30,8 @@ where
} }
#[inline] #[inline]
fn payload(mut self) -> P { fn payload(&mut self) -> Option<P> {
self.payload.take().unwrap() self.payload.take()
} }
} }
@ -62,9 +63,9 @@ impl<Payload> Request<Payload> {
} }
/// Take request's payload /// Take request's payload
pub fn take_payload(mut self) -> (Payload, Request<()>) { pub fn take_payload(mut self) -> (Option<Payload>, Request<()>) {
( (
self.payload.take().unwrap(), self.payload.take(),
Request { Request {
payload: Some(()), payload: Some(()),
inner: self.inner.clone(), inner: self.inner.clone(),

View file

@ -1,3 +1,5 @@
use h2::RecvStream;
mod senderror; mod senderror;
pub use self::senderror::{SendError, SendResponse}; pub use self::senderror::{SendError, SendResponse};

View file

@ -6,8 +6,8 @@ use cookie::Cookie;
use http::header::HeaderName; use http::header::HeaderName;
use http::{HeaderMap, HttpTryFrom, Method, Uri, Version}; use http::{HeaderMap, HttpTryFrom, Method, Uri, Version};
use crate::h1::Payload;
use crate::header::{Header, IntoHeaderValue}; use crate::header::{Header, IntoHeaderValue};
use crate::payload::Payload;
use crate::Request; use crate::Request;
/// Test `Request` builder /// Test `Request` builder

View file

@ -47,7 +47,7 @@ fn test_h1_v2() {
assert!(repr.contains("ClientRequest")); assert!(repr.contains("ClientRequest"));
assert!(repr.contains("x-test")); assert!(repr.contains("x-test"));
let response = srv.block_on(request.send(&mut connector)).unwrap(); let mut response = srv.block_on(request.send(&mut connector)).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
@ -55,7 +55,7 @@ fn test_h1_v2() {
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
let request = srv.post().finish().unwrap(); let request = srv.post().finish().unwrap();
let response = srv.block_on(request.send(&mut connector)).unwrap(); let mut response = srv.block_on(request.send(&mut connector)).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response

View file

@ -89,7 +89,7 @@ fn test_h2_body() -> std::io::Result<()> {
.map_err(|e| println!("Openssl error: {}", e)) .map_err(|e| println!("Openssl error: {}", e))
.and_then( .and_then(
h2::H2Service::build() h2::H2Service::build()
.finish(|req: Request<_>| { .finish(|mut req: Request<_>| {
req.body() req.body()
.limit(1024 * 1024) .limit(1024 * 1024)
.and_then(|body| Ok(Response::Ok().body(body))) .and_then(|body| Ok(Response::Ok().body(body)))
@ -101,7 +101,7 @@ fn test_h2_body() -> std::io::Result<()> {
let req = client::ClientRequest::get(srv.surl("/")) let req = client::ClientRequest::get(srv.surl("/"))
.body(data.clone()) .body(data.clone())
.unwrap(); .unwrap();
let response = srv.send_request(req).unwrap(); let mut response = srv.send_request(req).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let body = srv.block_on(response.body().limit(1024 * 1024)).unwrap(); let body = srv.block_on(response.body().limit(1024 * 1024)).unwrap();
@ -350,7 +350,7 @@ fn test_headers() {
let req = srv.get().finish().unwrap(); let req = srv.get().finish().unwrap();
let response = srv.block_on(req.send(&mut connector)).unwrap(); let mut response = srv.block_on(req.send(&mut connector)).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
@ -387,7 +387,7 @@ fn test_body() {
}); });
let req = srv.get().finish().unwrap(); let req = srv.get().finish().unwrap();
let response = srv.send_request(req).unwrap(); let mut response = srv.send_request(req).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
@ -402,7 +402,7 @@ fn test_head_empty() {
}); });
let req = client::ClientRequest::head(srv.url("/")).finish().unwrap(); let req = client::ClientRequest::head(srv.url("/")).finish().unwrap();
let response = srv.send_request(req).unwrap(); let mut response = srv.send_request(req).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
{ {
@ -428,7 +428,7 @@ fn test_head_binary() {
}); });
let req = client::ClientRequest::head(srv.url("/")).finish().unwrap(); let req = client::ClientRequest::head(srv.url("/")).finish().unwrap();
let response = srv.send_request(req).unwrap(); let mut response = srv.send_request(req).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
{ {
@ -477,7 +477,7 @@ fn test_body_length() {
}); });
let req = srv.get().finish().unwrap(); let req = srv.get().finish().unwrap();
let response = srv.send_request(req).unwrap(); let mut response = srv.send_request(req).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
@ -496,7 +496,7 @@ fn test_body_chunked_explicit() {
}); });
let req = srv.get().finish().unwrap(); let req = srv.get().finish().unwrap();
let response = srv.send_request(req).unwrap(); let mut response = srv.send_request(req).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
@ -517,7 +517,7 @@ fn test_body_chunked_implicit() {
}); });
let req = srv.get().finish().unwrap(); let req = srv.get().finish().unwrap();
let response = srv.send_request(req).unwrap(); let mut response = srv.send_request(req).unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
@ -540,7 +540,7 @@ fn test_response_http_error_handling() {
}); });
let req = srv.get().finish().unwrap(); let req = srv.get().finish().unwrap();
let response = srv.send_request(req).unwrap(); let mut response = srv.send_request(req).unwrap();
assert_eq!(response.status(), http::StatusCode::INTERNAL_SERVER_ERROR); assert_eq!(response.status(), http::StatusCode::INTERNAL_SERVER_ERROR);
// read response // read response

View file

@ -5,7 +5,6 @@ use actix_http_test::TestServer;
use actix_service::NewService; use actix_service::NewService;
use actix_utils::framed::IntoFramed; use actix_utils::framed::IntoFramed;
use actix_utils::stream::TakeItem; use actix_utils::stream::TakeItem;
use actix_web::ws as web_ws;
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures::future::{lazy, ok, Either}; use futures::future::{lazy, ok, Either};
use futures::{Future, Sink, Stream}; use futures::{Future, Sink, Stream};
@ -105,37 +104,4 @@ fn test_simple() {
item, item,
Some(ws::Frame::Close(Some(ws::CloseCode::Normal.into()))) Some(ws::Frame::Close(Some(ws::CloseCode::Normal.into())))
); );
{
let mut sys = actix_web::actix::System::new("test");
let url = srv.url("/");
let (reader, mut writer) = sys
.block_on(lazy(|| web_ws::Client::new(url).connect()))
.unwrap();
writer.text("text");
let (item, reader) = sys.block_on(reader.into_future()).unwrap();
assert_eq!(item, Some(web_ws::Message::Text("text".to_owned())));
writer.binary(b"text".as_ref());
let (item, reader) = sys.block_on(reader.into_future()).unwrap();
assert_eq!(
item,
Some(web_ws::Message::Binary(Bytes::from_static(b"text").into()))
);
writer.ping("ping");
let (item, reader) = sys.block_on(reader.into_future()).unwrap();
assert_eq!(item, Some(web_ws::Message::Pong("ping".to_owned())));
writer.close(Some(web_ws::CloseCode::Normal.into()));
let (item, _) = sys.block_on(reader.into_future()).unwrap();
assert_eq!(
item,
Some(web_ws::Message::Close(Some(
web_ws::CloseCode::Normal.into()
)))
);
}
} }