1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-01-19 06:04:40 +01:00

replace reqwest with actix::client

This commit is contained in:
Nikolay Kim 2018-02-19 13:18:18 -08:00
parent cb70d5ec3d
commit 548f4e4d62
12 changed files with 430 additions and 151 deletions

View File

@ -82,7 +82,6 @@ version = "0.5"
[dev-dependencies] [dev-dependencies]
env_logger = "0.5" env_logger = "0.5"
reqwest = "0.8"
skeptic = "0.13" skeptic = "0.13"
serde_derive = "1.0" serde_derive = "1.0"

View File

@ -1,3 +1,4 @@
[book]
title = "Actix web" title = "Actix web"
description = "Actix web framework guide" description = "Actix web framework guide"
author = "Actix Project and Contributors" author = "Actix Project and Contributors"

View File

@ -45,8 +45,8 @@ fn main() {
There are several methods how you can test your application. Actix provides There are several methods how you can test your application. Actix provides
[*TestServer*](../actix_web/test/struct.TestServer.html) [*TestServer*](../actix_web/test/struct.TestServer.html)
server that could be used to run whole application of just specific handlers server that could be used to run whole application of just specific handlers
in real http server. At the moment it is required to use third-party libraries in real http server. *TrstServer::get()*, *TrstServer::post()* or *TrstServer::client()*
to make actual requests, libraries like [reqwest](https://crates.io/crates/reqwest). methods could be used to send request to test server.
In simple form *TestServer* could be configured to use handler. *TestServer::new* method In simple form *TestServer* could be configured to use handler. *TestServer::new* method
accepts configuration function, only argument for this function is *test application* accepts configuration function, only argument for this function is *test application*
@ -55,7 +55,6 @@ for more information.
```rust ```rust
# extern crate actix_web; # extern crate actix_web;
extern crate reqwest;
use actix_web::*; use actix_web::*;
use actix_web::test::TestServer; use actix_web::test::TestServer;
@ -64,9 +63,13 @@ fn index(req: HttpRequest) -> HttpResponse {
} }
fn main() { fn main() {
let srv = TestServer::new(|app| app.handler(index)); // <- Start new test server let mut srv = TestServer::new(|app| app.handler(index)); // <- Start new test server
let url = srv.url("/"); // <- get handler url
assert!(reqwest::get(&url).unwrap().status().is_success()); // <- make request let request = srv.get().finish().unwrap(); // <- create client request
let response = srv.execute(request.send()).unwrap(); // <- send request to the server
assert!(response.status().is_success()); // <- check response
let bytes = srv.execute(response.body()).unwrap(); // <- read response body
} }
``` ```
@ -74,8 +77,9 @@ Other option is to use application factory. In this case you need to pass factor
same as you use for real http server configuration. same as you use for real http server configuration.
```rust ```rust
# extern crate http;
# extern crate actix_web; # extern crate actix_web;
extern crate reqwest; use http::Method;
use actix_web::*; use actix_web::*;
use actix_web::test::TestServer; use actix_web::test::TestServer;
@ -90,9 +94,12 @@ fn create_app() -> Application {
} }
fn main() { fn main() {
let srv = TestServer::with_factory(create_app); // <- Start new test server let mut srv = TestServer::with_factory(create_app); // <- Start new test server
let url = srv.url("/test"); // <- get handler url
assert!(reqwest::get(&url).unwrap().status().is_success()); // <- make request let request = srv.client(Method::GET, "/test").finish().unwrap(); // <- create client request
let response = srv.execute(request.send()).unwrap(); // <- send request to the server
assert!(response.status().is_success()); // <- check response
} }
``` ```

View File

@ -1,3 +1,4 @@
//! Http client
mod connector; mod connector;
mod parser; mod parser;
mod request; mod request;
@ -7,7 +8,7 @@ mod writer;
pub use self::pipeline::{SendRequest, SendRequestError}; pub use self::pipeline::{SendRequest, SendRequestError};
pub use self::request::{ClientRequest, ClientRequestBuilder}; pub use self::request::{ClientRequest, ClientRequestBuilder};
pub use self::response::{ClientResponse, JsonResponse, UrlEncoded}; pub use self::response::{ClientResponse, ResponseBody, JsonResponse, UrlEncoded};
pub use self::connector::{Connect, Connection, ClientConnector, ClientConnectorError}; pub use self::connector::{Connect, Connection, ClientConnector, ClientConnectorError};
pub(crate) use self::writer::HttpClientWriter; pub(crate) use self::writer::HttpClientWriter;
pub(crate) use self::parser::{HttpResponseParser, HttpResponseParserError}; pub(crate) use self::parser::{HttpResponseParser, HttpResponseParserError};

View File

@ -21,11 +21,13 @@ pub struct HttpResponseParser {
decoder: Option<Decoder>, decoder: Option<Decoder>,
} }
#[derive(Debug)] #[derive(Debug, Fail)]
pub enum HttpResponseParserError { pub enum HttpResponseParserError {
/// Server disconnected
#[fail(display="Server disconnected")]
Disconnect, Disconnect,
Payload, #[fail(display="{}", _0)]
Error(ParseError), Error(#[cause] ParseError),
} }
impl HttpResponseParser { impl HttpResponseParser {

View File

@ -11,10 +11,18 @@ use super::{Connect, Connection, ClientConnector, ClientConnectorError};
use super::HttpClientWriter; use super::HttpClientWriter;
use super::{HttpResponseParser, HttpResponseParserError}; use super::{HttpResponseParser, HttpResponseParserError};
/// A set of errors that can occur during sending request and reading response
#[derive(Fail, Debug)]
pub enum SendRequestError { pub enum SendRequestError {
Connector(ClientConnectorError), /// Failed to connect to host
ParseError(HttpResponseParserError), #[fail(display="Failed to connect to host: {}", _0)]
Io(io::Error), Connector(#[cause] ClientConnectorError),
/// Error parsing response
#[fail(display="{}", _0)]
ParseError(#[cause] HttpResponseParserError),
/// Error reading response payload
#[fail(display="Error reading response payload: {}", _0)]
Io(#[cause] io::Error),
} }
impl From<io::Error> for SendRequestError { impl From<io::Error> for SendRequestError {
@ -116,6 +124,7 @@ impl Pipeline {
#[inline] #[inline]
pub fn poll(&mut self) -> Poll<Option<Bytes>, PayloadError> { pub fn poll(&mut self) -> Poll<Option<Bytes>, PayloadError> {
self.poll_write()?;
self.parser.parse_payload(&mut self.conn, &mut self.parser_buf) self.parser.parse_payload(&mut self.conn, &mut self.parser_buf)
} }

View File

@ -463,6 +463,15 @@ impl ClientRequestBuilder {
pub fn finish(&mut self) -> Result<ClientRequest, HttpError> { pub fn finish(&mut self) -> Result<ClientRequest, HttpError> {
self.body(Body::Empty) self.body(Body::Empty)
} }
/// This method construct new `ClientRequestBuilder`
pub fn take(&mut self) -> ClientRequestBuilder {
ClientRequestBuilder {
request: self.request.take(),
err: self.err.take(),
cookies: self.cookies.take(),
}
}
} }
#[inline] #[inline]

View File

@ -158,6 +158,15 @@ impl ClientResponse {
} }
} }
/// Load request body.
///
/// By default only 256Kb payload reads to a memory, then connection get dropped
/// and `PayloadError` get returned. Use `ResponseBody::limit()`
/// method to change upper limit.
pub fn body(self) -> ResponseBody {
ResponseBody::new(self)
}
// /// Return stream to http payload processes as multipart. // /// Return stream to http payload processes as multipart.
// /// // ///
// /// Content-type: multipart/form-data; // /// Content-type: multipart/form-data;
@ -221,6 +230,67 @@ impl Stream for ClientResponse {
} }
} }
/// Future that resolves to a complete response body.
#[must_use = "ResponseBody does nothing unless polled"]
pub struct ResponseBody {
limit: usize,
resp: Option<ClientResponse>,
fut: Option<Box<Future<Item=Bytes, Error=PayloadError>>>,
}
impl ResponseBody {
/// Create `ResponseBody` for request.
pub fn new(resp: ClientResponse) -> Self {
ResponseBody {
limit: 262_144,
resp: Some(resp),
fut: None,
}
}
/// Change max size of payload. By default max size is 256Kb
pub fn limit(mut self, limit: usize) -> Self {
self.limit = limit;
self
}
}
impl Future for ResponseBody {
type Item = Bytes;
type Error = PayloadError;
fn poll(&mut self) -> Poll<Bytes, PayloadError> {
if let Some(resp) = self.resp.take() {
if let Some(len) = resp.headers().get(header::CONTENT_LENGTH) {
if let Ok(s) = len.to_str() {
if let Ok(len) = s.parse::<usize>() {
if len > self.limit {
return Err(PayloadError::Overflow);
}
} else {
return Err(PayloadError::Overflow);
}
}
}
let limit = self.limit;
let fut = resp.from_err()
.fold(BytesMut::new(), move |mut body, chunk| {
if (body.len() + chunk.len()) > limit {
Err(PayloadError::Overflow)
} else {
body.extend_from_slice(&chunk);
Ok(body)
}
})
.map(|bytes| bytes.freeze());
self.fut = Some(Box::new(fut));
}
self.fut.as_mut().expect("ResponseBody could not be used second time").poll()
}
}
/// Client response json parser that resolves to a deserialized `T` value. /// Client response json parser that resolves to a deserialized `T` value.
/// ///
/// Returns error: /// Returns error:
@ -237,7 +307,7 @@ pub struct JsonResponse<T: DeserializeOwned>{
impl<T: DeserializeOwned> JsonResponse<T> { impl<T: DeserializeOwned> JsonResponse<T> {
/// Create `JsonBody` for request. /// Create `JsonResponse` for request.
pub fn from_response(resp: ClientResponse) -> Self { pub fn from_response(resp: ClientResponse) -> Self {
JsonResponse{ JsonResponse{
limit: 262_144, limit: 262_144,

View File

@ -212,8 +212,10 @@ fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder
// TODO return error! // TODO return error!
let _ = enc.write(bytes.clone()); let _ = enc.write(bytes.clone());
let _ = enc.write_eof(); let _ = enc.write_eof();
*bytes = Binary::from(tmp.take()); *bytes = Binary::from(tmp.take());
req.headers_mut().insert(
CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
encoding = ContentEncoding::Identity; encoding = ContentEncoding::Identity;
} }
let mut b = BytesMut::new(); let mut b = BytesMut::new();
@ -240,6 +242,11 @@ fn content_encoder(buf: SharedBytes, req: &mut ClientRequest) -> ContentEncoder
} }
}; };
if encoding.is_compression() {
req.headers_mut().insert(
CONTENT_ENCODING, HeaderValue::from_static(encoding.as_str()));
}
req.replace_body(body); req.replace_body(body);
match encoding { match encoding {
ContentEncoding::Deflate => ContentEncoder::Deflate( ContentEncoding::Deflate => ContentEncoder::Deflate(

View File

@ -33,7 +33,8 @@ impl ContentEncoding {
} }
} }
fn as_str(&self) -> &'static str { #[inline]
pub fn as_str(&self) -> &'static str {
match *self { match *self {
ContentEncoding::Br => "br", ContentEncoding::Br => "br",
ContentEncoding::Gzip => "gzip", ContentEncoding::Gzip => "gzip",

View File

@ -26,6 +26,7 @@ use httprequest::HttpRequest;
use httpresponse::HttpResponse; use httpresponse::HttpResponse;
use server::{HttpServer, IntoHttpHandler, ServerSettings}; use server::{HttpServer, IntoHttpHandler, ServerSettings};
use ws::{WsClient, WsClientError, WsClientReader, WsClientWriter}; use ws::{WsClient, WsClientError, WsClientReader, WsClientWriter};
use client::{ClientRequest, ClientRequestBuilder};
/// The `TestServer` type. /// The `TestServer` type.
/// ///
@ -38,7 +39,6 @@ use ws::{WsClient, WsClientError, WsClientReader, WsClientWriter};
/// # extern crate actix; /// # extern crate actix;
/// # extern crate actix_web; /// # extern crate actix_web;
/// # use actix_web::*; /// # use actix_web::*;
/// # extern crate reqwest;
/// # /// #
/// # fn my_handler(req: HttpRequest) -> HttpResponse { /// # fn my_handler(req: HttpRequest) -> HttpResponse {
/// # httpcodes::HTTPOk.into() /// # httpcodes::HTTPOk.into()
@ -47,9 +47,11 @@ use ws::{WsClient, WsClientError, WsClientReader, WsClientWriter};
/// # fn main() { /// # fn main() {
/// use actix_web::test::TestServer; /// use actix_web::test::TestServer;
/// ///
/// let srv = TestServer::new(|app| app.handler(my_handler)); /// let mut srv = TestServer::new(|app| app.handler(my_handler));
/// ///
/// assert!(reqwest::get(&srv.url("/")).unwrap().status().is_success()); /// let req = srv.get().finish().unwrap();
/// let response = srv.execute(req.send()).unwrap();
/// assert!(response.status().is_success());
/// # } /// # }
/// ``` /// ```
pub struct TestServer { pub struct TestServer {
@ -182,6 +184,28 @@ impl TestServer {
let url = self.url("/"); let url = self.url("/");
self.system.run_until_complete(WsClient::new(url).connect().unwrap()) self.system.run_until_complete(WsClient::new(url).connect().unwrap())
} }
/// Create `GET` request
pub fn get(&self) -> ClientRequestBuilder {
ClientRequest::get(self.url("/").as_str())
}
/// Create `POST` request
pub fn post(&self) -> ClientRequestBuilder {
ClientRequest::get(self.url("/").as_str())
}
/// Create `HEAD` request
pub fn head(&self) -> ClientRequestBuilder {
ClientRequest::head(self.url("/").as_str())
}
/// Connect to test http server
pub fn client(&self, meth: Method, path: &str) -> ClientRequestBuilder {
ClientRequest::build()
.method(meth)
.uri(self.url(path).as_str()).take()
}
} }
impl Drop for TestServer { impl Drop for TestServer {

View File

@ -1,7 +1,6 @@
extern crate actix; extern crate actix;
extern crate actix_web; extern crate actix_web;
extern crate tokio_core; extern crate tokio_core;
extern crate reqwest;
extern crate futures; extern crate futures;
extern crate h2; extern crate h2;
extern crate http; extern crate http;
@ -10,23 +9,24 @@ extern crate flate2;
extern crate brotli2; extern crate brotli2;
use std::{net, thread, time}; use std::{net, thread, time};
use std::io::Write; use std::io::{Read, Write};
use std::sync::{Arc, mpsc}; use std::sync::{Arc, mpsc};
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
use flate2::Compression; use flate2::Compression;
use flate2::read::GzDecoder;
use flate2::write::{GzEncoder, DeflateEncoder, DeflateDecoder}; use flate2::write::{GzEncoder, DeflateEncoder, DeflateDecoder};
use brotli2::write::{BrotliEncoder, BrotliDecoder}; use brotli2::write::{BrotliEncoder, BrotliDecoder};
use futures::{Future, Stream}; use futures::{Future, Stream};
use futures::stream::once; use futures::stream::once;
use h2::client; use h2::client as h2client;
use bytes::{Bytes, BytesMut, BufMut}; use bytes::{Bytes, BytesMut};
use http::Request; use http::{header, Request};
use tokio_core::net::TcpStream; use tokio_core::net::TcpStream;
use tokio_core::reactor::Core; use tokio_core::reactor::Core;
use reqwest::header::{Encoding, ContentEncoding};
use actix_web::*;
use actix::System; use actix::System;
use actix_web::*;
const STR: &str = const STR: &str =
"Hello World Hello World Hello World Hello World Hello World \ "Hello World Hello World Hello World Hello World Hello World \
@ -69,7 +69,14 @@ fn test_start() {
sys.run(); sys.run();
}); });
let (addr, srv_addr) = rx.recv().unwrap(); let (addr, srv_addr) = rx.recv().unwrap();
assert!(reqwest::get(&format!("http://{}/", addr)).unwrap().status().is_success());
let mut sys = System::new("test-server");
{
let req = client::ClientRequest::get(format!("http://{}/", addr).as_str()).finish().unwrap();
let response = sys.run_until_complete(req.send()).unwrap();
assert!(response.status().is_success());
}
// pause // pause
let _ = srv_addr.send(server::PauseServer).wait(); let _ = srv_addr.send(server::PauseServer).wait();
@ -78,74 +85,98 @@ fn test_start() {
// resume // resume
let _ = srv_addr.send(server::ResumeServer).wait(); let _ = srv_addr.send(server::ResumeServer).wait();
assert!(reqwest::get(&format!("http://{}/", addr)).unwrap().status().is_success());
{
let req = client::ClientRequest::get(format!("http://{}/", addr).as_str()).finish().unwrap();
let response = sys.run_until_complete(req.send()).unwrap();
assert!(response.status().is_success());
}
} }
#[test] #[test]
fn test_simple() { fn test_simple() {
let srv = test::TestServer::new(|app| app.handler(httpcodes::HTTPOk)); let mut srv = test::TestServer::new(|app| app.handler(httpcodes::HTTPOk));
assert!(reqwest::get(&srv.url("/")).unwrap().status().is_success()); let req = srv.get().finish().unwrap();
let response = srv.execute(req.send()).unwrap();
assert!(response.status().is_success());
} }
#[test] #[test]
fn test_body() { fn test_body() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler(|_| httpcodes::HTTPOk.build().body(STR))); |app| app.handler(|_| httpcodes::HTTPOk.build().body(STR)));
let mut res = reqwest::get(&srv.url("/")).unwrap();
assert!(res.status().is_success()); let request = srv.get().finish().unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); let response = srv.execute(request.send()).unwrap();
let _ = res.copy_to(&mut bytes); assert!(response.status().is_success());
let bytes = bytes.into_inner();
// read response
let bytes = srv.execute(response.body()).unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
} }
#[test] #[test]
fn test_body_gzip() { fn test_body_gzip() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler( |app| app.handler(
|_| httpcodes::HTTPOk.build() |_| httpcodes::HTTPOk.build()
.content_encoding(headers::ContentEncoding::Gzip) .content_encoding(headers::ContentEncoding::Gzip)
.body(STR))); .body(STR)));
let mut res = reqwest::get(&srv.url("/")).unwrap();
assert!(res.status().is_success()); let request = srv.get().finish().unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); let response = srv.execute(request.send()).unwrap();
let _ = res.copy_to(&mut bytes); assert!(response.status().is_success());
let bytes = bytes.into_inner();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); // read response
let bytes = srv.execute(response.body()).unwrap();
// decode
let mut e = GzDecoder::new(&bytes[..]);
let mut dec = Vec::new();
e.read_to_end(&mut dec).unwrap();
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
} }
#[test] #[test]
fn test_body_streaming_implicit() { fn test_body_streaming_implicit() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler(|_| { |app| app.handler(|_| {
let body = once(Ok(Bytes::from_static(STR.as_ref()))); let body = once(Ok(Bytes::from_static(STR.as_ref())));
httpcodes::HTTPOk.build() httpcodes::HTTPOk.build()
.content_encoding(headers::ContentEncoding::Gzip) .content_encoding(headers::ContentEncoding::Gzip)
.body(Body::Streaming(Box::new(body)))})); .body(Body::Streaming(Box::new(body)))}));
let mut res = reqwest::get(&srv.url("/")).unwrap(); let request = srv.get().finish().unwrap();
assert!(res.status().is_success()); let response = srv.execute(request.send()).unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); assert!(response.status().is_success());
let _ = res.copy_to(&mut bytes);
let bytes = bytes.into_inner(); // read response
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); let bytes = srv.execute(response.body()).unwrap();
// decode
let mut e = GzDecoder::new(&bytes[..]);
let mut dec = Vec::new();
e.read_to_end(&mut dec).unwrap();
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
} }
#[test] #[test]
fn test_body_br_streaming() { fn test_body_br_streaming() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler(|_| { |app| app.handler(|_| {
let body = once(Ok(Bytes::from_static(STR.as_ref()))); let body = once(Ok(Bytes::from_static(STR.as_ref())));
httpcodes::HTTPOk.build() httpcodes::HTTPOk.build()
.content_encoding(headers::ContentEncoding::Br) .content_encoding(headers::ContentEncoding::Br)
.body(Body::Streaming(Box::new(body)))})); .body(Body::Streaming(Box::new(body)))}));
let mut res = reqwest::get(&srv.url("/")).unwrap(); let request = srv.get().finish().unwrap();
assert!(res.status().is_success()); let response = srv.execute(request.send()).unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); assert!(response.status().is_success());
let _ = res.copy_to(&mut bytes);
let bytes = bytes.into_inner();
// read response
let bytes = srv.execute(response.body()).unwrap();
// decode br
let mut e = BrotliDecoder::new(Vec::with_capacity(2048)); let mut e = BrotliDecoder::new(Vec::with_capacity(2048));
e.write_all(bytes.as_ref()).unwrap(); e.write_all(bytes.as_ref()).unwrap();
let dec = e.finish().unwrap(); let dec = e.finish().unwrap();
@ -154,84 +185,87 @@ fn test_body_br_streaming() {
#[test] #[test]
fn test_head_empty() { fn test_head_empty() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler(|_| { |app| app.handler(|_| {
httpcodes::HTTPOk.build() httpcodes::HTTPOk.build()
.content_length(STR.len() as u64).finish()})); .content_length(STR.len() as u64).finish()}));
let client = reqwest::Client::new(); let request = srv.head().finish().unwrap();
let mut res = client.head(&srv.url("/")).send().unwrap(); let response = srv.execute(request.send()).unwrap();
assert!(res.status().is_success()); assert!(response.status().is_success());
let mut bytes = BytesMut::with_capacity(2048).writer();
let len = res.headers() {
.get::<reqwest::header::ContentLength>().map(|ct_len| **ct_len).unwrap(); let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
assert_eq!(len, STR.len() as u64); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
let _ = res.copy_to(&mut bytes); }
let bytes = bytes.into_inner();
assert!(bytes.is_empty()); // read response
//let bytes = srv.execute(response.body()).unwrap();
//assert!(bytes.is_empty());
} }
#[test] #[test]
fn test_head_binary() { fn test_head_binary() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler(|_| { |app| app.handler(|_| {
httpcodes::HTTPOk.build() httpcodes::HTTPOk.build()
.content_encoding(headers::ContentEncoding::Identity) .content_encoding(headers::ContentEncoding::Identity)
.content_length(100).body(STR)})); .content_length(100).body(STR)}));
let client = reqwest::Client::new(); let request = srv.head().finish().unwrap();
let mut res = client.head(&srv.url("/")).send().unwrap(); let response = srv.execute(request.send()).unwrap();
assert!(res.status().is_success()); assert!(response.status().is_success());
let mut bytes = BytesMut::with_capacity(2048).writer();
let len = res.headers() {
.get::<reqwest::header::ContentLength>().map(|ct_len| **ct_len).unwrap(); let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
assert_eq!(len, STR.len() as u64); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
let _ = res.copy_to(&mut bytes); }
let bytes = bytes.into_inner();
assert!(bytes.is_empty()); // read response
//let bytes = srv.execute(response.body()).unwrap();
//assert!(bytes.is_empty());
} }
#[test] #[test]
fn test_head_binary2() { fn test_head_binary2() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler(|_| { |app| app.handler(|_| {
httpcodes::HTTPOk.build() httpcodes::HTTPOk.build()
.content_encoding(headers::ContentEncoding::Identity) .content_encoding(headers::ContentEncoding::Identity)
.body(STR) .body(STR)
})); }));
let client = reqwest::Client::new(); let request = srv.head().finish().unwrap();
let mut res = client.head(&srv.url("/")).send().unwrap(); let response = srv.execute(request.send()).unwrap();
assert!(res.status().is_success()); assert!(response.status().is_success());
let mut bytes = BytesMut::with_capacity(2048).writer();
let len = res.headers() {
.get::<reqwest::header::ContentLength>().map(|ct_len| **ct_len).unwrap(); let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
assert_eq!(len, STR.len() as u64); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
let _ = res.copy_to(&mut bytes); }
let bytes = bytes.into_inner();
assert!(bytes.is_empty());
} }
#[test] #[test]
fn test_body_length() { fn test_body_length() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler(|_| { |app| app.handler(|_| {
let body = once(Ok(Bytes::from_static(STR.as_ref()))); let body = once(Ok(Bytes::from_static(STR.as_ref())));
httpcodes::HTTPOk.build() httpcodes::HTTPOk.build()
.content_length(STR.len() as u64) .content_length(STR.len() as u64)
.body(Body::Streaming(Box::new(body)))})); .body(Body::Streaming(Box::new(body)))}));
let mut res = reqwest::get(&srv.url("/")).unwrap(); let request = srv.get().finish().unwrap();
assert!(res.status().is_success()); let response = srv.execute(request.send()).unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); assert!(response.status().is_success());
let _ = res.copy_to(&mut bytes);
let bytes = bytes.into_inner(); // read response
let bytes = srv.execute(response.body()).unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
} }
#[test] #[test]
fn test_body_streaming_explicit() { fn test_body_streaming_explicit() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler(|_| { |app| app.handler(|_| {
let body = once(Ok(Bytes::from_static(STR.as_ref()))); let body = once(Ok(Bytes::from_static(STR.as_ref())));
httpcodes::HTTPOk.build() httpcodes::HTTPOk.build()
@ -239,28 +273,38 @@ fn test_body_streaming_explicit() {
.content_encoding(headers::ContentEncoding::Gzip) .content_encoding(headers::ContentEncoding::Gzip)
.body(Body::Streaming(Box::new(body)))})); .body(Body::Streaming(Box::new(body)))}));
let mut res = reqwest::get(&srv.url("/")).unwrap(); let request = srv.get().finish().unwrap();
assert!(res.status().is_success()); let response = srv.execute(request.send()).unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); assert!(response.status().is_success());
let _ = res.copy_to(&mut bytes);
let bytes = bytes.into_inner(); // read response
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); let bytes = srv.execute(response.body()).unwrap();
// decode
let mut e = GzDecoder::new(&bytes[..]);
let mut dec = Vec::new();
e.read_to_end(&mut dec).unwrap();
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
} }
#[test] #[test]
fn test_body_deflate() { fn test_body_deflate() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler( |app| app.handler(
|_| httpcodes::HTTPOk |_| httpcodes::HTTPOk
.build() .build()
.content_encoding(headers::ContentEncoding::Deflate) .content_encoding(headers::ContentEncoding::Deflate)
.body(STR))); .body(STR)));
let mut res = reqwest::get(&srv.url("/")).unwrap();
assert!(res.status().is_success());
let mut bytes = BytesMut::with_capacity(2048).writer();
let _ = res.copy_to(&mut bytes);
let bytes = bytes.into_inner();
// client request
let request = srv.get().finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.execute(response.body()).unwrap();
// decode deflate
let mut e = DeflateDecoder::new(Vec::new()); let mut e = DeflateDecoder::new(Vec::new());
e.write_all(bytes.as_ref()).unwrap(); e.write_all(bytes.as_ref()).unwrap();
let dec = e.finish().unwrap(); let dec = e.finish().unwrap();
@ -269,18 +313,22 @@ fn test_body_deflate() {
#[test] #[test]
fn test_body_brotli() { fn test_body_brotli() {
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
|app| app.handler( |app| app.handler(
|_| httpcodes::HTTPOk |_| httpcodes::HTTPOk
.build() .build()
.content_encoding(headers::ContentEncoding::Br) .content_encoding(headers::ContentEncoding::Br)
.body(STR))); .body(STR)));
let mut res = reqwest::get(&srv.url("/")).unwrap();
assert!(res.status().is_success());
let mut bytes = BytesMut::with_capacity(2048).writer();
let _ = res.copy_to(&mut bytes);
let bytes = bytes.into_inner();
// client request
let request = srv.get().finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.execute(response.body()).unwrap();
// decode brotli
let mut e = BrotliDecoder::new(Vec::with_capacity(2048)); let mut e = BrotliDecoder::new(Vec::with_capacity(2048));
e.write_all(bytes.as_ref()).unwrap(); e.write_all(bytes.as_ref()).unwrap();
let dec = e.finish().unwrap(); let dec = e.finish().unwrap();
@ -289,7 +337,7 @@ fn test_body_brotli() {
#[test] #[test]
fn test_gzip_encoding() { fn test_gzip_encoding() {
let srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| { let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
req.body() req.body()
.and_then(|bytes: Bytes| { .and_then(|bytes: Bytes| {
Ok(httpcodes::HTTPOk Ok(httpcodes::HTTPOk
@ -299,23 +347,53 @@ fn test_gzip_encoding() {
}).responder()} }).responder()}
)); ));
// client request
let mut e = GzEncoder::new(Vec::new(), Compression::default()); let mut e = GzEncoder::new(Vec::new(), Compression::default());
e.write_all(STR.as_ref()).unwrap(); e.write_all(STR.as_ref()).unwrap();
let enc = e.finish().unwrap(); let enc = e.finish().unwrap();
let client = reqwest::Client::new(); let request = srv.post()
let mut res = client.post(&srv.url("/")) .header(header::CONTENT_ENCODING, "gzip")
.header(ContentEncoding(vec![Encoding::Gzip])) .body(enc.clone()).unwrap();
.body(enc.clone()).send().unwrap(); let response = srv.execute(request.send()).unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); assert!(response.status().is_success());
let _ = res.copy_to(&mut bytes);
let bytes = bytes.into_inner(); // read response
let bytes = srv.execute(response.body()).unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
} }
#[test]
fn test_client_gzip_encoding() {
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
req.body()
.and_then(|bytes: Bytes| {
Ok(httpcodes::HTTPOk
.build()
.content_encoding(headers::ContentEncoding::Deflate)
.body(bytes))
}).responder()}
));
// client request
let request = srv.post()
.content_encoding(headers::ContentEncoding::Gzip)
.body(STR).unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.execute(response.body()).unwrap();
let mut e = DeflateDecoder::new(Vec::new());
e.write_all(bytes.as_ref()).unwrap();
let dec = e.finish().unwrap();
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
}
#[test] #[test]
fn test_deflate_encoding() { fn test_deflate_encoding() {
let srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| { let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
req.body() req.body()
.and_then(|bytes: Bytes| { .and_then(|bytes: Bytes| {
Ok(httpcodes::HTTPOk Ok(httpcodes::HTTPOk
@ -329,19 +407,50 @@ fn test_deflate_encoding() {
e.write_all(STR.as_ref()).unwrap(); e.write_all(STR.as_ref()).unwrap();
let enc = e.finish().unwrap(); let enc = e.finish().unwrap();
let client = reqwest::Client::new(); // client request
let mut res = client.post(&srv.url("/")) let request = srv.post()
.header(ContentEncoding(vec![Encoding::Deflate])) .header(header::CONTENT_ENCODING, "deflate")
.body(enc.clone()).send().unwrap(); .body(enc).unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); let response = srv.execute(request.send()).unwrap();
let _ = res.copy_to(&mut bytes); assert!(response.status().is_success());
let bytes = bytes.into_inner();
// read response
let bytes = srv.execute(response.body()).unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
} }
#[test]
fn test_client_deflate_encoding() {
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
req.body()
.and_then(|bytes: Bytes| {
Ok(httpcodes::HTTPOk
.build()
.content_encoding(headers::ContentEncoding::Br)
.body(bytes))
}).responder()}
));
// client request
let request = srv.post()
.content_encoding(headers::ContentEncoding::Deflate)
.body(STR).unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.execute(response.body()).unwrap();
// decode brotli
let mut e = BrotliDecoder::new(Vec::with_capacity(2048));
e.write_all(bytes.as_ref()).unwrap();
let dec = e.finish().unwrap();
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
}
#[test] #[test]
fn test_brotli_encoding() { fn test_brotli_encoding() {
let srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| { let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
req.body() req.body()
.and_then(|bytes: Bytes| { .and_then(|bytes: Bytes| {
Ok(httpcodes::HTTPOk Ok(httpcodes::HTTPOk
@ -355,16 +464,47 @@ fn test_brotli_encoding() {
e.write_all(STR.as_ref()).unwrap(); e.write_all(STR.as_ref()).unwrap();
let enc = e.finish().unwrap(); let enc = e.finish().unwrap();
let client = reqwest::Client::new(); // client request
let mut res = client.post(&srv.url("/")) let request = srv.post()
.header(ContentEncoding(vec![Encoding::Brotli])) .header(header::CONTENT_ENCODING, "br")
.body(enc.clone()).send().unwrap(); .body(enc).unwrap();
let mut bytes = BytesMut::with_capacity(2048).writer(); let response = srv.execute(request.send()).unwrap();
let _ = res.copy_to(&mut bytes); assert!(response.status().is_success());
let bytes = bytes.into_inner();
// read response
let bytes = srv.execute(response.body()).unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
} }
#[test]
fn test_client_brotli_encoding() {
let mut srv = test::TestServer::new(|app| app.handler(|req: HttpRequest| {
req.body()
.and_then(|bytes: Bytes| {
Ok(httpcodes::HTTPOk
.build()
.content_encoding(headers::ContentEncoding::Deflate)
.body(bytes))
}).responder()}
));
// client request
let request = srv.client(Method::POST, "/")
.content_encoding(headers::ContentEncoding::Br)
.body(STR).unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.execute(response.body()).unwrap();
// decode brotli
let mut e = DeflateDecoder::new(Vec::with_capacity(2048));
e.write_all(bytes.as_ref()).unwrap();
let dec = e.finish().unwrap();
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
}
#[test] #[test]
fn test_h2() { fn test_h2() {
let srv = test::TestServer::new(|app| app.handler(|_|{ let srv = test::TestServer::new(|app| app.handler(|_|{
@ -377,7 +517,7 @@ fn test_h2() {
let tcp = TcpStream::connect(&addr, &handle); let tcp = TcpStream::connect(&addr, &handle);
let tcp = tcp.then(|res| { let tcp = tcp.then(|res| {
client::handshake(res.unwrap()) h2client::handshake(res.unwrap())
}).then(move |res| { }).then(move |res| {
let (mut client, h2) = res.unwrap(); let (mut client, h2) = res.unwrap();
@ -407,9 +547,12 @@ fn test_h2() {
#[test] #[test]
fn test_application() { fn test_application() {
let srv = test::TestServer::with_factory( let mut srv = test::TestServer::with_factory(
|| Application::new().resource("/", |r| r.h(httpcodes::HTTPOk))); || Application::new().resource("/", |r| r.h(httpcodes::HTTPOk)));
assert!(reqwest::get(&srv.url("/")).unwrap().status().is_success());
let request = srv.get().finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
} }
struct MiddlewareTest { struct MiddlewareTest {
@ -445,14 +588,17 @@ fn test_middlewares() {
let act_num2 = Arc::clone(&num2); let act_num2 = Arc::clone(&num2);
let act_num3 = Arc::clone(&num3); let act_num3 = Arc::clone(&num3);
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
move |app| app.middleware(MiddlewareTest{start: Arc::clone(&act_num1), move |app| app.middleware(MiddlewareTest{start: Arc::clone(&act_num1),
response: Arc::clone(&act_num2), response: Arc::clone(&act_num2),
finish: Arc::clone(&act_num3)}) finish: Arc::clone(&act_num3)})
.handler(httpcodes::HTTPOk) .handler(httpcodes::HTTPOk)
); );
assert!(reqwest::get(&srv.url("/")).unwrap().status().is_success()); let request = srv.get().finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
assert_eq!(num1.load(Ordering::Relaxed), 1); assert_eq!(num1.load(Ordering::Relaxed), 1);
assert_eq!(num2.load(Ordering::Relaxed), 1); assert_eq!(num2.load(Ordering::Relaxed), 1);
assert_eq!(num3.load(Ordering::Relaxed), 1); assert_eq!(num3.load(Ordering::Relaxed), 1);
@ -469,7 +615,7 @@ fn test_resource_middlewares() {
let act_num2 = Arc::clone(&num2); let act_num2 = Arc::clone(&num2);
let act_num3 = Arc::clone(&num3); let act_num3 = Arc::clone(&num3);
let srv = test::TestServer::new( let mut srv = test::TestServer::new(
move |app| app.handler2( move |app| app.handler2(
httpcodes::HTTPOk, httpcodes::HTTPOk,
MiddlewareTest{start: Arc::clone(&act_num1), MiddlewareTest{start: Arc::clone(&act_num1),
@ -477,7 +623,10 @@ fn test_resource_middlewares() {
finish: Arc::clone(&act_num3)}) finish: Arc::clone(&act_num3)})
); );
assert!(reqwest::get(&srv.url("/")).unwrap().status().is_success()); let request = srv.get().finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
assert_eq!(num1.load(Ordering::Relaxed), 1); assert_eq!(num1.load(Ordering::Relaxed), 1);
assert_eq!(num2.load(Ordering::Relaxed), 1); assert_eq!(num2.load(Ordering::Relaxed), 1);
// assert_eq!(num3.load(Ordering::Relaxed), 1); // assert_eq!(num3.load(Ordering::Relaxed), 1);