mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into master
This commit is contained in:
commit
c2598b7f8c
|
@ -1,12 +1,14 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## [1.0.0-alpha.7] - 2019-04-xx
|
## [1.0.0-beta.1] - 2019-04-xx
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
* Added helper functions for reading test response body,
|
* Add helper functions for reading test response body,
|
||||||
`test::read_response()` and test::read_response_json()`
|
`test::read_response()` and test::read_response_json()`
|
||||||
|
|
||||||
|
* Add `.peer_addr()` #744
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
* Rename `RouterConfig` to `ServiceConfig`
|
* Rename `RouterConfig` to `ServiceConfig`
|
||||||
|
|
15
Cargo.toml
15
Cargo.toml
|
@ -71,17 +71,17 @@ actix-utils = "0.3.4"
|
||||||
actix-router = "0.1.2"
|
actix-router = "0.1.2"
|
||||||
actix-rt = "0.2.2"
|
actix-rt = "0.2.2"
|
||||||
actix-web-codegen = "0.1.0-alpha.6"
|
actix-web-codegen = "0.1.0-alpha.6"
|
||||||
actix-http = { version = "0.1.0-alpha.5", features=["fail"] }
|
actix-http = { version = "0.1.0", features=["fail"] }
|
||||||
actix-server = "0.4.2"
|
actix-server = "0.4.3"
|
||||||
actix-server-config = "0.1.0"
|
actix-server-config = "0.1.1"
|
||||||
actix-threadpool = "0.1.0"
|
actix-threadpool = "0.1.0"
|
||||||
awc = { version = "0.1.0-alpha.6", optional = true }
|
awc = { version = "0.1.0", optional = true }
|
||||||
|
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
derive_more = "0.14"
|
derive_more = "0.14"
|
||||||
encoding = "0.2"
|
encoding = "0.2"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
hashbrown = "0.2.1"
|
hashbrown = "0.2.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
net2 = "0.2.33"
|
net2 = "0.2.33"
|
||||||
|
@ -98,8 +98,8 @@ openssl = { version="0.10", optional = true }
|
||||||
rustls = { version = "^0.15", optional = true }
|
rustls = { version = "^0.15", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-http = { version = "0.1.0-alpha.5", features=["ssl", "brotli", "flate2-zlib"] }
|
actix-http = { version = "0.1.0", features=["ssl", "brotli", "flate2-zlib"] }
|
||||||
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
|
actix-http-test = { version = "0.1.0", features=["ssl"] }
|
||||||
actix-files = { version = "0.1.0-alpha.6" }
|
actix-files = { version = "0.1.0-alpha.6" }
|
||||||
rand = "0.6"
|
rand = "0.6"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
|
@ -116,7 +116,6 @@ codegen-units = 1
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
actix-web = { path = "." }
|
actix-web = { path = "." }
|
||||||
actix-http = { path = "actix-http" }
|
actix-http = { path = "actix-http" }
|
||||||
actix-http-test = { path = "test-server" }
|
|
||||||
actix-web-codegen = { path = "actix-web-codegen" }
|
actix-web-codegen = { path = "actix-web-codegen" }
|
||||||
actix-web-actors = { path = "actix-web-actors" }
|
actix-web-actors = { path = "actix-web-actors" }
|
||||||
actix-session = { path = "actix-session" }
|
actix-session = { path = "actix-session" }
|
||||||
|
|
|
@ -775,7 +775,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let request = TestRequest::get().uri("/").to_request();
|
let request = TestRequest::get().uri("/").to_request();
|
||||||
let response = test::call_success(&mut srv, request);
|
let response = test::call_service(&mut srv, request);
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
let content_disposition = response
|
let content_disposition = response
|
||||||
|
@ -799,7 +799,7 @@ mod tests {
|
||||||
.uri("/t%65st/Cargo.toml")
|
.uri("/t%65st/Cargo.toml")
|
||||||
.header(header::RANGE, "bytes=10-20")
|
.header(header::RANGE, "bytes=10-20")
|
||||||
.to_request();
|
.to_request();
|
||||||
let response = test::call_success(&mut srv, request);
|
let response = test::call_service(&mut srv, request);
|
||||||
assert_eq!(response.status(), StatusCode::PARTIAL_CONTENT);
|
assert_eq!(response.status(), StatusCode::PARTIAL_CONTENT);
|
||||||
|
|
||||||
// Invalid range header
|
// Invalid range header
|
||||||
|
@ -807,7 +807,7 @@ mod tests {
|
||||||
.uri("/t%65st/Cargo.toml")
|
.uri("/t%65st/Cargo.toml")
|
||||||
.header(header::RANGE, "bytes=1-0")
|
.header(header::RANGE, "bytes=1-0")
|
||||||
.to_request();
|
.to_request();
|
||||||
let response = test::call_success(&mut srv, request);
|
let response = test::call_service(&mut srv, request);
|
||||||
|
|
||||||
assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE);
|
assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE);
|
||||||
}
|
}
|
||||||
|
@ -824,7 +824,7 @@ mod tests {
|
||||||
.header(header::RANGE, "bytes=10-20")
|
.header(header::RANGE, "bytes=10-20")
|
||||||
.to_request();
|
.to_request();
|
||||||
|
|
||||||
let response = test::call_success(&mut srv, request);
|
let response = test::call_service(&mut srv, request);
|
||||||
let contentrange = response
|
let contentrange = response
|
||||||
.headers()
|
.headers()
|
||||||
.get(header::CONTENT_RANGE)
|
.get(header::CONTENT_RANGE)
|
||||||
|
@ -839,7 +839,7 @@ mod tests {
|
||||||
.uri("/t%65st/tests/test.binary")
|
.uri("/t%65st/tests/test.binary")
|
||||||
.header(header::RANGE, "bytes=10-5")
|
.header(header::RANGE, "bytes=10-5")
|
||||||
.to_request();
|
.to_request();
|
||||||
let response = test::call_success(&mut srv, request);
|
let response = test::call_service(&mut srv, request);
|
||||||
|
|
||||||
let contentrange = response
|
let contentrange = response
|
||||||
.headers()
|
.headers()
|
||||||
|
@ -862,7 +862,7 @@ mod tests {
|
||||||
.uri("/t%65st/tests/test.binary")
|
.uri("/t%65st/tests/test.binary")
|
||||||
.header(header::RANGE, "bytes=10-20")
|
.header(header::RANGE, "bytes=10-20")
|
||||||
.to_request();
|
.to_request();
|
||||||
let response = test::call_success(&mut srv, request);
|
let response = test::call_service(&mut srv, request);
|
||||||
|
|
||||||
let contentlength = response
|
let contentlength = response
|
||||||
.headers()
|
.headers()
|
||||||
|
@ -878,7 +878,7 @@ mod tests {
|
||||||
.uri("/t%65st/tests/test.binary")
|
.uri("/t%65st/tests/test.binary")
|
||||||
.header(header::RANGE, "bytes=10-8")
|
.header(header::RANGE, "bytes=10-8")
|
||||||
.to_request();
|
.to_request();
|
||||||
let response = test::call_success(&mut srv, request);
|
let response = test::call_service(&mut srv, request);
|
||||||
assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE);
|
assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE);
|
||||||
|
|
||||||
// Without range header
|
// Without range header
|
||||||
|
@ -886,7 +886,7 @@ mod tests {
|
||||||
.uri("/t%65st/tests/test.binary")
|
.uri("/t%65st/tests/test.binary")
|
||||||
// .no_default_headers()
|
// .no_default_headers()
|
||||||
.to_request();
|
.to_request();
|
||||||
let response = test::call_success(&mut srv, request);
|
let response = test::call_service(&mut srv, request);
|
||||||
|
|
||||||
let contentlength = response
|
let contentlength = response
|
||||||
.headers()
|
.headers()
|
||||||
|
@ -901,7 +901,7 @@ mod tests {
|
||||||
let request = TestRequest::get()
|
let request = TestRequest::get()
|
||||||
.uri("/t%65st/tests/test.binary")
|
.uri("/t%65st/tests/test.binary")
|
||||||
.to_request();
|
.to_request();
|
||||||
let mut response = test::call_success(&mut srv, request);
|
let mut response = test::call_service(&mut srv, request);
|
||||||
|
|
||||||
// with enabled compression
|
// with enabled compression
|
||||||
// {
|
// {
|
||||||
|
@ -932,7 +932,7 @@ mod tests {
|
||||||
let request = TestRequest::get()
|
let request = TestRequest::get()
|
||||||
.uri("/tests/test%20space.binary")
|
.uri("/tests/test%20space.binary")
|
||||||
.to_request();
|
.to_request();
|
||||||
let mut response = test::call_success(&mut srv, request);
|
let mut response = test::call_service(&mut srv, request);
|
||||||
assert_eq!(response.status(), StatusCode::OK);
|
assert_eq!(response.status(), StatusCode::OK);
|
||||||
|
|
||||||
let bytes =
|
let bytes =
|
||||||
|
@ -975,7 +975,7 @@ mod tests {
|
||||||
.uri("/")
|
.uri("/")
|
||||||
.header(header::ACCEPT_ENCODING, "gzip")
|
.header(header::ACCEPT_ENCODING, "gzip")
|
||||||
.to_request();
|
.to_request();
|
||||||
let res = test::call_success(&mut srv, request);
|
let res = test::call_service(&mut srv, request);
|
||||||
assert_eq!(res.status(), StatusCode::OK);
|
assert_eq!(res.status(), StatusCode::OK);
|
||||||
assert!(!res.headers().contains_key(header::CONTENT_ENCODING));
|
assert!(!res.headers().contains_key(header::CONTENT_ENCODING));
|
||||||
}
|
}
|
||||||
|
@ -994,7 +994,7 @@ mod tests {
|
||||||
.uri("/")
|
.uri("/")
|
||||||
.header(header::ACCEPT_ENCODING, "gzip")
|
.header(header::ACCEPT_ENCODING, "gzip")
|
||||||
.to_request();
|
.to_request();
|
||||||
let res = test::call_success(&mut srv, request);
|
let res = test::call_service(&mut srv, request);
|
||||||
assert_eq!(res.status(), StatusCode::OK);
|
assert_eq!(res.status(), StatusCode::OK);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res.headers()
|
res.headers()
|
||||||
|
@ -1021,20 +1021,20 @@ mod tests {
|
||||||
);
|
);
|
||||||
let req = TestRequest::with_uri("/missing").to_request();
|
let req = TestRequest::with_uri("/missing").to_request();
|
||||||
|
|
||||||
let resp = test::call_success(&mut srv, req);
|
let resp = test::call_service(&mut srv, req);
|
||||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
let mut srv = test::init_service(App::new().service(Files::new("/", ".")));
|
let mut srv = test::init_service(App::new().service(Files::new("/", ".")));
|
||||||
|
|
||||||
let req = TestRequest::default().to_request();
|
let req = TestRequest::default().to_request();
|
||||||
let resp = test::call_success(&mut srv, req);
|
let resp = test::call_service(&mut srv, req);
|
||||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
let mut srv = test::init_service(
|
let mut srv = test::init_service(
|
||||||
App::new().service(Files::new("/", ".").show_files_listing()),
|
App::new().service(Files::new("/", ".").show_files_listing()),
|
||||||
);
|
);
|
||||||
let req = TestRequest::with_uri("/tests").to_request();
|
let req = TestRequest::with_uri("/tests").to_request();
|
||||||
let mut resp = test::call_success(&mut srv, req);
|
let mut resp = test::call_service(&mut srv, req);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
resp.headers().get(header::CONTENT_TYPE).unwrap(),
|
||||||
"text/html; charset=utf-8"
|
"text/html; charset=utf-8"
|
||||||
|
@ -1067,7 +1067,7 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let req = TestRequest::with_uri("/missing").to_srv_request();
|
let req = TestRequest::with_uri("/missing").to_srv_request();
|
||||||
|
|
||||||
let mut resp = test::call_success(&mut st, req);
|
let mut resp = test::call_service(&mut st, req);
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
let bytes =
|
let bytes =
|
||||||
test::block_on(resp.take_body().fold(BytesMut::new(), |mut b, c| {
|
test::block_on(resp.take_body().fold(BytesMut::new(), |mut b, c| {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-framed"
|
name = "actix-framed"
|
||||||
version = "0.1.0-alpha.1"
|
version = "0.1.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix framed app server"
|
description = "Actix framed app server"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -25,13 +25,13 @@ actix-service = "0.3.6"
|
||||||
actix-utils = "0.3.4"
|
actix-utils = "0.3.4"
|
||||||
actix-router = "0.1.2"
|
actix-router = "0.1.2"
|
||||||
actix-rt = "0.2.2"
|
actix-rt = "0.2.2"
|
||||||
actix-http = "0.1.0-alpha.5"
|
actix-http = "0.1.0"
|
||||||
|
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-server = { version = "0.4.1", features=["ssl"] }
|
actix-server = { version = "0.4.3", features=["ssl"] }
|
||||||
actix-connect = { version = "0.1.4", features=["ssl"] }
|
actix-connect = { version = "0.1.4", features=["ssl"] }
|
||||||
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
|
actix-http-test = { version = "0.1.0", features=["ssl"] }
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.1.0] - 2019-04-16
|
||||||
|
|
||||||
|
* Update tests
|
||||||
|
|
||||||
|
|
||||||
## [0.1.0-alpha.1] - 2019-04-12
|
## [0.1.0-alpha.1] - 2019-04-12
|
||||||
|
|
||||||
* Initial release
|
* Initial release
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## [0.1.0] - 2019-04-xx
|
## [0.1.0] - 2019-04-16
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Expose peer addr via `Request::peer_addr()` and `RequestHead::peer_addr`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
* `actix_http::encoding` always available
|
||||||
|
|
||||||
* use trust-dns-resolver 0.11.0
|
* use trust-dns-resolver 0.11.0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "0.1.0-alpha.5"
|
version = "0.1.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix http primitives"
|
description = "Actix http primitives"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -48,7 +48,7 @@ actix-service = "0.3.6"
|
||||||
actix-codec = "0.1.2"
|
actix-codec = "0.1.2"
|
||||||
actix-connect = "0.1.4"
|
actix-connect = "0.1.4"
|
||||||
actix-utils = "0.3.5"
|
actix-utils = "0.3.5"
|
||||||
actix-server-config = "0.1.0"
|
actix-server-config = "0.1.1"
|
||||||
actix-threadpool = "0.1.0"
|
actix-threadpool = "0.1.0"
|
||||||
|
|
||||||
base64 = "0.10"
|
base64 = "0.10"
|
||||||
|
@ -60,7 +60,7 @@ derive_more = "0.14"
|
||||||
either = "1.5.2"
|
either = "1.5.2"
|
||||||
encoding = "0.2"
|
encoding = "0.2"
|
||||||
futures = "0.1"
|
futures = "0.1"
|
||||||
hashbrown = "0.2.0"
|
hashbrown = "0.2.2"
|
||||||
h2 = "0.1.16"
|
h2 = "0.1.16"
|
||||||
http = "0.1.17"
|
http = "0.1.17"
|
||||||
httparse = "1.3"
|
httparse = "1.3"
|
||||||
|
@ -76,10 +76,10 @@ serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
sha1 = "0.6"
|
sha1 = "0.6"
|
||||||
slab = "0.4"
|
slab = "0.4"
|
||||||
serde_urlencoded = "0.5.3"
|
serde_urlencoded = "0.5.5"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
tokio-tcp = "0.1.3"
|
tokio-tcp = "0.1.3"
|
||||||
tokio-timer = "0.2"
|
tokio-timer = "0.2.8"
|
||||||
tokio-current-thread = "0.1"
|
tokio-current-thread = "0.1"
|
||||||
trust-dns-resolver = { version="0.11.0", default-features = false }
|
trust-dns-resolver = { version="0.11.0", default-features = false }
|
||||||
|
|
||||||
|
@ -96,9 +96,9 @@ openssl = { version="0.10", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "0.2.2"
|
actix-rt = "0.2.2"
|
||||||
actix-server = { version = "0.4.1", features=["ssl"] }
|
actix-server = { version = "0.4.3", features=["ssl"] }
|
||||||
actix-connect = { version = "0.1.4", features=["ssl"] }
|
actix-connect = { version = "0.1.4", features=["ssl"] }
|
||||||
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
|
actix-http-test = { version = "0.1.0", features=["ssl"] }
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
openssl = { version="0.10" }
|
openssl = { version="0.10" }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#![allow(unused_imports, unused_variables, dead_code)]
|
#![allow(unused_imports, unused_variables, dead_code)]
|
||||||
use std::fmt;
|
use std::io::Write;
|
||||||
use std::io::{self, Write};
|
use std::{fmt, io, net};
|
||||||
|
|
||||||
use actix_codec::{Decoder, Encoder};
|
use actix_codec::{Decoder, Encoder};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
@ -40,7 +40,6 @@ pub struct Codec {
|
||||||
// encoder part
|
// encoder part
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
encoder: encoder::MessageEncoder<Response<()>>,
|
encoder: encoder::MessageEncoder<Response<()>>,
|
||||||
// headers_size: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Codec {
|
impl Default for Codec {
|
||||||
|
@ -67,13 +66,11 @@ impl Codec {
|
||||||
};
|
};
|
||||||
Codec {
|
Codec {
|
||||||
config,
|
config,
|
||||||
|
flags,
|
||||||
decoder: decoder::MessageDecoder::default(),
|
decoder: decoder::MessageDecoder::default(),
|
||||||
payload: None,
|
payload: None,
|
||||||
version: Version::HTTP_11,
|
version: Version::HTTP_11,
|
||||||
ctype: ConnectionType::Close,
|
ctype: ConnectionType::Close,
|
||||||
|
|
||||||
flags,
|
|
||||||
// headers_size: 0,
|
|
||||||
encoder: encoder::MessageEncoder::default(),
|
encoder: encoder::MessageEncoder::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::{fmt, io};
|
use std::{fmt, io, net};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed, FramedParts};
|
use actix_codec::{Decoder, Encoder, Framed, FramedParts};
|
||||||
|
use actix_server_config::IoStream;
|
||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
use actix_utils::cloneable::CloneableService;
|
use actix_utils::cloneable::CloneableService;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
@ -81,6 +82,7 @@ where
|
||||||
expect: CloneableService<X>,
|
expect: CloneableService<X>,
|
||||||
upgrade: Option<CloneableService<U>>,
|
upgrade: Option<CloneableService<U>>,
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
|
peer_addr: Option<net::SocketAddr>,
|
||||||
error: Option<DispatchError>,
|
error: Option<DispatchError>,
|
||||||
|
|
||||||
state: State<S, B, X>,
|
state: State<S, B, X>,
|
||||||
|
@ -161,7 +163,7 @@ impl PartialEq for PollResponse {
|
||||||
|
|
||||||
impl<T, S, B, X, U> Dispatcher<T, S, B, X, U>
|
impl<T, S, B, X, U> Dispatcher<T, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
@ -220,14 +222,15 @@ where
|
||||||
|
|
||||||
Dispatcher {
|
Dispatcher {
|
||||||
inner: DispatcherState::Normal(InnerDispatcher {
|
inner: DispatcherState::Normal(InnerDispatcher {
|
||||||
io,
|
|
||||||
codec,
|
|
||||||
read_buf,
|
|
||||||
write_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
|
write_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
|
||||||
payload: None,
|
payload: None,
|
||||||
state: State::None,
|
state: State::None,
|
||||||
error: None,
|
error: None,
|
||||||
|
peer_addr: io.peer_addr(),
|
||||||
messages: VecDeque::new(),
|
messages: VecDeque::new(),
|
||||||
|
io,
|
||||||
|
codec,
|
||||||
|
read_buf,
|
||||||
service,
|
service,
|
||||||
expect,
|
expect,
|
||||||
upgrade,
|
upgrade,
|
||||||
|
@ -241,7 +244,7 @@ where
|
||||||
|
|
||||||
impl<T, S, B, X, U> InnerDispatcher<T, S, B, X, U>
|
impl<T, S, B, X, U> InnerDispatcher<T, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
@ -490,6 +493,7 @@ where
|
||||||
match msg {
|
match msg {
|
||||||
Message::Item(mut req) => {
|
Message::Item(mut req) => {
|
||||||
let pl = self.codec.message_type();
|
let pl = self.codec.message_type();
|
||||||
|
req.head_mut().peer_addr = self.peer_addr;
|
||||||
|
|
||||||
if pl == MessageType::Stream && self.upgrade.is_some() {
|
if pl == MessageType::Stream && self.upgrade.is_some() {
|
||||||
self.messages.push_back(DispatcherMessage::Upgrade(req));
|
self.messages.push_back(DispatcherMessage::Upgrade(req));
|
||||||
|
@ -649,7 +653,7 @@ where
|
||||||
|
|
||||||
impl<T, S, B, X, U> Future for Dispatcher<T, S, B, X, U>
|
impl<T, S, B, X, U> Future for Dispatcher<T, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::Framed;
|
||||||
use actix_server_config::{Io, ServerConfig as SrvConfig};
|
use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig};
|
||||||
use actix_service::{IntoNewService, NewService, Service};
|
use actix_service::{IntoNewService, NewService, Service};
|
||||||
use actix_utils::cloneable::CloneableService;
|
use actix_utils::cloneable::CloneableService;
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, FutureResult};
|
||||||
|
@ -104,7 +104,7 @@ where
|
||||||
|
|
||||||
impl<T, P, S, B, X, U> NewService<SrvConfig> for H1Service<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> NewService<SrvConfig> for H1Service<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: NewService<SrvConfig, Request = Request>,
|
S: NewService<SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
@ -161,7 +161,7 @@ where
|
||||||
|
|
||||||
impl<T, P, S, B, X, U> Future for H1ServiceResponse<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> Future for H1ServiceResponse<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: NewService<SrvConfig, Request = Request>,
|
S: NewService<SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
@ -245,7 +245,7 @@ where
|
||||||
|
|
||||||
impl<T, P, S, B, X, U> Service for H1ServiceHandler<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> Service for H1ServiceHandler<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
@ -309,7 +309,7 @@ pub struct OneRequest<T, P> {
|
||||||
|
|
||||||
impl<T, P> OneRequest<T, P>
|
impl<T, P> OneRequest<T, P>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
{
|
{
|
||||||
/// Create new `H1SimpleService` instance.
|
/// Create new `H1SimpleService` instance.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
@ -322,7 +322,7 @@ where
|
||||||
|
|
||||||
impl<T, P> NewService<SrvConfig> for OneRequest<T, P>
|
impl<T, P> NewService<SrvConfig> for OneRequest<T, P>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
{
|
{
|
||||||
type Request = Io<T, P>;
|
type Request = Io<T, P>;
|
||||||
type Response = (Request, Framed<T, Codec>);
|
type Response = (Request, Framed<T, Codec>);
|
||||||
|
@ -348,7 +348,7 @@ pub struct OneRequestService<T, P> {
|
||||||
|
|
||||||
impl<T, P> Service for OneRequestService<T, P>
|
impl<T, P> Service for OneRequestService<T, P>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
{
|
{
|
||||||
type Request = Io<T, P>;
|
type Request = Io<T, P>;
|
||||||
type Response = (Request, Framed<T, Codec>);
|
type Response = (Request, Framed<T, Codec>);
|
||||||
|
@ -372,14 +372,14 @@ where
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub struct OneRequestServiceResponse<T>
|
pub struct OneRequestServiceResponse<T>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
{
|
{
|
||||||
framed: Option<Framed<T, Codec>>,
|
framed: Option<Framed<T, Codec>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Future for OneRequestServiceResponse<T>
|
impl<T> Future for OneRequestServiceResponse<T>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
{
|
{
|
||||||
type Item = (Request, Framed<T, Codec>);
|
type Item = (Request, Framed<T, Codec>);
|
||||||
type Error = ParseError;
|
type Error = ParseError;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::{fmt, mem};
|
use std::{fmt, mem, net};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
use actix_codec::{AsyncRead, AsyncWrite};
|
||||||
|
use actix_server_config::IoStream;
|
||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
use actix_utils::cloneable::CloneableService;
|
use actix_utils::cloneable::CloneableService;
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
@ -29,14 +30,11 @@ use crate::response::Response;
|
||||||
const CHUNK_SIZE: usize = 16_384;
|
const CHUNK_SIZE: usize = 16_384;
|
||||||
|
|
||||||
/// Dispatcher for HTTP/2 protocol
|
/// Dispatcher for HTTP/2 protocol
|
||||||
pub struct Dispatcher<
|
pub struct Dispatcher<T: IoStream, S: Service<Request = Request>, B: MessageBody> {
|
||||||
T: AsyncRead + AsyncWrite,
|
|
||||||
S: Service<Request = Request>,
|
|
||||||
B: MessageBody,
|
|
||||||
> {
|
|
||||||
service: CloneableService<S>,
|
service: CloneableService<S>,
|
||||||
connection: Connection<T, Bytes>,
|
connection: Connection<T, Bytes>,
|
||||||
config: ServiceConfig,
|
config: ServiceConfig,
|
||||||
|
peer_addr: Option<net::SocketAddr>,
|
||||||
ka_expire: Instant,
|
ka_expire: Instant,
|
||||||
ka_timer: Option<Delay>,
|
ka_timer: Option<Delay>,
|
||||||
_t: PhantomData<B>,
|
_t: PhantomData<B>,
|
||||||
|
@ -44,7 +42,7 @@ pub struct Dispatcher<
|
||||||
|
|
||||||
impl<T, S, B> Dispatcher<T, S, B>
|
impl<T, S, B> Dispatcher<T, S, B>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
|
@ -56,6 +54,7 @@ where
|
||||||
connection: Connection<T, Bytes>,
|
connection: Connection<T, Bytes>,
|
||||||
config: ServiceConfig,
|
config: ServiceConfig,
|
||||||
timeout: Option<Delay>,
|
timeout: Option<Delay>,
|
||||||
|
peer_addr: Option<net::SocketAddr>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// let keepalive = config.keep_alive_enabled();
|
// let keepalive = config.keep_alive_enabled();
|
||||||
// let flags = if keepalive {
|
// let flags = if keepalive {
|
||||||
|
@ -76,9 +75,10 @@ where
|
||||||
Dispatcher {
|
Dispatcher {
|
||||||
service,
|
service,
|
||||||
config,
|
config,
|
||||||
|
peer_addr,
|
||||||
|
connection,
|
||||||
ka_expire,
|
ka_expire,
|
||||||
ka_timer,
|
ka_timer,
|
||||||
connection,
|
|
||||||
_t: PhantomData,
|
_t: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ where
|
||||||
|
|
||||||
impl<T, S, B> Future for Dispatcher<T, S, B>
|
impl<T, S, B> Future for Dispatcher<T, S, B>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
|
@ -117,6 +117,7 @@ where
|
||||||
head.method = parts.method;
|
head.method = parts.method;
|
||||||
head.version = parts.version;
|
head.version = parts.version;
|
||||||
head.headers = parts.headers.into();
|
head.headers = parts.headers.into();
|
||||||
|
head.peer_addr = self.peer_addr;
|
||||||
tokio_current_thread::spawn(ServiceResponse::<S::Future, B> {
|
tokio_current_thread::spawn(ServiceResponse::<S::Future, B> {
|
||||||
state: ServiceResponseState::ServiceCall(
|
state: ServiceResponseState::ServiceCall(
|
||||||
self.service.call(req),
|
self.service.call(req),
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::marker::PhantomData;
|
||||||
use std::{io, net};
|
use std::{io, net};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||||
use actix_server_config::{Io, ServerConfig as SrvConfig};
|
use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig};
|
||||||
use actix_service::{IntoNewService, NewService, Service};
|
use actix_service::{IntoNewService, NewService, Service};
|
||||||
use actix_utils::cloneable::CloneableService;
|
use actix_utils::cloneable::CloneableService;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
@ -63,7 +63,7 @@ where
|
||||||
|
|
||||||
impl<T, P, S, B> NewService<SrvConfig> for H2Service<T, P, S, B>
|
impl<T, P, S, B> NewService<SrvConfig> for H2Service<T, P, S, B>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: NewService<SrvConfig, Request = Request>,
|
S: NewService<SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
@ -95,7 +95,7 @@ pub struct H2ServiceResponse<T, P, S: NewService<SrvConfig, Request = Request>,
|
||||||
|
|
||||||
impl<T, P, S, B> Future for H2ServiceResponse<T, P, S, B>
|
impl<T, P, S, B> Future for H2ServiceResponse<T, P, S, B>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: NewService<SrvConfig, Request = Request>,
|
S: NewService<SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Response: Into<Response<B>>,
|
S::Response: Into<Response<B>>,
|
||||||
|
@ -140,7 +140,7 @@ where
|
||||||
|
|
||||||
impl<T, P, S, B> Service for H2ServiceHandler<T, P, S, B>
|
impl<T, P, S, B> Service for H2ServiceHandler<T, P, S, B>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
|
@ -161,17 +161,20 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||||
|
let io = req.into_parts().0;
|
||||||
|
let peer_addr = io.peer_addr();
|
||||||
H2ServiceHandlerResponse {
|
H2ServiceHandlerResponse {
|
||||||
state: State::Handshake(
|
state: State::Handshake(
|
||||||
Some(self.srv.clone()),
|
Some(self.srv.clone()),
|
||||||
Some(self.cfg.clone()),
|
Some(self.cfg.clone()),
|
||||||
server::handshake(req.into_parts().0),
|
peer_addr,
|
||||||
|
server::handshake(io),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum State<T: AsyncRead + AsyncWrite, S: Service<Request = Request>, B: MessageBody>
|
enum State<T: IoStream, S: Service<Request = Request>, B: MessageBody>
|
||||||
where
|
where
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
{
|
{
|
||||||
|
@ -179,13 +182,14 @@ where
|
||||||
Handshake(
|
Handshake(
|
||||||
Option<CloneableService<S>>,
|
Option<CloneableService<S>>,
|
||||||
Option<ServiceConfig>,
|
Option<ServiceConfig>,
|
||||||
|
Option<net::SocketAddr>,
|
||||||
Handshake<T, Bytes>,
|
Handshake<T, Bytes>,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct H2ServiceHandlerResponse<T, S, B>
|
pub struct H2ServiceHandlerResponse<T, S, B>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
|
@ -197,7 +201,7 @@ where
|
||||||
|
|
||||||
impl<T, S, B> Future for H2ServiceHandlerResponse<T, S, B>
|
impl<T, S, B> Future for H2ServiceHandlerResponse<T, S, B>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
|
@ -210,24 +214,28 @@ where
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::Incoming(ref mut disp) => disp.poll(),
|
State::Incoming(ref mut disp) => disp.poll(),
|
||||||
State::Handshake(ref mut srv, ref mut config, ref mut handshake) => {
|
State::Handshake(
|
||||||
match handshake.poll() {
|
ref mut srv,
|
||||||
Ok(Async::Ready(conn)) => {
|
ref mut config,
|
||||||
self.state = State::Incoming(Dispatcher::new(
|
ref peer_addr,
|
||||||
srv.take().unwrap(),
|
ref mut handshake,
|
||||||
conn,
|
) => match handshake.poll() {
|
||||||
config.take().unwrap(),
|
Ok(Async::Ready(conn)) => {
|
||||||
None,
|
self.state = State::Incoming(Dispatcher::new(
|
||||||
));
|
srv.take().unwrap(),
|
||||||
self.poll()
|
conn,
|
||||||
}
|
config.take().unwrap(),
|
||||||
Ok(Async::NotReady) => Ok(Async::NotReady),
|
None,
|
||||||
Err(err) => {
|
peer_addr.clone(),
|
||||||
trace!("H2 handshake error: {}", err);
|
));
|
||||||
Err(err.into())
|
self.poll()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
Ok(Async::NotReady) => Ok(Async::NotReady),
|
||||||
|
Err(err) => {
|
||||||
|
trace!("H2 handshake error: {}", err);
|
||||||
|
Err(err.into())
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ impl Response {
|
||||||
STATIC_RESP!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE);
|
STATIC_RESP!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE);
|
||||||
STATIC_RESP!(RangeNotSatisfiable, StatusCode::RANGE_NOT_SATISFIABLE);
|
STATIC_RESP!(RangeNotSatisfiable, StatusCode::RANGE_NOT_SATISFIABLE);
|
||||||
STATIC_RESP!(ExpectationFailed, StatusCode::EXPECTATION_FAILED);
|
STATIC_RESP!(ExpectationFailed, StatusCode::EXPECTATION_FAILED);
|
||||||
|
STATIC_RESP!(UnprocessableEntity, StatusCode::UNPROCESSABLE_ENTITY);
|
||||||
|
|
||||||
STATIC_RESP!(InternalServerError, StatusCode::INTERNAL_SERVER_ERROR);
|
STATIC_RESP!(InternalServerError, StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
STATIC_RESP!(NotImplemented, StatusCode::NOT_IMPLEMENTED);
|
STATIC_RESP!(NotImplemented, StatusCode::NOT_IMPLEMENTED);
|
||||||
|
|
|
@ -12,7 +12,6 @@ pub mod body;
|
||||||
mod builder;
|
mod builder;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
mod config;
|
mod config;
|
||||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust", feature = "brotli"))]
|
|
||||||
pub mod encoding;
|
pub mod encoding;
|
||||||
mod extensions;
|
mod extensions;
|
||||||
mod header;
|
mod header;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::cell::{Ref, RefCell, RefMut};
|
use std::cell::{Ref, RefCell, RefMut};
|
||||||
|
use std::net;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
@ -43,6 +44,7 @@ pub struct RequestHead {
|
||||||
pub version: Version,
|
pub version: Version,
|
||||||
pub headers: HeaderMap,
|
pub headers: HeaderMap,
|
||||||
pub extensions: RefCell<Extensions>,
|
pub extensions: RefCell<Extensions>,
|
||||||
|
pub peer_addr: Option<net::SocketAddr>,
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +56,7 @@ impl Default for RequestHead {
|
||||||
version: Version::HTTP_11,
|
version: Version::HTTP_11,
|
||||||
headers: HeaderMap::with_capacity(16),
|
headers: HeaderMap::with_capacity(16),
|
||||||
flags: Flags::empty(),
|
flags: Flags::empty(),
|
||||||
|
peer_addr: None,
|
||||||
extensions: RefCell::new(Extensions::new()),
|
extensions: RefCell::new(Extensions::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::cell::{Ref, RefMut};
|
use std::cell::{Ref, RefMut};
|
||||||
use std::fmt;
|
use std::{fmt, net};
|
||||||
|
|
||||||
use http::{header, Method, Uri, Version};
|
use http::{header, Method, Uri, Version};
|
||||||
|
|
||||||
|
@ -139,6 +139,7 @@ impl<P> Request<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if request requires connection upgrade
|
/// Check if request requires connection upgrade
|
||||||
|
#[inline]
|
||||||
pub fn upgrade(&self) -> bool {
|
pub fn upgrade(&self) -> bool {
|
||||||
if let Some(conn) = self.head().headers.get(header::CONNECTION) {
|
if let Some(conn) = self.head().headers.get(header::CONNECTION) {
|
||||||
if let Ok(s) = conn.to_str() {
|
if let Ok(s) = conn.to_str() {
|
||||||
|
@ -147,6 +148,15 @@ impl<P> Request<P> {
|
||||||
}
|
}
|
||||||
self.head().method == Method::CONNECT
|
self.head().method == Method::CONNECT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Peer socket address
|
||||||
|
///
|
||||||
|
/// Peer address is actual socket address, if proxy is used in front of
|
||||||
|
/// actix http server, then peer address would be address of this proxy.
|
||||||
|
#[inline]
|
||||||
|
pub fn peer_addr(&self) -> Option<net::SocketAddr> {
|
||||||
|
self.head().peer_addr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> fmt::Debug for Request<P> {
|
impl<P> fmt::Debug for Request<P> {
|
||||||
|
@ -168,3 +178,28 @@ impl<P> fmt::Debug for Request<P> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use http::HttpTryFrom;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_basics() {
|
||||||
|
let msg = Message::new();
|
||||||
|
let mut req = Request::from(msg);
|
||||||
|
req.headers_mut().insert(
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
header::HeaderValue::from_static("text/plain"),
|
||||||
|
);
|
||||||
|
assert!(req.headers().contains_key(header::CONTENT_TYPE));
|
||||||
|
|
||||||
|
*req.uri_mut() = Uri::try_from("/index.html?q=1").unwrap();
|
||||||
|
assert_eq!(req.uri().path(), "/index.html");
|
||||||
|
assert_eq!(req.uri().query(), Some("q=1"));
|
||||||
|
|
||||||
|
let s = format!("{:?}", req);
|
||||||
|
println!("T: {:?}", s);
|
||||||
|
assert!(s.contains("Request HTTP/1.1 GET:/index.html"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::{fmt, io};
|
use std::{fmt, io, net};
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||||
use actix_server_config::{Io as ServerIo, Protocol, ServerConfig as SrvConfig};
|
use actix_server_config::{
|
||||||
|
Io as ServerIo, IoStream, Protocol, ServerConfig as SrvConfig,
|
||||||
|
};
|
||||||
use actix_service::{IntoNewService, NewService, Service};
|
use actix_service::{IntoNewService, NewService, Service};
|
||||||
use actix_utils::cloneable::CloneableService;
|
use actix_utils::cloneable::CloneableService;
|
||||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||||
|
@ -128,7 +130,7 @@ where
|
||||||
|
|
||||||
impl<T, P, S, B, X, U> NewService<SrvConfig> for HttpService<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> NewService<SrvConfig> for HttpService<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: NewService<SrvConfig, Request = Request>,
|
S: NewService<SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
|
@ -182,7 +184,7 @@ pub struct HttpServiceResponse<
|
||||||
|
|
||||||
impl<T, P, S, B, X, U> Future for HttpServiceResponse<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> Future for HttpServiceResponse<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: NewService<SrvConfig, Request = Request>,
|
S: NewService<SrvConfig, Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::InitError: fmt::Debug,
|
S::InitError: fmt::Debug,
|
||||||
|
@ -268,7 +270,7 @@ where
|
||||||
|
|
||||||
impl<T, P, S, B, X, U> Service for HttpServiceHandler<T, P, S, B, X, U>
|
impl<T, P, S, B, X, U> Service for HttpServiceHandler<T, P, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
|
@ -317,6 +319,7 @@ where
|
||||||
let (io, _, proto) = req.into_parts();
|
let (io, _, proto) = req.into_parts();
|
||||||
match proto {
|
match proto {
|
||||||
Protocol::Http2 => {
|
Protocol::Http2 => {
|
||||||
|
let peer_addr = io.peer_addr();
|
||||||
let io = Io {
|
let io = Io {
|
||||||
inner: io,
|
inner: io,
|
||||||
unread: None,
|
unread: None,
|
||||||
|
@ -326,6 +329,7 @@ where
|
||||||
server::handshake(io),
|
server::handshake(io),
|
||||||
self.cfg.clone(),
|
self.cfg.clone(),
|
||||||
self.srv.clone(),
|
self.srv.clone(),
|
||||||
|
peer_addr,
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,7 +361,7 @@ where
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
X: Service<Request = Request, Response = Request>,
|
X: Service<Request = Request, Response = Request>,
|
||||||
X::Error: Into<Error>,
|
X::Error: Into<Error>,
|
||||||
|
@ -376,12 +380,19 @@ where
|
||||||
Option<CloneableService<U>>,
|
Option<CloneableService<U>>,
|
||||||
)>,
|
)>,
|
||||||
),
|
),
|
||||||
Handshake(Option<(Handshake<Io<T>, Bytes>, ServiceConfig, CloneableService<S>)>),
|
Handshake(
|
||||||
|
Option<(
|
||||||
|
Handshake<Io<T>, Bytes>,
|
||||||
|
ServiceConfig,
|
||||||
|
CloneableService<S>,
|
||||||
|
Option<net::SocketAddr>,
|
||||||
|
)>,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HttpServiceHandlerResponse<T, S, B, X, U>
|
pub struct HttpServiceHandlerResponse<T, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
|
@ -399,7 +410,7 @@ const HTTP2_PREFACE: [u8; 14] = *b"PRI * HTTP/2.0";
|
||||||
|
|
||||||
impl<T, S, B, X, U> Future for HttpServiceHandlerResponse<T, S, B, X, U>
|
impl<T, S, B, X, U> Future for HttpServiceHandlerResponse<T, S, B, X, U>
|
||||||
where
|
where
|
||||||
T: AsyncRead + AsyncWrite,
|
T: IoStream,
|
||||||
S: Service<Request = Request>,
|
S: Service<Request = Request>,
|
||||||
S::Error: Into<Error>,
|
S::Error: Into<Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
|
@ -437,12 +448,17 @@ where
|
||||||
}
|
}
|
||||||
let (io, buf, cfg, srv, expect, upgrade) = data.take().unwrap();
|
let (io, buf, cfg, srv, expect, upgrade) = data.take().unwrap();
|
||||||
if buf[..14] == HTTP2_PREFACE[..] {
|
if buf[..14] == HTTP2_PREFACE[..] {
|
||||||
|
let peer_addr = io.peer_addr();
|
||||||
let io = Io {
|
let io = Io {
|
||||||
inner: io,
|
inner: io,
|
||||||
unread: Some(buf),
|
unread: Some(buf),
|
||||||
};
|
};
|
||||||
self.state =
|
self.state = State::Handshake(Some((
|
||||||
State::Handshake(Some((server::handshake(io), cfg, srv)));
|
server::handshake(io),
|
||||||
|
cfg,
|
||||||
|
srv,
|
||||||
|
peer_addr,
|
||||||
|
)));
|
||||||
} else {
|
} else {
|
||||||
self.state = State::H1(h1::Dispatcher::with_timeout(
|
self.state = State::H1(h1::Dispatcher::with_timeout(
|
||||||
io,
|
io,
|
||||||
|
@ -470,8 +486,8 @@ where
|
||||||
} else {
|
} else {
|
||||||
panic!()
|
panic!()
|
||||||
};
|
};
|
||||||
let (_, cfg, srv) = data.take().unwrap();
|
let (_, cfg, srv, peer_addr) = data.take().unwrap();
|
||||||
self.state = State::H2(Dispatcher::new(srv, conn, cfg, None));
|
self.state = State::H2(Dispatcher::new(srv, conn, cfg, None, peer_addr));
|
||||||
self.poll()
|
self.poll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,3 +539,25 @@ impl<T: AsyncWrite> AsyncWrite for Io<T> {
|
||||||
self.inner.write_buf(buf)
|
self.inner.write_buf(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: IoStream> IoStream for Io<T> {
|
||||||
|
#[inline]
|
||||||
|
fn peer_addr(&self) -> Option<net::SocketAddr> {
|
||||||
|
self.inner.peer_addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
|
||||||
|
self.inner.set_nodelay(nodelay)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_linger(&mut self, dur: Option<std::time::Duration>) -> io::Result<()> {
|
||||||
|
self.inner.set_linger(dur)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_keepalive(&mut self, dur: Option<std::time::Duration>) -> io::Result<()> {
|
||||||
|
self.inner.set_keepalive(dur)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::io;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite};
|
use actix_codec::{AsyncRead, AsyncWrite};
|
||||||
|
use actix_server_config::IoStream;
|
||||||
use bytes::{Buf, Bytes, BytesMut};
|
use bytes::{Buf, Bytes, BytesMut};
|
||||||
use futures::{Async, Poll};
|
use futures::{Async, Poll};
|
||||||
use http::header::{self, HeaderName, HeaderValue};
|
use http::header::{self, HeaderName, HeaderValue};
|
||||||
|
@ -253,3 +254,17 @@ impl AsyncWrite for TestBuffer {
|
||||||
Ok(Async::NotReady)
|
Ok(Async::NotReady)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IoStream for TestBuffer {
|
||||||
|
fn set_nodelay(&mut self, _nodelay: bool) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_linger(&mut self, _dur: Option<std::time::Duration>) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_keepalive(&mut self, _dur: Option<std::time::Duration>) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -35,7 +35,10 @@ fn test_h1() {
|
||||||
.keep_alive(KeepAlive::Disabled)
|
.keep_alive(KeepAlive::Disabled)
|
||||||
.client_timeout(1000)
|
.client_timeout(1000)
|
||||||
.client_disconnect(1000)
|
.client_disconnect(1000)
|
||||||
.h1(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
.h1(|req: Request| {
|
||||||
|
assert!(req.peer_addr().is_some());
|
||||||
|
future::ok::<_, ()>(Response::Ok().finish())
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let response = srv.block_on(srv.get("/").send()).unwrap();
|
let response = srv.block_on(srv.get("/").send()).unwrap();
|
||||||
|
@ -50,6 +53,7 @@ fn test_h1_2() {
|
||||||
.client_timeout(1000)
|
.client_timeout(1000)
|
||||||
.client_disconnect(1000)
|
.client_disconnect(1000)
|
||||||
.finish(|req: Request| {
|
.finish(|req: Request| {
|
||||||
|
assert!(req.peer_addr().is_some());
|
||||||
assert_eq!(req.version(), http::Version::HTTP_11);
|
assert_eq!(req.version(), http::Version::HTTP_11);
|
||||||
future::ok::<_, ()>(Response::Ok().finish())
|
future::ok::<_, ()>(Response::Ok().finish())
|
||||||
})
|
})
|
||||||
|
@ -115,6 +119,7 @@ fn test_h2_1() -> std::io::Result<()> {
|
||||||
.and_then(
|
.and_then(
|
||||||
HttpService::build()
|
HttpService::build()
|
||||||
.finish(|req: Request| {
|
.finish(|req: Request| {
|
||||||
|
assert!(req.peer_addr().is_some());
|
||||||
assert_eq!(req.version(), http::Version::HTTP_2);
|
assert_eq!(req.version(), http::Version::HTTP_2);
|
||||||
future::ok::<_, Error>(Response::Ok().finish())
|
future::ok::<_, Error>(Response::Ok().finish())
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,7 +18,7 @@ name = "actix_multipart"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = "1.0.0-alpha.3"
|
actix-web = "1.0.0-alpha.6"
|
||||||
actix-service = "0.3.4"
|
actix-service = "0.3.4"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
derive_more = "0.14"
|
derive_more = "0.14"
|
||||||
|
@ -31,4 +31,4 @@ twoway = "0.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "0.2.2"
|
actix-rt = "0.2.2"
|
||||||
actix-http = "0.1.0-alpha.3"
|
actix-http = "0.1.0"
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use actix_service::{Service, Transform};
|
use actix_service::{Service, Transform};
|
||||||
use actix_web::cookie::{Cookie, CookieJar, Key, SameSite};
|
use actix_web::cookie::{Cookie, CookieJar, Key, SameSite};
|
||||||
|
@ -27,7 +28,6 @@ use derive_more::{Display, From};
|
||||||
use futures::future::{ok, Future, FutureResult};
|
use futures::future::{ok, Future, FutureResult};
|
||||||
use futures::Poll;
|
use futures::Poll;
|
||||||
use serde_json::error::Error as JsonError;
|
use serde_json::error::Error as JsonError;
|
||||||
use time::Duration;
|
|
||||||
|
|
||||||
use crate::Session;
|
use crate::Session;
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ impl CookieSessionInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(max_age) = self.max_age {
|
if let Some(max_age) = self.max_age {
|
||||||
cookie.set_max_age(max_age);
|
cookie.set_max_age(time::Duration::from_std(max_age).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(same_site) = self.same_site {
|
if let Some(same_site) = self.same_site {
|
||||||
|
@ -317,6 +317,7 @@ where
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use actix_web::{test, web, App};
|
use actix_web::{test, web, App};
|
||||||
|
use bytes::Bytes;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cookie_session() {
|
fn cookie_session() {
|
||||||
|
@ -338,6 +339,26 @@ mod tests {
|
||||||
.is_some());
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn private_cookie() {
|
||||||
|
let mut app = test::init_service(
|
||||||
|
App::new()
|
||||||
|
.wrap(CookieSession::private(&[0; 32]).secure(false))
|
||||||
|
.service(web::resource("/").to(|ses: Session| {
|
||||||
|
let _ = ses.set("counter", 100);
|
||||||
|
"test"
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
let request = test::TestRequest::get().to_request();
|
||||||
|
let response = test::block_on(app.call(request)).unwrap();
|
||||||
|
assert!(response
|
||||||
|
.response()
|
||||||
|
.cookies()
|
||||||
|
.find(|c| c.name() == "actix-session")
|
||||||
|
.is_some());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn cookie_session_extractor() {
|
fn cookie_session_extractor() {
|
||||||
let mut app = test::init_service(
|
let mut app = test::init_service(
|
||||||
|
@ -357,4 +378,44 @@ mod tests {
|
||||||
.find(|c| c.name() == "actix-session")
|
.find(|c| c.name() == "actix-session")
|
||||||
.is_some());
|
.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basics() {
|
||||||
|
let mut app = test::init_service(
|
||||||
|
App::new()
|
||||||
|
.wrap(
|
||||||
|
CookieSession::signed(&[0; 32])
|
||||||
|
.path("/test/")
|
||||||
|
.name("actix-test")
|
||||||
|
.domain("localhost")
|
||||||
|
.http_only(true)
|
||||||
|
.same_site(SameSite::Lax)
|
||||||
|
.max_age(Duration::from_secs(100)),
|
||||||
|
)
|
||||||
|
.service(web::resource("/").to(|ses: Session| {
|
||||||
|
let _ = ses.set("counter", 100);
|
||||||
|
"test"
|
||||||
|
}))
|
||||||
|
.service(web::resource("/test/").to(|ses: Session| {
|
||||||
|
let val: usize = ses.get("counter").unwrap().unwrap();
|
||||||
|
format!("counter: {}", val)
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
|
||||||
|
let request = test::TestRequest::get().to_request();
|
||||||
|
let response = test::block_on(app.call(request)).unwrap();
|
||||||
|
let cookie = response
|
||||||
|
.response()
|
||||||
|
.cookies()
|
||||||
|
.find(|c| c.name() == "actix-test")
|
||||||
|
.unwrap()
|
||||||
|
.clone();
|
||||||
|
assert_eq!(cookie.path().unwrap(), "/test/");
|
||||||
|
|
||||||
|
let request = test::TestRequest::with_uri("/test/")
|
||||||
|
.cookie(cookie)
|
||||||
|
.to_request();
|
||||||
|
let body = test::read_response(&mut app, request);
|
||||||
|
assert_eq!(body, Bytes::from_static(b"counter: 100"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@ path = "src/lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "0.8.0"
|
actix = "0.8.0"
|
||||||
actix-web = "1.0.0-alpha.5"
|
actix-web = "1.0.0-alpha.5"
|
||||||
actix-http = "0.1.0-alpha.5"
|
actix-http = "0.1.0"
|
||||||
actix-codec = "0.1.2"
|
actix-codec = "0.1.2"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
|
actix-http-test = { version = "0.1.0", features=["ssl"] }
|
||||||
|
|
|
@ -199,7 +199,7 @@ mod tests {
|
||||||
|
|
||||||
use actix::Actor;
|
use actix::Actor;
|
||||||
use actix_web::http::StatusCode;
|
use actix_web::http::StatusCode;
|
||||||
use actix_web::test::{block_on, call_success, init_service, TestRequest};
|
use actix_web::test::{block_on, call_service, init_service, TestRequest};
|
||||||
use actix_web::{web, App, HttpResponse};
|
use actix_web::{web, App, HttpResponse};
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ mod tests {
|
||||||
})));
|
})));
|
||||||
|
|
||||||
let req = TestRequest::with_uri("/test").to_request();
|
let req = TestRequest::with_uri("/test").to_request();
|
||||||
let mut resp = call_success(&mut srv, req);
|
let mut resp = call_service(&mut srv, req);
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
|
||||||
let body = block_on(resp.take_body().fold(
|
let body = block_on(resp.take_body().fold(
|
||||||
|
|
|
@ -17,6 +17,6 @@ syn = { version = "0.15", features = ["full", "parsing"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-web = { version = "1.0.0-alpha.6" }
|
actix-web = { version = "1.0.0-alpha.6" }
|
||||||
actix-http = { version = "0.1.0-alpha.5", features=["ssl"] }
|
actix-http = { version = "0.1.0", features=["ssl"] }
|
||||||
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
|
actix-http-test = { version = "0.1.0", features=["ssl"] }
|
||||||
futures = { version = "0.1" }
|
futures = { version = "0.1" }
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.1.1] - 2019-04-xx
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* `ClientRequest::if_true()` and `ClientRequest::if_some()` use instance instead of ref
|
||||||
|
|
||||||
|
|
||||||
|
## [0.1.0] - 2019-04-16
|
||||||
|
|
||||||
|
* No changes
|
||||||
|
|
||||||
|
|
||||||
## [0.1.0-alpha.6] - 2019-04-14
|
## [0.1.0-alpha.6] - 2019-04-14
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "awc"
|
name = "awc"
|
||||||
version = "0.1.0-alpha.6"
|
version = "0.1.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix http client."
|
description = "Actix http client."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -38,7 +38,7 @@ flate2-rust = ["actix-http/flate2-rust"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-codec = "0.1.2"
|
actix-codec = "0.1.2"
|
||||||
actix-service = "0.3.6"
|
actix-service = "0.3.6"
|
||||||
actix-http = "0.1.0-alpha.5"
|
actix-http = "0.1.0"
|
||||||
base64 = "0.10.1"
|
base64 = "0.10.1"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
derive_more = "0.14"
|
derive_more = "0.14"
|
||||||
|
@ -56,10 +56,10 @@ openssl = { version="0.10", optional = true }
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "0.2.2"
|
actix-rt = "0.2.2"
|
||||||
actix-web = { version = "1.0.0-alpha.6", features=["ssl"] }
|
actix-web = { version = "1.0.0-alpha.6", features=["ssl"] }
|
||||||
actix-http = { version = "0.1.0-alpha.5", features=["ssl"] }
|
actix-http = { version = "0.1.0", features=["ssl"] }
|
||||||
actix-http-test = { version = "0.1.0-alpha.3", features=["ssl"] }
|
actix-http-test = { version = "0.1.0", features=["ssl"] }
|
||||||
actix-utils = "0.3.4"
|
actix-utils = "0.3.4"
|
||||||
actix-server = { version = "0.4.1", features=["ssl"] }
|
actix-server = { version = "0.4.3", features=["ssl"] }
|
||||||
brotli2 = { version="0.3.2" }
|
brotli2 = { version="0.3.2" }
|
||||||
flate2 = { version="1.0.2" }
|
flate2 = { version="1.0.2" }
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
|
|
|
@ -1 +1,33 @@
|
||||||
# Actix http client [](https://travis-ci.org/actix/actix-web) [](https://codecov.io/gh/actix/actix-web) [](https://crates.io/crates/awc) [](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
# Actix http client [](https://travis-ci.org/actix/actix-web) [](https://codecov.io/gh/actix/actix-web) [](https://crates.io/crates/awc) [](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
|
An HTTP Client
|
||||||
|
|
||||||
|
## Documentation & community resources
|
||||||
|
|
||||||
|
* [User Guide](https://actix.rs/docs/)
|
||||||
|
* [API Documentation](https://docs.rs/awc/)
|
||||||
|
* [Chat on gitter](https://gitter.im/actix/actix)
|
||||||
|
* Cargo package: [awc](https://crates.io/crates/awc)
|
||||||
|
* Minimum supported Rust version: 1.33 or later
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use actix_rt::System;
|
||||||
|
use awc::Client;
|
||||||
|
use futures::future::{Future, lazy};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
System::new("test").block_on(lazy(|| {
|
||||||
|
let mut client = Client::default();
|
||||||
|
|
||||||
|
client.get("http://www.rust-lang.org") // <- Create request builder
|
||||||
|
.header("User-Agent", "Actix-web")
|
||||||
|
.send() // <- Send http request
|
||||||
|
.and_then(|response| { // <- server http response
|
||||||
|
println!("Response: {:?}", response);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -331,26 +331,28 @@ impl ClientRequest {
|
||||||
|
|
||||||
/// This method calls provided closure with builder reference if
|
/// This method calls provided closure with builder reference if
|
||||||
/// value is `true`.
|
/// value is `true`.
|
||||||
pub fn if_true<F>(mut self, value: bool, f: F) -> Self
|
pub fn if_true<F>(self, value: bool, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: FnOnce(&mut ClientRequest),
|
F: FnOnce(ClientRequest) -> ClientRequest,
|
||||||
{
|
{
|
||||||
if value {
|
if value {
|
||||||
f(&mut self);
|
f(self)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
}
|
}
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This method calls provided closure with builder reference if
|
/// This method calls provided closure with builder reference if
|
||||||
/// value is `Some`.
|
/// value is `Some`.
|
||||||
pub fn if_some<T, F>(mut self, value: Option<T>, f: F) -> Self
|
pub fn if_some<T, F>(self, value: Option<T>, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: FnOnce(T, &mut ClientRequest),
|
F: FnOnce(T, ClientRequest) -> ClientRequest,
|
||||||
{
|
{
|
||||||
if let Some(val) = value {
|
if let Some(val) = value {
|
||||||
f(val, &mut self);
|
f(val, self)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
}
|
}
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Complete request construction and send body.
|
/// Complete request construction and send body.
|
||||||
|
|
10
src/info.rs
10
src/info.rs
|
@ -30,7 +30,7 @@ impl ConnectionInfo {
|
||||||
let mut host = None;
|
let mut host = None;
|
||||||
let mut scheme = None;
|
let mut scheme = None;
|
||||||
let mut remote = None;
|
let mut remote = None;
|
||||||
let peer = None;
|
let mut peer = None;
|
||||||
|
|
||||||
// load forwarded header
|
// load forwarded header
|
||||||
for hdr in req.headers.get_all(&header::FORWARDED) {
|
for hdr in req.headers.get_all(&header::FORWARDED) {
|
||||||
|
@ -116,10 +116,10 @@ impl ConnectionInfo {
|
||||||
remote = h.split(',').next().map(|v| v.trim());
|
remote = h.split(',').next().map(|v| v.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if remote.is_none() {
|
if remote.is_none() {
|
||||||
// get peeraddr from socketaddr
|
// get peeraddr from socketaddr
|
||||||
// peer = req.peer_addr().map(|addr| format!("{}", addr));
|
peer = req.peer_addr.map(|addr| format!("{}", addr));
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionInfo {
|
ConnectionInfo {
|
||||||
|
|
|
@ -363,13 +363,6 @@ impl FormatText {
|
||||||
let rt = (rt.num_nanoseconds().unwrap_or(0) as f64) / 1_000_000.0;
|
let rt = (rt.num_nanoseconds().unwrap_or(0) as f64) / 1_000_000.0;
|
||||||
fmt.write_fmt(format_args!("{:.6}", rt))
|
fmt.write_fmt(format_args!("{:.6}", rt))
|
||||||
}
|
}
|
||||||
// FormatText::RemoteAddr => {
|
|
||||||
// if let Some(remote) = req.connection_info().remote() {
|
|
||||||
// return remote.fmt(fmt);
|
|
||||||
// } else {
|
|
||||||
// "-".fmt(fmt)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
FormatText::EnvironHeader(ref name) => {
|
FormatText::EnvironHeader(ref name) => {
|
||||||
if let Ok(val) = env::var(name) {
|
if let Ok(val) = env::var(name) {
|
||||||
fmt.write_fmt(format_args!("{}", val))
|
fmt.write_fmt(format_args!("{}", val))
|
||||||
|
@ -441,6 +434,14 @@ impl FormatText {
|
||||||
};
|
};
|
||||||
*self = FormatText::Str(s.to_string());
|
*self = FormatText::Str(s.to_string());
|
||||||
}
|
}
|
||||||
|
FormatText::RemoteAddr => {
|
||||||
|
let s = if let Some(remote) = req.connection_info().remote() {
|
||||||
|
FormatText::Str(remote.to_string())
|
||||||
|
} else {
|
||||||
|
FormatText::Str("-".to_string())
|
||||||
|
};
|
||||||
|
*self = s;
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::cell::{Ref, RefCell, RefMut};
|
use std::cell::{Ref, RefCell, RefMut};
|
||||||
use std::fmt;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::{fmt, net};
|
||||||
|
|
||||||
use actix_http::http::{HeaderMap, Method, Uri, Version};
|
use actix_http::http::{HeaderMap, Method, Uri, Version};
|
||||||
use actix_http::{Error, Extensions, HttpMessage, Message, Payload, RequestHead};
|
use actix_http::{Error, Extensions, HttpMessage, Message, Payload, RequestHead};
|
||||||
|
@ -170,6 +170,17 @@ impl HttpRequest {
|
||||||
self.url_for(name, &NO_PARAMS)
|
self.url_for(name, &NO_PARAMS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Peer socket address
|
||||||
|
///
|
||||||
|
/// Peer address is actual socket address, if proxy is used in front of
|
||||||
|
/// actix http server, then peer address would be address of this proxy.
|
||||||
|
///
|
||||||
|
/// To get client connection information `.connection_info()` should be used.
|
||||||
|
#[inline]
|
||||||
|
pub fn peer_addr(&self) -> Option<net::SocketAddr> {
|
||||||
|
self.head().peer_addr
|
||||||
|
}
|
||||||
|
|
||||||
/// Get *ConnectionInfo* for the current request.
|
/// Get *ConnectionInfo* for the current request.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn connection_info(&self) -> Ref<ConnectionInfo> {
|
pub fn connection_info(&self) -> Ref<ConnectionInfo> {
|
||||||
|
|
|
@ -307,11 +307,11 @@ pub(crate) mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let req = TestRequest::with_uri("/none").to_request();
|
let req = TestRequest::with_uri("/none").to_request();
|
||||||
let resp = TestRequest::block_on(srv.call(req)).unwrap();
|
let resp = block_on(srv.call(req)).unwrap();
|
||||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||||
|
|
||||||
let req = TestRequest::with_uri("/some").to_request();
|
let req = TestRequest::with_uri("/some").to_request();
|
||||||
let resp = TestRequest::block_on(srv.call(req)).unwrap();
|
let resp = block_on(srv.call(req)).unwrap();
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
match resp.response().body() {
|
match resp.response().body() {
|
||||||
ResponseBody::Body(Body::Bytes(ref b)) => {
|
ResponseBody::Body(Body::Bytes(ref b)) => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::cell::{Ref, RefMut};
|
use std::cell::{Ref, RefMut};
|
||||||
use std::fmt;
|
use std::{fmt, net};
|
||||||
|
|
||||||
use actix_http::body::{Body, MessageBody, ResponseBody};
|
use actix_http::body::{Body, MessageBody, ResponseBody};
|
||||||
use actix_http::http::{HeaderMap, Method, StatusCode, Uri, Version};
|
use actix_http::http::{HeaderMap, Method, StatusCode, Uri, Version};
|
||||||
|
@ -12,6 +12,7 @@ use futures::future::{ok, FutureResult, IntoFuture};
|
||||||
|
|
||||||
use crate::config::{AppConfig, AppService};
|
use crate::config::{AppConfig, AppService};
|
||||||
use crate::data::Data;
|
use crate::data::Data;
|
||||||
|
use crate::info::ConnectionInfo;
|
||||||
use crate::request::HttpRequest;
|
use crate::request::HttpRequest;
|
||||||
|
|
||||||
pub trait HttpServiceFactory {
|
pub trait HttpServiceFactory {
|
||||||
|
@ -134,6 +135,23 @@ impl ServiceRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Peer socket address
|
||||||
|
///
|
||||||
|
/// Peer address is actual socket address, if proxy is used in front of
|
||||||
|
/// actix http server, then peer address would be address of this proxy.
|
||||||
|
///
|
||||||
|
/// To get client connection information `ConnectionInfo` should be used.
|
||||||
|
#[inline]
|
||||||
|
pub fn peer_addr(&self) -> Option<net::SocketAddr> {
|
||||||
|
self.head().peer_addr
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get *ConnectionInfo* for the current request.
|
||||||
|
#[inline]
|
||||||
|
pub fn connection_info(&self) -> Ref<ConnectionInfo> {
|
||||||
|
ConnectionInfo::get(self.head(), &*self.app_config())
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a reference to the Path parameters.
|
/// Get a reference to the Path parameters.
|
||||||
///
|
///
|
||||||
/// Params is a container for url parameters.
|
/// Params is a container for url parameters.
|
||||||
|
|
65
src/test.rs
65
src/test.rs
|
@ -58,7 +58,7 @@ where
|
||||||
/// This function panics on nested call.
|
/// This function panics on nested call.
|
||||||
pub fn run_on<F, R>(f: F) -> R
|
pub fn run_on<F, R>(f: F) -> R
|
||||||
where
|
where
|
||||||
F: Fn() -> R,
|
F: FnOnce() -> R,
|
||||||
{
|
{
|
||||||
RT.with(move |rt| rt.borrow_mut().block_on(lazy(|| Ok::<_, ()>(f()))))
|
RT.with(move |rt| rt.borrow_mut().block_on(lazy(|| Ok::<_, ()>(f()))))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -117,7 +117,9 @@ where
|
||||||
S::InitError: std::fmt::Debug,
|
S::InitError: std::fmt::Debug,
|
||||||
{
|
{
|
||||||
let cfg = ServerConfig::new("127.0.0.1:8080".parse().unwrap());
|
let cfg = ServerConfig::new("127.0.0.1:8080".parse().unwrap());
|
||||||
block_on(app.into_new_service().new_service(&cfg)).unwrap()
|
let srv = app.into_new_service();
|
||||||
|
let fut = run_on(move || srv.new_service(&cfg));
|
||||||
|
block_on(fut).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calls service and waits for response future completion.
|
/// Calls service and waits for response future completion.
|
||||||
|
@ -146,7 +148,7 @@ where
|
||||||
S: Service<Request = R, Response = ServiceResponse<B>, Error = E>,
|
S: Service<Request = R, Response = ServiceResponse<B>, Error = E>,
|
||||||
E: std::fmt::Debug,
|
E: std::fmt::Debug,
|
||||||
{
|
{
|
||||||
block_on(app.call(req)).unwrap()
|
block_on(run_on(move || app.call(req))).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function that returns a response body of a TestRequest
|
/// Helper function that returns a response body of a TestRequest
|
||||||
|
@ -178,13 +180,15 @@ where
|
||||||
S: Service<Request = Request, Response = ServiceResponse<B>, Error = Error>,
|
S: Service<Request = Request, Response = ServiceResponse<B>, Error = Error>,
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
{
|
{
|
||||||
block_on(app.call(req).and_then(|mut resp: ServiceResponse<B>| {
|
block_on(run_on(move || {
|
||||||
resp.take_body()
|
app.call(req).and_then(|mut resp: ServiceResponse<B>| {
|
||||||
.fold(BytesMut::new(), move |mut body, chunk| {
|
resp.take_body()
|
||||||
body.extend_from_slice(&chunk);
|
.fold(BytesMut::new(), move |mut body, chunk| {
|
||||||
Ok::<_, Error>(body)
|
body.extend_from_slice(&chunk);
|
||||||
})
|
Ok::<_, Error>(body)
|
||||||
.map(|body: BytesMut| body.freeze())
|
})
|
||||||
|
.map(|body: BytesMut| body.freeze())
|
||||||
|
})
|
||||||
}))
|
}))
|
||||||
.unwrap_or_else(|_| panic!("read_response failed at block_on unwrap"))
|
.unwrap_or_else(|_| panic!("read_response failed at block_on unwrap"))
|
||||||
}
|
}
|
||||||
|
@ -229,17 +233,19 @@ where
|
||||||
B: MessageBody,
|
B: MessageBody,
|
||||||
T: DeserializeOwned,
|
T: DeserializeOwned,
|
||||||
{
|
{
|
||||||
block_on(app.call(req).and_then(|mut resp: ServiceResponse<B>| {
|
block_on(run_on(move || {
|
||||||
resp.take_body()
|
app.call(req).and_then(|mut resp: ServiceResponse<B>| {
|
||||||
.fold(BytesMut::new(), move |mut body, chunk| {
|
resp.take_body()
|
||||||
body.extend_from_slice(&chunk);
|
.fold(BytesMut::new(), move |mut body, chunk| {
|
||||||
Ok::<_, Error>(body)
|
body.extend_from_slice(&chunk);
|
||||||
})
|
Ok::<_, Error>(body)
|
||||||
.and_then(|body: BytesMut| {
|
})
|
||||||
ok(serde_json::from_slice(&body).unwrap_or_else(|_| {
|
.and_then(|body: BytesMut| {
|
||||||
panic!("read_response_json failed during deserialization")
|
ok(serde_json::from_slice(&body).unwrap_or_else(|_| {
|
||||||
}))
|
panic!("read_response_json failed during deserialization")
|
||||||
})
|
}))
|
||||||
|
})
|
||||||
|
})
|
||||||
}))
|
}))
|
||||||
.unwrap_or_else(|_| panic!("read_response_json failed at block_on unwrap"))
|
.unwrap_or_else(|_| panic!("read_response_json failed at block_on unwrap"))
|
||||||
}
|
}
|
||||||
|
@ -468,23 +474,6 @@ impl TestRequest {
|
||||||
req.set_route_data(Some(Rc::new(self.route_data)));
|
req.set_route_data(Some(Rc::new(self.route_data)));
|
||||||
(req, payload)
|
(req, payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the provided future, blocking the current thread until the future
|
|
||||||
/// completes.
|
|
||||||
///
|
|
||||||
/// This function can be used to synchronously block the current thread
|
|
||||||
/// until the provided `future` has resolved either successfully or with an
|
|
||||||
/// error. The result of the future is then returned from this function
|
|
||||||
/// call.
|
|
||||||
///
|
|
||||||
/// Note that this function is intended to be used only for testing purpose.
|
|
||||||
/// This function panics on nested call.
|
|
||||||
pub fn block_on<F>(f: F) -> Result<F::Item, F::Error>
|
|
||||||
where
|
|
||||||
F: Future,
|
|
||||||
{
|
|
||||||
block_on(f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.1.0] - 2019-04-16
|
||||||
|
|
||||||
|
* No changes
|
||||||
|
|
||||||
|
|
||||||
## [0.1.0-alpha.3] - 2019-04-02
|
## [0.1.0-alpha.3] - 2019-04-02
|
||||||
|
|
||||||
* Request functions accept path #743
|
* Request functions accept path #743
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-http-test"
|
name = "actix-http-test"
|
||||||
version = "0.1.0-alpha.3"
|
version = "0.1.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix http test server"
|
description = "Actix http test server"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -33,9 +33,9 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"]
|
||||||
actix-codec = "0.1.2"
|
actix-codec = "0.1.2"
|
||||||
actix-rt = "0.2.2"
|
actix-rt = "0.2.2"
|
||||||
actix-service = "0.3.6"
|
actix-service = "0.3.6"
|
||||||
actix-server = "0.4.1"
|
actix-server = "0.4.3"
|
||||||
actix-utils = "0.3.5"
|
actix-utils = "0.3.5"
|
||||||
awc = "0.1.0-alpha.5"
|
awc = "0.1.0"
|
||||||
|
|
||||||
base64 = "0.10"
|
base64 = "0.10"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
|
@ -56,4 +56,4 @@ openssl = { version="0.10", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-web = "1.0.0-alpha.5"
|
actix-web = "1.0.0-alpha.5"
|
||||||
actix-http = "0.1.0-alpha.5"
|
actix-http = "0.1.0"
|
||||||
|
|
|
@ -17,7 +17,7 @@ use futures::stream::once;
|
||||||
use rand::{distributions::Alphanumeric, Rng};
|
use rand::{distributions::Alphanumeric, Rng};
|
||||||
|
|
||||||
use actix_web::middleware::{BodyEncoding, Compress};
|
use actix_web::middleware::{BodyEncoding, Compress};
|
||||||
use actix_web::{http, test, web, App, HttpResponse, HttpServer};
|
use actix_web::{dev, http, test, web, App, HttpResponse, HttpServer};
|
||||||
|
|
||||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||||
Hello World Hello World Hello World Hello World Hello World \
|
Hello World Hello World Hello World Hello World Hello World \
|
||||||
|
@ -89,6 +89,39 @@ fn test_body_gzip() {
|
||||||
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
|
assert_eq!(Bytes::from(dec), Bytes::from_static(STR.as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||||
|
#[test]
|
||||||
|
fn test_body_gzip2() {
|
||||||
|
let mut srv = TestServer::new(|| {
|
||||||
|
h1::H1Service::new(
|
||||||
|
App::new()
|
||||||
|
.wrap(Compress::new(ContentEncoding::Gzip))
|
||||||
|
.service(web::resource("/").route(web::to(|| {
|
||||||
|
Response::Ok().body(STR).into_body::<dev::Body>()
|
||||||
|
}))),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut response = srv
|
||||||
|
.block_on(
|
||||||
|
srv.get("/")
|
||||||
|
.no_decompress()
|
||||||
|
.header(ACCEPT_ENCODING, "gzip")
|
||||||
|
.send(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
|
// read response
|
||||||
|
let bytes = srv.block_on(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()));
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_body_encoding_override() {
|
fn test_body_encoding_override() {
|
||||||
|
|
Loading…
Reference in New Issue