mirror of
https://github.com/fafhrd91/actix-web
synced 2025-07-23 17:28:19 +02:00
Compare commits
68 Commits
v2.0.0-alp
...
multipart-
Author | SHA1 | Date | |
---|---|---|---|
|
48476362a3 | ||
|
2b4256baab | ||
|
e5a50f423d | ||
|
8b8a9a995d | ||
|
74fa4060c2 | ||
|
c877840c07 | ||
|
20248daeda | ||
|
a08d8dab70 | ||
|
fbbb4a86e9 | ||
|
1d12ba9d5f | ||
|
8c54054844 | ||
|
1732ae8c79 | ||
|
3b860ebdc7 | ||
|
29ac6463e1 | ||
|
01613f334b | ||
|
30dcaf9da0 | ||
|
b0aa9395da | ||
|
a153374b61 | ||
|
a791aab418 | ||
|
cb705317b8 | ||
|
e8e0f98f96 | ||
|
c878f66d05 | ||
|
fac6dec3c9 | ||
|
232f71b3b5 | ||
|
8881c13e60 | ||
|
d006a7b31f | ||
|
3d64d565d9 | ||
|
c1deaaeb2f | ||
|
b81417c2fa | ||
|
4937c9f9c2 | ||
|
db1d6b7963 | ||
|
fa07415721 | ||
|
b4b3350b3e | ||
|
4a1695f719 | ||
|
1b8d747937 | ||
|
a43a005f59 | ||
|
a612b74aeb | ||
|
131c897099 | ||
|
ef3a33b9d6 | ||
|
5132257b0d | ||
|
0c1f5f9edc | ||
|
e4382e4fc1 | ||
|
a3ce371312 | ||
|
42258ee289 | ||
|
b92eafb839 | ||
|
3b2e78db47 | ||
|
63da1a5560 | ||
|
1f3ffe38e8 | ||
|
c23b6b3879 | ||
|
909c7c8b5b | ||
|
4a8a9ef405 | ||
|
6c9f9fff73 | ||
|
8df33f7a81 | ||
|
7ec5ca88a1 | ||
|
e5f3d88a4e | ||
|
0ba125444a | ||
|
6c226e47bd | ||
|
8c3f58db9d | ||
|
4921243add | ||
|
91b3fcf85c | ||
|
f2ba389496 | ||
|
439f02b6b1 | ||
|
e32da08a26 | ||
|
82110e0927 | ||
|
7b3354a9ad | ||
|
5243e8baca | ||
|
98903028c7 | ||
|
b7d44d6c4c |
37
CHANGES.md
37
CHANGES.md
@@ -1,5 +1,42 @@
|
||||
# Changes
|
||||
|
||||
## [2.0.0-rc] - 2019-12-20
|
||||
|
||||
### Changed
|
||||
|
||||
* Move `BodyEncoding` to `dev` module #1220
|
||||
|
||||
* Allow to set `peer_addr` for TestRequest #1074
|
||||
|
||||
* Make web::Data deref to Arc<T> #1214
|
||||
|
||||
* Rename `App::register_data()` to `App::app_data()`
|
||||
|
||||
* `HttpRequest::app_data<T>()` returns `Option<&T>` instead of `Option<&Data<T>>`
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix `AppConfig::secure()` is always false. #1202
|
||||
|
||||
|
||||
## [2.0.0-alpha.6] - 2019-12-15
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed compilation with default features off
|
||||
|
||||
## [2.0.0-alpha.5] - 2019-12-13
|
||||
|
||||
### Added
|
||||
|
||||
* Add test server, `test::start()` and `test::start_with()`
|
||||
|
||||
## [2.0.0-alpha.4] - 2019-12-08
|
||||
|
||||
### Deleted
|
||||
|
||||
* Delete HttpServer::run(), it is not useful witht async/await
|
||||
|
||||
## [2.0.0-alpha.3] - 2019-12-07
|
||||
|
||||
### Changed
|
||||
|
62
Cargo.toml
62
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-web"
|
||||
version = "2.0.0-alpha.3"
|
||||
version = "2.0.0-rc"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust."
|
||||
readme = "README.md"
|
||||
@@ -12,11 +12,10 @@ categories = ["network-programming", "asynchronous",
|
||||
"web-programming::http-server",
|
||||
"web-programming::websocket"]
|
||||
license = "MIT/Apache-2.0"
|
||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||
edition = "2018"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["openssl", "brotli", "flate2-zlib", "secure-cookies", "client"]
|
||||
features = ["openssl", "rustls", "compress", "secure-cookies"]
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "actix/actix-web", branch = "master" }
|
||||
@@ -43,47 +42,39 @@ members = [
|
||||
]
|
||||
|
||||
[features]
|
||||
default = ["brotli", "flate2-zlib", "client", "fail"]
|
||||
default = ["compress", "failure"]
|
||||
|
||||
# http client
|
||||
client = ["awc"]
|
||||
|
||||
# brotli encoding, requires c compiler
|
||||
brotli = ["actix-http/brotli"]
|
||||
|
||||
# miniz-sys backend for flate2 crate
|
||||
flate2-zlib = ["actix-http/flate2-zlib"]
|
||||
|
||||
# rust backend for flate2 crate
|
||||
flate2-rust = ["actix-http/flate2-rust"]
|
||||
# content-encoding support
|
||||
compress = ["actix-http/compress", "awc/compress"]
|
||||
|
||||
# sessions feature, session require "ring" crate and c compiler
|
||||
secure-cookies = ["actix-http/secure-cookies"]
|
||||
|
||||
fail = ["actix-http/fail"]
|
||||
failure = ["actix-http/failure"]
|
||||
|
||||
# openssl
|
||||
openssl = ["open-ssl", "actix-tls/openssl", "awc/openssl"]
|
||||
openssl = ["actix-tls/openssl", "awc/openssl", "open-ssl"]
|
||||
|
||||
# rustls
|
||||
rustls = ["rust-tls", "actix-tls/rustls", "awc/rustls"]
|
||||
rustls = ["actix-tls/rustls", "awc/rustls", "rust-tls"]
|
||||
|
||||
[dependencies]
|
||||
actix-codec = "0.2.0-alpha.3"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-utils = "1.0.0-alpha.3"
|
||||
actix-codec = "0.2.0"
|
||||
actix-service = "1.0.0"
|
||||
actix-utils = "1.0.3"
|
||||
actix-router = "0.2.0"
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-server = "1.0.0-alpha.3"
|
||||
actix-testing = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0"
|
||||
actix-server = "1.0.0"
|
||||
actix-testing = "1.0.0"
|
||||
actix-macros = "0.1.0"
|
||||
actix-threadpool = "0.3.0"
|
||||
actix-tls = { version = "1.0.0-alpha.3" }
|
||||
actix-tls = "1.0.0"
|
||||
|
||||
actix-web-codegen = "0.2.0-alpha.2"
|
||||
actix-http = "1.0.0-alpha.3"
|
||||
awc = { version = "1.0.0-alpha.3", optional = true }
|
||||
actix-web-codegen = "0.2.0"
|
||||
actix-http = "1.0.0"
|
||||
awc = { version = "1.0.1", default-features = false }
|
||||
|
||||
bytes = "0.5.2"
|
||||
bytes = "0.5.3"
|
||||
derive_more = "0.99.2"
|
||||
encoding_rs = "0.8"
|
||||
futures = "0.3.1"
|
||||
@@ -91,7 +82,6 @@ fxhash = "0.2.1"
|
||||
log = "0.4"
|
||||
mime = "0.3"
|
||||
net2 = "0.2.33"
|
||||
parking_lot = "0.9"
|
||||
pin-project = "0.4.6"
|
||||
regex = "1.3"
|
||||
serde = { version = "1.0", features=["derive"] }
|
||||
@@ -99,20 +89,16 @@ serde_json = "1.0"
|
||||
serde_urlencoded = "0.6.1"
|
||||
time = "0.1.42"
|
||||
url = "2.1"
|
||||
|
||||
# ssl support
|
||||
open-ssl = { version="0.10", package="openssl", optional = true }
|
||||
rust-tls = { version = "0.16", package="rustls", optional = true }
|
||||
open-ssl = { version="0.10", package = "openssl", optional = true }
|
||||
rust-tls = { version = "0.16.0", package = "rustls", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
# actix = "0.8.3"
|
||||
actix-connect = "1.0.0-alpha.3"
|
||||
actix-http-test = "1.0.0-alpha.3"
|
||||
actix = "0.9.0-alpha.2"
|
||||
rand = "0.7"
|
||||
env_logger = "0.6"
|
||||
serde_derive = "1.0"
|
||||
brotli2 = "0.3.2"
|
||||
flate2 = "1.0.2"
|
||||
flate2 = "1.0.13"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
@@ -1,5 +1,10 @@
|
||||
## 2.0.0
|
||||
|
||||
* `App::register_data()` renamed to `App::app_data()` and accepts any type `T: 'static`.
|
||||
Stored data is available via `HttpRequest::app_data()` method at runtime.
|
||||
|
||||
* Extractor configuration must be registered with `App::app_data()` instead of `App::data()`
|
||||
|
||||
* Sync handlers has been removed. `.to_async()` method has been renamed to `.to()`
|
||||
|
||||
replace `fn` with `async fn` to convert sync handler to async
|
||||
|
36
README.md
36
README.md
@@ -1,4 +1,28 @@
|
||||
# Actix web [](https://travis-ci.org/actix/actix-web) [](https://codecov.io/gh/actix/actix-web) [](https://crates.io/crates/actix-web) [](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
<div align="center">
|
||||
<p><h1>Actix web</h1> </p>
|
||||
<p><strong>Actix web is a small, pragmatic, and extremely fast rust web framework</strong> </p>
|
||||
<p>
|
||||
|
||||
[](https://travis-ci.org/actix/actix-web)
|
||||
[](https://codecov.io/gh/actix/actix-web)
|
||||
[](https://crates.io/crates/actix-web)
|
||||
[](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://docs.rs/actix-web)
|
||||
[](https://crates.io/crates/actix-web)
|
||||
[](https://blog.rust-lang.org/2019/11/07/Rust-1.39.0.html)
|
||||

|
||||
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
<a href="https://actix.rs">Website</a>
|
||||
<span> | </span>
|
||||
<a href="https://gitter.im/actix/actix">Chat</a>
|
||||
<span> | </span>
|
||||
<a href="https://github.com/actix/examples">Examples</a>
|
||||
</h3>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
Actix web is a simple, pragmatic and extremely fast web framework for Rust.
|
||||
|
||||
@@ -15,18 +39,10 @@ Actix web is a simple, pragmatic and extremely fast web framework for Rust.
|
||||
* Includes an asynchronous [HTTP client](https://actix.rs/actix-web/actix_web/client/index.html)
|
||||
* Supports [Actix actor framework](https://github.com/actix/actix)
|
||||
|
||||
## Documentation & community resources
|
||||
|
||||
* [User Guide](https://actix.rs/docs/)
|
||||
* [API Documentation (1.0)](https://docs.rs/actix-web/)
|
||||
* [Chat on gitter](https://gitter.im/actix/actix)
|
||||
* Cargo package: [actix-web](https://crates.io/crates/actix-web)
|
||||
* Minimum supported Rust version: 1.39 or later
|
||||
|
||||
## Example
|
||||
|
||||
```rust
|
||||
use actix_web::{get, App, HttpServer, Responder};
|
||||
use actix_web::{get, web, App, HttpServer, Responder};
|
||||
|
||||
#[get("/{id}/{name}/index.html")]
|
||||
async fn index(info: web::Path<(u32, String)>) -> impl Responder {
|
||||
|
@@ -1,5 +1,9 @@
|
||||
# Changes
|
||||
|
||||
## [0.2.0] - 2019-12-20
|
||||
|
||||
* Release
|
||||
|
||||
## [0.2.0-alpha.3] - 2019-12-07
|
||||
|
||||
* Migrate to actix-web 2.0.0
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-cors"
|
||||
version = "0.2.0-alpha.3"
|
||||
version = "0.2.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Cross-origin resource sharing (CORS) for Actix applications."
|
||||
readme = "README.md"
|
||||
@@ -17,10 +17,10 @@ name = "actix_cors"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "2.0.0-alpha.3"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-web = "2.0.0-rc"
|
||||
actix-service = "1.0.0"
|
||||
derive_more = "0.99.2"
|
||||
futures = "0.3.1"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0"
|
||||
|
@@ -822,7 +822,7 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix_service::{service_fn2, Transform};
|
||||
use actix_service::{fn_service, Transform};
|
||||
use actix_web::test::{self, TestRequest};
|
||||
|
||||
use super::*;
|
||||
@@ -1083,7 +1083,7 @@ mod tests {
|
||||
.expose_headers(exposed_headers.clone())
|
||||
.allowed_header(header::CONTENT_TYPE)
|
||||
.finish()
|
||||
.new_transform(service_fn2(|req: ServiceRequest| {
|
||||
.new_transform(fn_service(|req: ServiceRequest| {
|
||||
ok(req.into_response(
|
||||
HttpResponse::Ok().header(header::VARY, "Accept").finish(),
|
||||
))
|
||||
|
@@ -1,6 +1,10 @@
|
||||
# Changes
|
||||
|
||||
## [0.2.0-alpha.7] - 2019-12-07
|
||||
## [0.2.0] - 2019-12-20
|
||||
|
||||
* Fix BodyEncoding trait import #1220
|
||||
|
||||
## [0.2.0-alpha.1] - 2019-12-07
|
||||
|
||||
* Migrate to `std::future`
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-files"
|
||||
version = "0.2.0-alpha.3"
|
||||
version = "0.2.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Static files support for actix web."
|
||||
readme = "README.md"
|
||||
@@ -18,11 +18,11 @@ name = "actix_files"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-web = { version = "2.0.0-alpha.3", default-features = false }
|
||||
actix-http = "1.0.0-alpha.3"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-web = { version = "2.0.0-rc", default-features = false }
|
||||
actix-http = "1.0.1"
|
||||
actix-service = "1.0.0"
|
||||
bitflags = "1"
|
||||
bytes = "0.5.2"
|
||||
bytes = "0.5.3"
|
||||
futures = "0.3.1"
|
||||
derive_more = "0.99.2"
|
||||
log = "0.4"
|
||||
@@ -32,5 +32,5 @@ percent-encoding = "2.1"
|
||||
v_htmlescape = "0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-web = { version = "2.0.0-alpha.3", features=["openssl"] }
|
||||
actix-rt = "1.0.0"
|
||||
actix-web = { version = "2.0.0-rc", features=["openssl"] }
|
||||
|
@@ -274,10 +274,14 @@ impl Files {
|
||||
/// By default pool with 5x threads of available cpus is used.
|
||||
/// Pool size can be changed by setting ACTIX_CPU_POOL environment variable.
|
||||
pub fn new<T: Into<PathBuf>>(path: &str, dir: T) -> Files {
|
||||
let dir = dir.into().canonicalize().unwrap_or_else(|_| PathBuf::new());
|
||||
if !dir.is_dir() {
|
||||
log::error!("Specified path is not a directory: {:?}", dir);
|
||||
}
|
||||
let orig_dir = dir.into();
|
||||
let dir = match orig_dir.canonicalize() {
|
||||
Ok(canon_dir) => canon_dir,
|
||||
Err(_) => {
|
||||
log::error!("Specified path is not a directory: {:?}", orig_dir);
|
||||
PathBuf::new()
|
||||
}
|
||||
};
|
||||
|
||||
Files {
|
||||
path: path.to_string(),
|
||||
|
@@ -12,11 +12,11 @@ use mime;
|
||||
use mime_guess::from_path;
|
||||
|
||||
use actix_http::body::SizedStream;
|
||||
use actix_web::dev::BodyEncoding;
|
||||
use actix_web::http::header::{
|
||||
self, Charset, ContentDisposition, DispositionParam, DispositionType, ExtendedValue,
|
||||
};
|
||||
use actix_web::http::{ContentEncoding, StatusCode};
|
||||
use actix_web::middleware::BodyEncoding;
|
||||
use actix_web::{Error, HttpMessage, HttpRequest, HttpResponse, Responder};
|
||||
use futures::future::{ready, Ready};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-framed"
|
||||
version = "0.3.0-alpha.1"
|
||||
version = "0.3.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix framed app server"
|
||||
readme = "README.md"
|
||||
@@ -20,19 +20,19 @@ name = "actix_framed"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-codec = "0.2.0-alpha.3"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-codec = "0.2.0"
|
||||
actix-service = "1.0.0"
|
||||
actix-router = "0.2.0"
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-http = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0"
|
||||
actix-http = "1.0.0"
|
||||
|
||||
bytes = "0.5.2"
|
||||
bytes = "0.5.3"
|
||||
futures = "0.3.1"
|
||||
pin-project = "0.4.6"
|
||||
log = "0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-server = { version = "1.0.0-alpha.3" }
|
||||
actix-connect = { version = "1.0.0-alpha.3", features=["openssl"] }
|
||||
actix-http-test = { version = "1.0.0-alpha.3", features=["openssl"] }
|
||||
actix-utils = "1.0.0-alpha.3"
|
||||
actix-server = "1.0.0"
|
||||
actix-connect = { version = "1.0.0", features=["openssl"] }
|
||||
actix-http-test = { version = "1.0.0", features=["openssl"] }
|
||||
actix-utils = "1.0.3"
|
||||
|
@@ -1,9 +1,9 @@
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use actix_http::{body, http::StatusCode, ws, Error, HttpService, Response};
|
||||
use actix_http_test::TestServer;
|
||||
use actix_http_test::test_server;
|
||||
use actix_service::{pipeline_factory, IntoServiceFactory, ServiceFactory};
|
||||
use actix_utils::framed::FramedTransport;
|
||||
use bytes::BytesMut;
|
||||
use actix_utils::framed::Dispatcher;
|
||||
use bytes::Bytes;
|
||||
use futures::{future, SinkExt, StreamExt};
|
||||
|
||||
use actix_framed::{FramedApp, FramedRequest, FramedRoute, SendError, VerifyWebSockets};
|
||||
@@ -18,7 +18,7 @@ async fn ws_service<T: AsyncRead + AsyncWrite>(
|
||||
.send((res, body::BodySize::None).into())
|
||||
.await
|
||||
.unwrap();
|
||||
FramedTransport::new(framed.into_framed(ws::Codec::new()), service)
|
||||
Dispatcher::new(framed.into_framed(ws::Codec::new()), service)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -29,9 +29,9 @@ async fn service(msg: ws::Frame) -> Result<ws::Message, Error> {
|
||||
let msg = match msg {
|
||||
ws::Frame::Ping(msg) => ws::Message::Pong(msg),
|
||||
ws::Frame::Text(text) => {
|
||||
ws::Message::Text(String::from_utf8_lossy(&text.unwrap()).to_string())
|
||||
ws::Message::Text(String::from_utf8_lossy(&text).to_string())
|
||||
}
|
||||
ws::Frame::Binary(bin) => ws::Message::Binary(bin.unwrap().freeze()),
|
||||
ws::Frame::Binary(bin) => ws::Message::Binary(bin),
|
||||
ws::Frame::Close(reason) => ws::Message::Close(reason),
|
||||
_ => panic!(),
|
||||
};
|
||||
@@ -40,7 +40,7 @@ async fn service(msg: ws::Frame) -> Result<ws::Message, Error> {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_simple() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.upgrade(
|
||||
FramedApp::new().service(FramedRoute::get("/index.html").to(ws_service)),
|
||||
@@ -60,7 +60,7 @@ async fn test_simple() {
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Text(Some(BytesMut::from("text")))
|
||||
ws::Frame::Text(Bytes::from_static(b"text"))
|
||||
);
|
||||
|
||||
framed
|
||||
@@ -70,7 +70,7 @@ async fn test_simple() {
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Binary(Some(BytesMut::from(&b"text"[..])))
|
||||
ws::Frame::Binary(Bytes::from_static(b"text"))
|
||||
);
|
||||
|
||||
framed.send(ws::Message::Ping("text".into())).await.unwrap();
|
||||
@@ -94,7 +94,7 @@ async fn test_simple() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_service() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
pipeline_factory(actix_http::h1::OneRequest::new().map_err(|_| ())).and_then(
|
||||
pipeline_factory(
|
||||
pipeline_factory(VerifyWebSockets::default())
|
||||
@@ -126,7 +126,7 @@ async fn test_service() {
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Text(Some(BytesMut::from("text")))
|
||||
ws::Frame::Text(Bytes::from_static(b"text"))
|
||||
);
|
||||
|
||||
framed
|
||||
@@ -136,7 +136,7 @@ async fn test_service() {
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Binary(Some(BytesMut::from(&b"text"[..])))
|
||||
ws::Frame::Binary(Bytes::from_static(b"text"))
|
||||
);
|
||||
|
||||
framed.send(ws::Message::Ping("text".into())).await.unwrap();
|
||||
|
@@ -1,5 +1,45 @@
|
||||
# Changes
|
||||
|
||||
## [1.0.1] - 2019-12-20
|
||||
|
||||
### Fixed
|
||||
|
||||
* Poll upgrade service's readiness from HTTP service handlers
|
||||
|
||||
* Replace brotli with brotli2 #1224
|
||||
|
||||
## [1.0.0] - 2019-12-13
|
||||
|
||||
### Added
|
||||
|
||||
* Add websockets continuation frame support
|
||||
|
||||
### Changed
|
||||
|
||||
* Replace `flate2-xxx` features with `compress`
|
||||
|
||||
## [1.0.0-alpha.5] - 2019-12-09
|
||||
|
||||
### Fixed
|
||||
|
||||
* Check `Upgrade` service readiness before calling it
|
||||
|
||||
* Fix buffer remaining capacity calcualtion
|
||||
|
||||
### Changed
|
||||
|
||||
* Websockets: Ping and Pong should have binary data #1049
|
||||
|
||||
## [1.0.0-alpha.4] - 2019-12-08
|
||||
|
||||
### Added
|
||||
|
||||
* Add impl ResponseBuilder for Error
|
||||
|
||||
### Changed
|
||||
|
||||
* Use rust based brotli compression library
|
||||
|
||||
## [1.0.0-alpha.3] - 2019-12-07
|
||||
|
||||
### Changed
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-http"
|
||||
version = "1.0.0-alpha.3"
|
||||
version = "1.0.1"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix http primitives"
|
||||
readme = "README.md"
|
||||
@@ -13,10 +13,9 @@ categories = ["network-programming", "asynchronous",
|
||||
"web-programming::websocket"]
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2018"
|
||||
workspace = ".."
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["openssl", "rustls", "fail", "brotli", "flate2-zlib", "secure-cookies"]
|
||||
features = ["openssl", "rustls", "failure", "compress", "secure-cookies"]
|
||||
|
||||
[lib]
|
||||
name = "actix_http"
|
||||
@@ -31,45 +30,41 @@ openssl = ["actix-tls/openssl", "actix-connect/openssl"]
|
||||
# rustls support
|
||||
rustls = ["actix-tls/rustls", "actix-connect/rustls"]
|
||||
|
||||
# brotli encoding, requires c compiler
|
||||
brotli = ["brotli2"]
|
||||
|
||||
# miniz-sys backend for flate2 crate
|
||||
flate2-zlib = ["flate2/miniz-sys"]
|
||||
|
||||
# rust backend for flate2 crate
|
||||
flate2-rust = ["flate2/rust_backend"]
|
||||
# enable compressison support
|
||||
compress = ["flate2", "brotli2"]
|
||||
|
||||
# failure integration. actix does not use failure anymore
|
||||
fail = ["failure"]
|
||||
failure = ["fail-ure"]
|
||||
|
||||
# support for secure cookies
|
||||
secure-cookies = ["ring"]
|
||||
|
||||
[dependencies]
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-codec = "0.2.0-alpha.3"
|
||||
actix-connect = "1.0.0-alpha.3"
|
||||
actix-utils = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-threadpool = "0.3.0"
|
||||
actix-tls = { version = "1.0.0-alpha.3", optional = true }
|
||||
actix-service = "1.0.0"
|
||||
actix-codec = "0.2.0"
|
||||
actix-connect = "1.0.1"
|
||||
actix-utils = "1.0.3"
|
||||
actix-rt = "1.0.0"
|
||||
actix-threadpool = "0.3.1"
|
||||
actix-tls = { version = "1.0.0", optional = true }
|
||||
|
||||
base64 = "0.11"
|
||||
bitflags = "1.0"
|
||||
bytes = "0.5.2"
|
||||
bitflags = "1.2"
|
||||
bytes = "0.5.3"
|
||||
copyless = "0.1.4"
|
||||
chrono = "0.4.6"
|
||||
derive_more = "0.99.2"
|
||||
either = "1.5.2"
|
||||
either = "1.5.3"
|
||||
encoding_rs = "0.8"
|
||||
futures = "0.3.1"
|
||||
futures-core = "0.3.1"
|
||||
futures-util = "0.3.1"
|
||||
futures-channel = "0.3.1"
|
||||
fxhash = "0.2.1"
|
||||
h2 = "0.2.1"
|
||||
http = "0.2.0"
|
||||
httparse = "1.3"
|
||||
indexmap = "1.2"
|
||||
lazy_static = "1.0"
|
||||
indexmap = "1.3"
|
||||
lazy_static = "1.4"
|
||||
language-tags = "0.2"
|
||||
log = "0.4"
|
||||
mime = "0.3"
|
||||
@@ -89,16 +84,17 @@ ring = { version = "0.16.9", optional = true }
|
||||
|
||||
# compression
|
||||
brotli2 = { version="0.3.2", optional = true }
|
||||
flate2 = { version="1.0.7", optional = true, default-features = false }
|
||||
flate2 = { version = "1.0.13", optional = true }
|
||||
|
||||
# optional deps
|
||||
failure = { version = "0.1.5", optional = true }
|
||||
fail-ure = { version = "0.1.5", package="failure", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-server = { version = "1.0.0-alpha.3" }
|
||||
actix-connect = { version = "1.0.0-alpha.3", features=["openssl"] }
|
||||
actix-http-test = { version = "1.0.0-alpha.3", features=["openssl"] }
|
||||
actix-tls = { version = "1.0.0-alpha.3", features=["openssl"] }
|
||||
actix-server = "1.0.0"
|
||||
actix-connect = { version = "1.0.0", features=["openssl"] }
|
||||
actix-http-test = { version = "1.0.0", features=["openssl"] }
|
||||
actix-tls = { version = "1.0.0", features=["openssl"] }
|
||||
futures = "0.3.1"
|
||||
env_logger = "0.6"
|
||||
serde_derive = "1.0"
|
||||
open-ssl = { version="0.10", package = "openssl" }
|
||||
|
@@ -4,7 +4,7 @@ use std::task::{Context, Poll};
|
||||
use std::{fmt, mem};
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::Stream;
|
||||
use futures_core::Stream;
|
||||
use pin_project::{pin_project, project};
|
||||
|
||||
use crate::error::Error;
|
||||
@@ -35,7 +35,7 @@ impl BodySize {
|
||||
pub trait MessageBody {
|
||||
fn size(&self) -> BodySize;
|
||||
|
||||
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>>;
|
||||
fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>>;
|
||||
}
|
||||
|
||||
impl MessageBody for () {
|
||||
@@ -43,7 +43,7 @@ impl MessageBody for () {
|
||||
BodySize::Empty
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, _: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
Poll::Ready(None)
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ impl<T: MessageBody> MessageBody for Box<T> {
|
||||
self.as_ref().size()
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
self.as_mut().poll_next(cx)
|
||||
}
|
||||
}
|
||||
@@ -97,7 +97,7 @@ impl<B: MessageBody> MessageBody for ResponseBody<B> {
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
match self {
|
||||
ResponseBody::Body(ref mut body) => body.poll_next(cx),
|
||||
ResponseBody::Other(ref mut body) => body.poll_next(cx),
|
||||
@@ -109,7 +109,10 @@ impl<B: MessageBody> Stream for ResponseBody<B> {
|
||||
type Item = Result<Bytes, Error>;
|
||||
|
||||
#[project]
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
#[project]
|
||||
match self.project() {
|
||||
ResponseBody::Body(ref mut body) => body.poll_next(cx),
|
||||
@@ -152,7 +155,7 @@ impl MessageBody for Body {
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
match self {
|
||||
Body::None => Poll::Ready(None),
|
||||
Body::Empty => Poll::Ready(None),
|
||||
@@ -190,7 +193,7 @@ impl PartialEq for Body {
|
||||
}
|
||||
|
||||
impl fmt::Debug for Body {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Body::None => write!(f, "Body::None"),
|
||||
Body::Empty => write!(f, "Body::Empty"),
|
||||
@@ -272,7 +275,7 @@ impl MessageBody for Bytes {
|
||||
BodySize::Sized(self.len())
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, _: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
if self.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
@@ -286,7 +289,7 @@ impl MessageBody for BytesMut {
|
||||
BodySize::Sized(self.len())
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, _: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
if self.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
@@ -300,7 +303,7 @@ impl MessageBody for &'static str {
|
||||
BodySize::Sized(self.len())
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, _: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
if self.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
@@ -316,7 +319,7 @@ impl MessageBody for &'static [u8] {
|
||||
BodySize::Sized(self.len())
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, _: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
if self.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
@@ -330,7 +333,7 @@ impl MessageBody for Vec<u8> {
|
||||
BodySize::Sized(self.len())
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, _: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
if self.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
@@ -344,7 +347,7 @@ impl MessageBody for String {
|
||||
BodySize::Sized(self.len())
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, _: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, _: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
if self.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
@@ -386,7 +389,7 @@ where
|
||||
BodySize::Stream
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
unsafe { Pin::new_unchecked(self) }
|
||||
.project()
|
||||
.stream
|
||||
@@ -421,7 +424,7 @@ where
|
||||
BodySize::Sized64(self.size)
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
unsafe { Pin::new_unchecked(self) }
|
||||
.project()
|
||||
.stream
|
||||
@@ -432,7 +435,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use futures::future::poll_fn;
|
||||
use futures_util::future::poll_fn;
|
||||
|
||||
impl Body {
|
||||
pub(crate) fn get_ref(&self) -> &[u8] {
|
||||
|
@@ -4,7 +4,7 @@ use std::{fmt, io, mem, time};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use bytes::{Buf, Bytes};
|
||||
use futures::future::{err, Either, Future, FutureExt, LocalBoxFuture, Ready};
|
||||
use futures_util::future::{err, Either, Future, FutureExt, LocalBoxFuture, Ready};
|
||||
use h2::client::SendRequest;
|
||||
use pin_project::{pin_project, project};
|
||||
|
||||
@@ -63,7 +63,7 @@ impl<T> fmt::Debug for IoConnection<T>
|
||||
where
|
||||
T: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.io {
|
||||
Some(ConnectionType::H1(ref io)) => write!(f, "H1Connection({:?})", io),
|
||||
Some(ConnectionType::H2(_)) => write!(f, "H2Connection"),
|
||||
@@ -247,7 +247,7 @@ where
|
||||
#[project]
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<io::Result<usize>> {
|
||||
#[project]
|
||||
|
@@ -62,7 +62,7 @@ trait Io: AsyncRead + AsyncWrite + Unpin {}
|
||||
impl<T: AsyncRead + AsyncWrite + Unpin> Io for T {}
|
||||
|
||||
impl Connector<(), ()> {
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
#[allow(clippy::new_ret_no_self, clippy::let_unit_value)]
|
||||
pub fn new() -> Connector<
|
||||
impl Service<
|
||||
Request = TcpConnect<Uri>,
|
||||
@@ -87,9 +87,9 @@ impl Connector<(), ()> {
|
||||
let protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
|
||||
let mut config = ClientConfig::new();
|
||||
config.set_protocols(&protos);
|
||||
config.root_store.add_server_trust_anchors(
|
||||
&actix_connect::ssl::rustls::TLS_SERVER_ROOTS,
|
||||
);
|
||||
config
|
||||
.root_store
|
||||
.add_server_trust_anchors(&actix_tls::rustls::TLS_SERVER_ROOTS);
|
||||
SslConnector::Rustls(Arc::new(config))
|
||||
}
|
||||
#[cfg(not(any(feature = "openssl", feature = "rustls")))]
|
||||
@@ -337,7 +337,7 @@ where
|
||||
mod connect_impl {
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::future::{err, Either, Ready};
|
||||
use futures_util::future::{err, Either, Ready};
|
||||
|
||||
use super::*;
|
||||
use crate::client::connection::IoConnection;
|
||||
@@ -378,7 +378,7 @@ mod connect_impl {
|
||||
Ready<Result<IoConnection<Io>, ConnectError>>,
|
||||
>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.tcp_pool.poll_ready(cx)
|
||||
}
|
||||
|
||||
@@ -400,8 +400,8 @@ mod connect_impl {
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use futures::future::Either;
|
||||
use futures::ready;
|
||||
use futures_core::ready;
|
||||
use futures_util::future::Either;
|
||||
|
||||
use super::*;
|
||||
use crate::client::connection::EitherConnection;
|
||||
@@ -451,7 +451,7 @@ mod connect_impl {
|
||||
InnerConnectorResponseB<T2, Io1, Io2>,
|
||||
>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.tcp_pool.poll_ready(cx)
|
||||
}
|
||||
|
||||
@@ -490,10 +490,10 @@ mod connect_impl {
|
||||
{
|
||||
type Output = Result<EitherConnection<Io1, Io2>, ConnectError>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Poll::Ready(
|
||||
ready!(Pin::new(&mut self.get_mut().fut).poll(cx))
|
||||
.map(|res| EitherConnection::A(res)),
|
||||
.map(EitherConnection::A),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -519,10 +519,10 @@ mod connect_impl {
|
||||
{
|
||||
type Output = Result<EitherConnection<Io1, Io2>, ConnectError>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Poll::Ready(
|
||||
ready!(Pin::new(&mut self.get_mut().fut).poll(cx))
|
||||
.map(|res| EitherConnection::B(res)),
|
||||
.map(EitherConnection::B),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -6,8 +6,9 @@ use std::{io, mem, time};
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use bytes::buf::BufMutExt;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::poll_fn;
|
||||
use futures::{SinkExt, Stream, StreamExt};
|
||||
use futures_core::Stream;
|
||||
use futures_util::future::poll_fn;
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
|
||||
use crate::error::PayloadError;
|
||||
use crate::h1;
|
||||
@@ -234,7 +235,7 @@ impl<T: AsyncRead + AsyncWrite + Unpin + 'static> AsyncWrite for H1Connection<T>
|
||||
|
||||
fn poll_shutdown(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), io::Error>> {
|
||||
Pin::new(self.io.as_mut().unwrap()).poll_shutdown(cx)
|
||||
}
|
||||
@@ -255,7 +256,10 @@ impl<Io: ConnectionLifetime> PlStream<Io> {
|
||||
impl<Io: ConnectionLifetime> Stream for PlStream<Io> {
|
||||
type Item = Result<Bytes, PayloadError>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
let this = self.get_mut();
|
||||
|
||||
match this.framed.as_mut().unwrap().next_item(cx)? {
|
||||
|
@@ -3,7 +3,7 @@ use std::time;
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use bytes::Bytes;
|
||||
use futures::future::poll_fn;
|
||||
use futures_util::future::poll_fn;
|
||||
use h2::{client::SendRequest, SendStream};
|
||||
use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, TRANSFER_ENCODING};
|
||||
use http::{request::Request, Method, Version};
|
||||
|
@@ -11,7 +11,7 @@ use actix_rt::time::{delay_for, Delay};
|
||||
use actix_service::Service;
|
||||
use actix_utils::{oneshot, task::LocalWaker};
|
||||
use bytes::Bytes;
|
||||
use futures::future::{poll_fn, FutureExt, LocalBoxFuture};
|
||||
use futures_util::future::{poll_fn, FutureExt, LocalBoxFuture};
|
||||
use fxhash::FxHashMap;
|
||||
use h2::client::{handshake, Connection, SendRequest};
|
||||
use http::uri::Authority;
|
||||
@@ -93,7 +93,7 @@ where
|
||||
type Error = ConnectError;
|
||||
type Future = LocalBoxFuture<'static, Result<IoConnection<Io>, ConnectError>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.0.poll_ready(cx)
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ where
|
||||
(rx, token)
|
||||
}
|
||||
|
||||
fn acquire(&mut self, key: &Key, cx: &mut Context) -> Acquire<Io> {
|
||||
fn acquire(&mut self, key: &Key, cx: &mut Context<'_>) -> Acquire<Io> {
|
||||
// check limits
|
||||
if self.limit > 0 && self.acquired >= self.limit {
|
||||
return Acquire::NotAvailable;
|
||||
@@ -409,7 +409,7 @@ where
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
|
||||
let this = self.get_mut();
|
||||
|
||||
match Pin::new(&mut this.timeout).poll(cx) {
|
||||
@@ -438,7 +438,7 @@ where
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = unsafe { self.get_unchecked_mut() };
|
||||
|
||||
let mut inner = this.inner.as_ref().borrow_mut();
|
||||
@@ -545,7 +545,7 @@ where
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = unsafe { self.get_unchecked_mut() };
|
||||
|
||||
if let Some(ref mut h2) = this.h2 {
|
||||
|
@@ -32,7 +32,7 @@ where
|
||||
type Error = T::Error;
|
||||
type Future = T::Future;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
unsafe { &mut *self.0.as_ref().get() }.poll_ready(cx)
|
||||
}
|
||||
|
||||
|
@@ -6,7 +6,7 @@ use std::{fmt, net};
|
||||
|
||||
use actix_rt::time::{delay_for, delay_until, Delay, Instant};
|
||||
use bytes::BytesMut;
|
||||
use futures::{future, FutureExt};
|
||||
use futures_util::{future, FutureExt};
|
||||
use time;
|
||||
|
||||
// "Sun, 06 Nov 1994 08:49:37 GMT".len()
|
||||
|
@@ -18,7 +18,6 @@ use super::{Cookie, SameSite};
|
||||
/// ```rust
|
||||
/// use actix_http::cookie::Cookie;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let cookie: Cookie = Cookie::build("name", "value")
|
||||
/// .domain("www.rust-lang.org")
|
||||
/// .path("/")
|
||||
@@ -26,7 +25,6 @@ use super::{Cookie, SameSite};
|
||||
/// .http_only(true)
|
||||
/// .max_age(84600)
|
||||
/// .finish();
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CookieBuilder {
|
||||
@@ -65,13 +63,11 @@ impl CookieBuilder {
|
||||
/// ```rust
|
||||
/// use actix_http::cookie::Cookie;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let c = Cookie::build("foo", "bar")
|
||||
/// .expires(time::now())
|
||||
/// .finish();
|
||||
///
|
||||
/// assert!(c.expires().is_some());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn expires(mut self, when: Tm) -> CookieBuilder {
|
||||
@@ -86,13 +82,11 @@ impl CookieBuilder {
|
||||
/// ```rust
|
||||
/// use actix_http::cookie::Cookie;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let c = Cookie::build("foo", "bar")
|
||||
/// .max_age(1800)
|
||||
/// .finish();
|
||||
///
|
||||
/// assert_eq!(c.max_age(), Some(time::Duration::seconds(30 * 60)));
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn max_age(self, seconds: i64) -> CookieBuilder {
|
||||
@@ -106,13 +100,11 @@ impl CookieBuilder {
|
||||
/// ```rust
|
||||
/// use actix_http::cookie::Cookie;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let c = Cookie::build("foo", "bar")
|
||||
/// .max_age_time(time::Duration::minutes(30))
|
||||
/// .finish();
|
||||
///
|
||||
/// assert_eq!(c.max_age(), Some(time::Duration::seconds(30 * 60)));
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn max_age_time(mut self, value: Duration) -> CookieBuilder {
|
||||
@@ -222,14 +214,12 @@ impl CookieBuilder {
|
||||
/// use actix_http::cookie::Cookie;
|
||||
/// use chrono::Duration;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let c = Cookie::build("foo", "bar")
|
||||
/// .permanent()
|
||||
/// .finish();
|
||||
///
|
||||
/// assert_eq!(c.max_age(), Some(Duration::days(365 * 20)));
|
||||
/// # assert!(c.expires().is_some());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn permanent(mut self) -> CookieBuilder {
|
||||
|
@@ -88,7 +88,7 @@ impl SameSite {
|
||||
}
|
||||
|
||||
impl fmt::Display for SameSite {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
SameSite::Strict => write!(f, "Strict"),
|
||||
SameSite::Lax => write!(f, "Lax"),
|
||||
|
@@ -190,7 +190,6 @@ impl CookieJar {
|
||||
/// use actix_http::cookie::{CookieJar, Cookie};
|
||||
/// use chrono::Duration;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut jar = CookieJar::new();
|
||||
///
|
||||
/// // Assume this cookie originally had a path of "/" and domain of "a.b".
|
||||
@@ -204,7 +203,6 @@ impl CookieJar {
|
||||
/// assert_eq!(delta.len(), 1);
|
||||
/// assert_eq!(delta[0].name(), "name");
|
||||
/// assert_eq!(delta[0].max_age(), Some(Duration::seconds(0)));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Removing a new cookie does not result in a _removal_ cookie:
|
||||
@@ -243,7 +241,6 @@ impl CookieJar {
|
||||
/// use actix_http::cookie::{CookieJar, Cookie};
|
||||
/// use chrono::Duration;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut jar = CookieJar::new();
|
||||
///
|
||||
/// // Add an original cookie and a new cookie.
|
||||
@@ -261,7 +258,6 @@ impl CookieJar {
|
||||
/// jar.force_remove(Cookie::new("key", "value"));
|
||||
/// assert_eq!(jar.delta().count(), 0);
|
||||
/// assert_eq!(jar.iter().count(), 0);
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn force_remove<'a>(&mut self, cookie: Cookie<'a>) {
|
||||
self.original_cookies.remove(cookie.name());
|
||||
@@ -307,7 +303,7 @@ impl CookieJar {
|
||||
/// // Delta contains two new cookies ("new", "yac") and a removal ("name").
|
||||
/// assert_eq!(jar.delta().count(), 3);
|
||||
/// ```
|
||||
pub fn delta(&self) -> Delta {
|
||||
pub fn delta(&self) -> Delta<'_> {
|
||||
Delta {
|
||||
iter: self.delta_cookies.iter(),
|
||||
}
|
||||
@@ -343,7 +339,7 @@ impl CookieJar {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn iter(&self) -> Iter {
|
||||
pub fn iter(&self) -> Iter<'_> {
|
||||
Iter {
|
||||
delta_cookies: self
|
||||
.delta_cookies
|
||||
@@ -386,7 +382,7 @@ impl CookieJar {
|
||||
/// assert!(jar.get("private").is_some());
|
||||
/// ```
|
||||
#[cfg(feature = "secure-cookies")]
|
||||
pub fn private(&mut self, key: &Key) -> PrivateJar {
|
||||
pub fn private(&mut self, key: &Key) -> PrivateJar<'_> {
|
||||
PrivateJar::new(self, key)
|
||||
}
|
||||
|
||||
@@ -424,7 +420,7 @@ impl CookieJar {
|
||||
/// assert!(jar.get("signed").is_some());
|
||||
/// ```
|
||||
#[cfg(feature = "secure-cookies")]
|
||||
pub fn signed(&mut self, key: &Key) -> SignedJar {
|
||||
pub fn signed(&mut self, key: &Key) -> SignedJar<'_> {
|
||||
SignedJar::new(self, key)
|
||||
}
|
||||
}
|
||||
|
@@ -110,7 +110,7 @@ impl CookieStr {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `self` is an indexed string and `string` is None.
|
||||
fn to_str<'s>(&'s self, string: Option<&'s Cow<str>>) -> &'s str {
|
||||
fn to_str<'s>(&'s self, string: Option<&'s Cow<'_, str>>) -> &'s str {
|
||||
match *self {
|
||||
CookieStr::Indexed(i, j) => {
|
||||
let s = string.expect(
|
||||
@@ -647,13 +647,11 @@ impl<'c> Cookie<'c> {
|
||||
/// use actix_http::cookie::Cookie;
|
||||
/// use chrono::Duration;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut c = Cookie::new("name", "value");
|
||||
/// assert_eq!(c.max_age(), None);
|
||||
///
|
||||
/// c.set_max_age(Duration::hours(10));
|
||||
/// assert_eq!(c.max_age(), Some(Duration::hours(10)));
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn set_max_age(&mut self, value: Duration) {
|
||||
@@ -701,7 +699,6 @@ impl<'c> Cookie<'c> {
|
||||
/// ```rust
|
||||
/// use actix_http::cookie::Cookie;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut c = Cookie::new("name", "value");
|
||||
/// assert_eq!(c.expires(), None);
|
||||
///
|
||||
@@ -710,7 +707,6 @@ impl<'c> Cookie<'c> {
|
||||
///
|
||||
/// c.set_expires(now);
|
||||
/// assert!(c.expires().is_some())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn set_expires(&mut self, time: Tm) {
|
||||
@@ -726,7 +722,6 @@ impl<'c> Cookie<'c> {
|
||||
/// use actix_http::cookie::Cookie;
|
||||
/// use chrono::Duration;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let mut c = Cookie::new("foo", "bar");
|
||||
/// assert!(c.expires().is_none());
|
||||
/// assert!(c.max_age().is_none());
|
||||
@@ -734,7 +729,6 @@ impl<'c> Cookie<'c> {
|
||||
/// c.make_permanent();
|
||||
/// assert!(c.expires().is_some());
|
||||
/// assert_eq!(c.max_age(), Some(Duration::days(365 * 20)));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn make_permanent(&mut self) {
|
||||
let twenty_years = Duration::days(365 * 20);
|
||||
@@ -742,7 +736,7 @@ impl<'c> Cookie<'c> {
|
||||
self.set_expires(time::now() + twenty_years);
|
||||
}
|
||||
|
||||
fn fmt_parameters(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt_parameters(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if let Some(true) = self.http_only() {
|
||||
write!(f, "; HttpOnly")?;
|
||||
}
|
||||
@@ -924,10 +918,10 @@ impl<'c> Cookie<'c> {
|
||||
/// let mut c = Cookie::new("my name", "this; value?");
|
||||
/// assert_eq!(&c.encoded().to_string(), "my%20name=this%3B%20value%3F");
|
||||
/// ```
|
||||
pub struct EncodedCookie<'a, 'c: 'a>(&'a Cookie<'c>);
|
||||
pub struct EncodedCookie<'a, 'c>(&'a Cookie<'c>);
|
||||
|
||||
impl<'a, 'c: 'a> fmt::Display for EncodedCookie<'a, 'c> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Percent-encode the name and value.
|
||||
let name = percent_encode(self.0.name().as_bytes(), USERINFO);
|
||||
let value = percent_encode(self.0.value().as_bytes(), USERINFO);
|
||||
@@ -952,7 +946,7 @@ impl<'c> fmt::Display for Cookie<'c> {
|
||||
///
|
||||
/// assert_eq!(&cookie.to_string(), "foo=bar; Path=/");
|
||||
/// ```
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}={}", self.name(), self.value())?;
|
||||
self.fmt_parameters(f)
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ impl ParseError {
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
@@ -51,11 +51,7 @@ impl From<Utf8Error> for ParseError {
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ParseError {
|
||||
fn description(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
impl Error for ParseError {}
|
||||
|
||||
fn indexes_of(needle: &str, haystack: &str) -> Option<(usize, usize)> {
|
||||
let haystack_start = haystack.as_ptr() as usize;
|
||||
|
@@ -10,7 +10,7 @@ use crate::cookie::{Cookie, CookieJar};
|
||||
|
||||
// Keep these in sync, and keep the key len synced with the `private` docs as
|
||||
// well as the `KEYS_INFO` const in secure::Key.
|
||||
static ALGO: &'static Algorithm = &AES_256_GCM;
|
||||
static ALGO: &Algorithm = &AES_256_GCM;
|
||||
const NONCE_LEN: usize = 12;
|
||||
pub const KEY_LEN: usize = 32;
|
||||
|
||||
@@ -159,7 +159,7 @@ Please change it as soon as possible."
|
||||
|
||||
/// Encrypts the cookie's value with
|
||||
/// authenticated encryption assuring confidentiality, integrity, and authenticity.
|
||||
fn encrypt_cookie(&self, cookie: &mut Cookie) {
|
||||
fn encrypt_cookie(&self, cookie: &mut Cookie<'_>) {
|
||||
let name = cookie.name().as_bytes();
|
||||
let value = cookie.value().as_bytes();
|
||||
let data = encrypt_name_value(name, value, &self.key);
|
||||
|
@@ -129,7 +129,7 @@ impl<'a> SignedJar<'a> {
|
||||
}
|
||||
|
||||
/// Signs the cookie's value assuring integrity and authenticity.
|
||||
fn sign_cookie(&self, cookie: &mut Cookie) {
|
||||
fn sign_cookie(&self, cookie: &mut Cookie<'_>) {
|
||||
let digest = sign(&self.key, cookie.value().as_bytes());
|
||||
let mut new_value = base64::encode(digest.as_ref());
|
||||
new_value.push_str(cookie.value());
|
||||
|
@@ -4,12 +4,10 @@ use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_threadpool::{run, CpuFuture};
|
||||
#[cfg(feature = "brotli")]
|
||||
use brotli2::write::BrotliDecoder;
|
||||
use bytes::Bytes;
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
use flate2::write::{GzDecoder, ZlibDecoder};
|
||||
use futures::{ready, Stream};
|
||||
use futures_core::{ready, Stream};
|
||||
|
||||
use super::Writer;
|
||||
use crate::error::PayloadError;
|
||||
@@ -32,15 +30,12 @@ where
|
||||
#[inline]
|
||||
pub fn new(stream: S, encoding: ContentEncoding) -> Decoder<S> {
|
||||
let decoder = match encoding {
|
||||
#[cfg(feature = "brotli")]
|
||||
ContentEncoding::Br => Some(ContentDecoder::Br(Box::new(
|
||||
BrotliDecoder::new(Writer::new()),
|
||||
))),
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new(
|
||||
ZlibDecoder::new(Writer::new()),
|
||||
))),
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoding::Gzip => Some(ContentDecoder::Gzip(Box::new(
|
||||
GzDecoder::new(Writer::new()),
|
||||
))),
|
||||
@@ -80,7 +75,7 @@ where
|
||||
|
||||
fn poll_next(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
loop {
|
||||
if let Some(ref mut fut) = self.fut {
|
||||
@@ -140,22 +135,17 @@ where
|
||||
}
|
||||
|
||||
enum ContentDecoder {
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
Deflate(Box<ZlibDecoder<Writer>>),
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
Gzip(Box<GzDecoder<Writer>>),
|
||||
#[cfg(feature = "brotli")]
|
||||
Br(Box<BrotliDecoder<Writer>>),
|
||||
}
|
||||
|
||||
impl ContentDecoder {
|
||||
#[allow(unreachable_patterns)]
|
||||
fn feed_eof(&mut self) -> io::Result<Option<Bytes>> {
|
||||
match self {
|
||||
#[cfg(feature = "brotli")]
|
||||
ContentDecoder::Br(ref mut decoder) => match decoder.finish() {
|
||||
Ok(mut writer) => {
|
||||
let b = writer.take();
|
||||
ContentDecoder::Br(ref mut decoder) => match decoder.flush() {
|
||||
Ok(()) => {
|
||||
let b = decoder.get_mut().take();
|
||||
if !b.is_empty() {
|
||||
Ok(Some(b))
|
||||
} else {
|
||||
@@ -164,7 +154,6 @@ impl ContentDecoder {
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentDecoder::Gzip(ref mut decoder) => match decoder.try_finish() {
|
||||
Ok(_) => {
|
||||
let b = decoder.get_mut().take();
|
||||
@@ -176,7 +165,6 @@ impl ContentDecoder {
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentDecoder::Deflate(ref mut decoder) => match decoder.try_finish() {
|
||||
Ok(_) => {
|
||||
let b = decoder.get_mut().take();
|
||||
@@ -188,14 +176,11 @@ impl ContentDecoder {
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
fn feed_data(&mut self, data: Bytes) -> io::Result<Option<Bytes>> {
|
||||
match self {
|
||||
#[cfg(feature = "brotli")]
|
||||
ContentDecoder::Br(ref mut decoder) => match decoder.write_all(&data) {
|
||||
Ok(_) => {
|
||||
decoder.flush()?;
|
||||
@@ -208,7 +193,6 @@ impl ContentDecoder {
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentDecoder::Gzip(ref mut decoder) => match decoder.write_all(&data) {
|
||||
Ok(_) => {
|
||||
decoder.flush()?;
|
||||
@@ -221,7 +205,6 @@ impl ContentDecoder {
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentDecoder::Deflate(ref mut decoder) => match decoder.write_all(&data) {
|
||||
Ok(_) => {
|
||||
decoder.flush()?;
|
||||
@@ -234,7 +217,6 @@ impl ContentDecoder {
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
},
|
||||
_ => Ok(Some(data)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,11 +5,10 @@ use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_threadpool::{run, CpuFuture};
|
||||
#[cfg(feature = "brotli")]
|
||||
use brotli2::write::BrotliEncoder;
|
||||
use bytes::Bytes;
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
use flate2::write::{GzEncoder, ZlibEncoder};
|
||||
use futures_core::ready;
|
||||
|
||||
use crate::body::{Body, BodySize, MessageBody, ResponseBody};
|
||||
use crate::http::header::{ContentEncoding, CONTENT_ENCODING};
|
||||
@@ -18,7 +17,7 @@ use crate::{Error, ResponseHead};
|
||||
|
||||
use super::Writer;
|
||||
|
||||
const INPLACE: usize = 2049;
|
||||
const INPLACE: usize = 1024;
|
||||
|
||||
pub struct Encoder<B> {
|
||||
eof: bool,
|
||||
@@ -96,14 +95,14 @@ impl<B: MessageBody> MessageBody for Encoder<B> {
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_next(&mut self, cx: &mut Context) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
loop {
|
||||
if self.eof {
|
||||
return Poll::Ready(None);
|
||||
}
|
||||
|
||||
if let Some(ref mut fut) = self.fut {
|
||||
let mut encoder = match futures::ready!(Pin::new(fut).poll(cx)) {
|
||||
let mut encoder = match ready!(Pin::new(fut).poll(cx)) {
|
||||
Ok(item) => item,
|
||||
Err(e) => return Poll::Ready(Some(Err(e.into()))),
|
||||
};
|
||||
@@ -173,28 +172,22 @@ fn update_head(encoding: ContentEncoding, head: &mut ResponseHead) {
|
||||
}
|
||||
|
||||
enum ContentEncoder {
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
Deflate(ZlibEncoder<Writer>),
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
Gzip(GzEncoder<Writer>),
|
||||
#[cfg(feature = "brotli")]
|
||||
Br(BrotliEncoder<Writer>),
|
||||
}
|
||||
|
||||
impl ContentEncoder {
|
||||
fn encoder(encoding: ContentEncoding) -> Option<Self> {
|
||||
match encoding {
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoding::Deflate => Some(ContentEncoder::Deflate(ZlibEncoder::new(
|
||||
Writer::new(),
|
||||
flate2::Compression::fast(),
|
||||
))),
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoding::Gzip => Some(ContentEncoder::Gzip(GzEncoder::new(
|
||||
Writer::new(),
|
||||
flate2::Compression::fast(),
|
||||
))),
|
||||
#[cfg(feature = "brotli")]
|
||||
ContentEncoding::Br => {
|
||||
Some(ContentEncoder::Br(BrotliEncoder::new(Writer::new(), 3)))
|
||||
}
|
||||
@@ -205,28 +198,22 @@ impl ContentEncoder {
|
||||
#[inline]
|
||||
pub(crate) fn take(&mut self) -> Bytes {
|
||||
match *self {
|
||||
#[cfg(feature = "brotli")]
|
||||
ContentEncoder::Br(ref mut encoder) => encoder.get_mut().take(),
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoder::Deflate(ref mut encoder) => encoder.get_mut().take(),
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoder::Gzip(ref mut encoder) => encoder.get_mut().take(),
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(self) -> Result<Bytes, io::Error> {
|
||||
match self {
|
||||
#[cfg(feature = "brotli")]
|
||||
ContentEncoder::Br(encoder) => match encoder.finish() {
|
||||
Ok(writer) => Ok(writer.buf.freeze()),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoder::Gzip(encoder) => match encoder.finish() {
|
||||
Ok(writer) => Ok(writer.buf.freeze()),
|
||||
Err(err) => Err(err),
|
||||
},
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoder::Deflate(encoder) => match encoder.finish() {
|
||||
Ok(writer) => Ok(writer.buf.freeze()),
|
||||
Err(err) => Err(err),
|
||||
@@ -236,7 +223,6 @@ impl ContentEncoder {
|
||||
|
||||
fn write(&mut self, data: &[u8]) -> Result<(), io::Error> {
|
||||
match *self {
|
||||
#[cfg(feature = "brotli")]
|
||||
ContentEncoder::Br(ref mut encoder) => match encoder.write_all(data) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
@@ -244,7 +230,6 @@ impl ContentEncoder {
|
||||
Err(err)
|
||||
}
|
||||
},
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoder::Gzip(ref mut encoder) => match encoder.write_all(data) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
@@ -252,7 +237,6 @@ impl ContentEncoder {
|
||||
Err(err)
|
||||
}
|
||||
},
|
||||
#[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))]
|
||||
ContentEncoder::Deflate(ref mut encoder) => match encoder.write_all(data) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => {
|
||||
|
@@ -19,6 +19,7 @@ impl Writer {
|
||||
buf: BytesMut::with_capacity(8192),
|
||||
}
|
||||
}
|
||||
|
||||
fn take(&mut self) -> Bytes {
|
||||
self.buf.split().freeze()
|
||||
}
|
||||
@@ -29,6 +30,7 @@ impl io::Write for Writer {
|
||||
self.buf.extend_from_slice(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -6,11 +6,13 @@ use std::str::Utf8Error;
|
||||
use std::string::FromUtf8Error;
|
||||
use std::{fmt, io, result};
|
||||
|
||||
use actix_codec::{Decoder, Encoder};
|
||||
pub use actix_threadpool::BlockingError;
|
||||
use actix_utils::framed::DispatcherError as FramedDispatcherError;
|
||||
use actix_utils::timeout::TimeoutError;
|
||||
use bytes::BytesMut;
|
||||
use derive_more::{Display, From};
|
||||
pub use futures::channel::oneshot::Canceled;
|
||||
pub use futures_channel::oneshot::Canceled;
|
||||
use http::uri::InvalidUri;
|
||||
use http::{header, Error as HttpError, StatusCode};
|
||||
use httparse;
|
||||
@@ -22,7 +24,7 @@ use serde_urlencoded::ser::Error as FormError;
|
||||
use crate::body::Body;
|
||||
pub use crate::cookie::ParseError as CookieParseError;
|
||||
use crate::helpers::Writer;
|
||||
use crate::response::Response;
|
||||
use crate::response::{Response, ResponseBuilder};
|
||||
|
||||
/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
|
||||
/// for actix web operations
|
||||
@@ -102,22 +104,18 @@ impl dyn ResponseError + 'static {
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.cause, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "{:?}", &self.cause)
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", &self.cause)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
"actix-http::Error"
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&dyn std::error::Error> {
|
||||
None
|
||||
}
|
||||
@@ -157,6 +155,20 @@ impl<T: ResponseError + 'static> From<T> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert Response to a Error
|
||||
impl From<Response> for Error {
|
||||
fn from(res: Response) -> Error {
|
||||
InternalError::from_response("", res).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert ResponseBuilder to a Error
|
||||
impl From<ResponseBuilder> for Error {
|
||||
fn from(mut res: ResponseBuilder) -> Error {
|
||||
InternalError::from_response("", res.finish()).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `GATEWAY_TIMEOUT` for `TimeoutError`
|
||||
impl<E: ResponseError> ResponseError for TimeoutError<E> {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
@@ -453,6 +465,14 @@ impl ResponseError for ContentTypeError {
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, U: Encoder + Decoder> ResponseError for FramedDispatcherError<E, U>
|
||||
where
|
||||
E: fmt::Debug + fmt::Display,
|
||||
<U as Encoder>::Error: fmt::Debug,
|
||||
<U as Decoder>::Error: fmt::Debug,
|
||||
{
|
||||
}
|
||||
|
||||
/// Helper type that can wrap any error and generate custom response.
|
||||
///
|
||||
/// In following example any `io::Error` will be converted into "BAD REQUEST"
|
||||
@@ -460,14 +480,12 @@ impl ResponseError for ContentTypeError {
|
||||
/// default.
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate actix_http;
|
||||
/// # use std::io;
|
||||
/// # use actix_http::*;
|
||||
///
|
||||
/// fn index(req: Request) -> Result<&'static str> {
|
||||
/// Err(error::ErrorBadRequest(io::Error::new(io::ErrorKind::Other, "error")))
|
||||
/// }
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
pub struct InternalError<T> {
|
||||
cause: T,
|
||||
@@ -501,7 +519,7 @@ impl<T> fmt::Debug for InternalError<T>
|
||||
where
|
||||
T: fmt::Debug + 'static,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.cause, f)
|
||||
}
|
||||
}
|
||||
@@ -510,7 +528,7 @@ impl<T> fmt::Display for InternalError<T>
|
||||
where
|
||||
T: fmt::Display + 'static,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.cause, f)
|
||||
}
|
||||
}
|
||||
@@ -555,13 +573,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert Response to a Error
|
||||
impl From<Response> for Error {
|
||||
fn from(res: Response) -> Error {
|
||||
InternalError::from_response("", res).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function that creates wrapper of any error and generate *BAD
|
||||
/// REQUEST* response.
|
||||
#[allow(non_snake_case)]
|
||||
@@ -952,20 +963,15 @@ where
|
||||
InternalError::new(err, StatusCode::NETWORK_AUTHENTICATION_REQUIRED).into()
|
||||
}
|
||||
|
||||
#[cfg(feature = "fail")]
|
||||
mod failure_integration {
|
||||
use super::*;
|
||||
|
||||
/// Compatibility for `failure::Error`
|
||||
impl ResponseError for failure::Error {}
|
||||
}
|
||||
#[cfg(feature = "failure")]
|
||||
/// Compatibility for `failure::Error`
|
||||
impl ResponseError for fail_ure::Error {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use http::{Error as HttpError, StatusCode};
|
||||
use httparse;
|
||||
use std::error::Error as StdError;
|
||||
use std::io;
|
||||
|
||||
#[test]
|
||||
@@ -994,7 +1000,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_error_cause() {
|
||||
let orig = io::Error::new(io::ErrorKind::Other, "other");
|
||||
let desc = orig.description().to_owned();
|
||||
let desc = orig.to_string();
|
||||
let e = Error::from(orig);
|
||||
assert_eq!(format!("{}", e.as_response_error()), desc);
|
||||
}
|
||||
@@ -1002,7 +1008,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_error_display() {
|
||||
let orig = io::Error::new(io::ErrorKind::Other, "other");
|
||||
let desc = orig.description().to_owned();
|
||||
let desc = orig.to_string();
|
||||
let e = Error::from(orig);
|
||||
assert_eq!(format!("{}", e), desc);
|
||||
}
|
||||
@@ -1044,7 +1050,7 @@ mod tests {
|
||||
match ParseError::from($from) {
|
||||
e @ $error => {
|
||||
let desc = format!("{}", e);
|
||||
assert_eq!(desc, format!("IO error: {}", $from.description()));
|
||||
assert_eq!(desc, format!("IO error: {}", $from));
|
||||
}
|
||||
_ => unreachable!("{:?}", $from),
|
||||
}
|
||||
|
@@ -65,7 +65,7 @@ impl Extensions {
|
||||
}
|
||||
|
||||
impl fmt::Debug for Extensions {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Extensions").finish()
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,8 @@
|
||||
#![allow(unused_imports, unused_variables, dead_code)]
|
||||
use std::io::{self, Write};
|
||||
use std::rc::Rc;
|
||||
use std::io;
|
||||
|
||||
use actix_codec::{Decoder, Encoder};
|
||||
use bitflags::bitflags;
|
||||
use bytes::{BufMut, Bytes, BytesMut};
|
||||
use http::header::{
|
||||
HeaderValue, CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING, UPGRADE,
|
||||
};
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use http::{Method, Version};
|
||||
|
||||
use super::decoder::{PayloadDecoder, PayloadItem, PayloadType};
|
||||
@@ -16,11 +11,7 @@ use super::{Message, MessageType};
|
||||
use crate::body::BodySize;
|
||||
use crate::config::ServiceConfig;
|
||||
use crate::error::{ParseError, PayloadError};
|
||||
use crate::header::HeaderMap;
|
||||
use crate::helpers;
|
||||
use crate::message::{
|
||||
ConnectionType, Head, MessagePool, RequestHead, RequestHeadType, ResponseHead,
|
||||
};
|
||||
use crate::message::{ConnectionType, RequestHeadType, ResponseHead};
|
||||
|
||||
bitflags! {
|
||||
struct Flags: u8 {
|
||||
@@ -30,8 +21,6 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
const AVERAGE_HEADER_SIZE: usize = 30;
|
||||
|
||||
/// HTTP/1 Codec
|
||||
pub struct ClientCodec {
|
||||
inner: ClientCodecInner,
|
||||
@@ -51,7 +40,6 @@ struct ClientCodecInner {
|
||||
|
||||
// encoder part
|
||||
flags: Flags,
|
||||
headers_size: u32,
|
||||
encoder: encoder::MessageEncoder<RequestHeadType>,
|
||||
}
|
||||
|
||||
@@ -80,7 +68,6 @@ impl ClientCodec {
|
||||
ctype: ConnectionType::Close,
|
||||
|
||||
flags,
|
||||
headers_size: 0,
|
||||
encoder: encoder::MessageEncoder::default(),
|
||||
},
|
||||
}
|
||||
|
@@ -1,12 +1,9 @@
|
||||
#![allow(unused_imports, unused_variables, dead_code)]
|
||||
use std::io::Write;
|
||||
use std::{fmt, io, net};
|
||||
use std::{fmt, io};
|
||||
|
||||
use actix_codec::{Decoder, Encoder};
|
||||
use bitflags::bitflags;
|
||||
use bytes::{BufMut, Bytes, BytesMut};
|
||||
use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING};
|
||||
use http::{Method, StatusCode, Version};
|
||||
use bytes::BytesMut;
|
||||
use http::{Method, Version};
|
||||
|
||||
use super::decoder::{PayloadDecoder, PayloadItem, PayloadType};
|
||||
use super::{decoder, encoder};
|
||||
@@ -14,8 +11,7 @@ use super::{Message, MessageType};
|
||||
use crate::body::BodySize;
|
||||
use crate::config::ServiceConfig;
|
||||
use crate::error::ParseError;
|
||||
use crate::helpers;
|
||||
use crate::message::{ConnectionType, Head, ResponseHead};
|
||||
use crate::message::ConnectionType;
|
||||
use crate::request::Request;
|
||||
use crate::response::Response;
|
||||
|
||||
@@ -27,8 +23,6 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
const AVERAGE_HEADER_SIZE: usize = 30;
|
||||
|
||||
/// HTTP/1 Codec
|
||||
pub struct Codec {
|
||||
config: ServiceConfig,
|
||||
@@ -49,7 +43,7 @@ impl Default for Codec {
|
||||
}
|
||||
|
||||
impl fmt::Debug for Codec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "h1::Codec({:?})", self.flags)
|
||||
}
|
||||
}
|
||||
@@ -176,7 +170,6 @@ impl Encoder for Codec {
|
||||
};
|
||||
|
||||
// encode message
|
||||
let len = dst.len();
|
||||
self.encoder.encode(
|
||||
dst,
|
||||
&mut res,
|
||||
@@ -202,17 +195,11 @@ impl Encoder for Codec {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{cmp, io};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
use http::{Method, Version};
|
||||
use bytes::BytesMut;
|
||||
use http::Method;
|
||||
|
||||
use super::*;
|
||||
use crate::error::ParseError;
|
||||
use crate::h1::Message;
|
||||
use crate::httpmessage::HttpMessage;
|
||||
use crate::request::Request;
|
||||
|
||||
#[test]
|
||||
fn test_http_request_chunked_payload_and_next_message() {
|
||||
|
@@ -5,7 +5,7 @@ use std::mem::MaybeUninit;
|
||||
use std::task::Poll;
|
||||
|
||||
use actix_codec::Decoder;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use bytes::{Buf, Bytes, BytesMut};
|
||||
use http::header::{HeaderName, HeaderValue};
|
||||
use http::{header, Method, StatusCode, Uri, Version};
|
||||
use httparse;
|
||||
@@ -185,6 +185,7 @@ impl MessageType for Request {
|
||||
&mut self.head_mut().headers
|
||||
}
|
||||
|
||||
#[allow(clippy::uninit_assumed_init)]
|
||||
fn decode(src: &mut BytesMut) -> Result<Option<(Self, PayloadType)>, ParseError> {
|
||||
// Unsafe: we read only this data only after httparse parses headers into.
|
||||
// performance bump for pipeline benchmarks.
|
||||
@@ -192,7 +193,7 @@ impl MessageType for Request {
|
||||
unsafe { MaybeUninit::uninit().assume_init() };
|
||||
|
||||
let (len, method, uri, ver, h_len) = {
|
||||
let mut parsed: [httparse::Header; MAX_HEADERS] =
|
||||
let mut parsed: [httparse::Header<'_>; MAX_HEADERS] =
|
||||
unsafe { MaybeUninit::uninit().assume_init() };
|
||||
|
||||
let mut req = httparse::Request::new(&mut parsed);
|
||||
@@ -260,6 +261,7 @@ impl MessageType for ResponseHead {
|
||||
&mut self.headers
|
||||
}
|
||||
|
||||
#[allow(clippy::uninit_assumed_init)]
|
||||
fn decode(src: &mut BytesMut) -> Result<Option<(Self, PayloadType)>, ParseError> {
|
||||
// Unsafe: we read only this data only after httparse parses headers into.
|
||||
// performance bump for pipeline benchmarks.
|
||||
@@ -267,7 +269,7 @@ impl MessageType for ResponseHead {
|
||||
unsafe { MaybeUninit::uninit().assume_init() };
|
||||
|
||||
let (len, ver, status, h_len) = {
|
||||
let mut parsed: [httparse::Header; MAX_HEADERS] =
|
||||
let mut parsed: [httparse::Header<'_>; MAX_HEADERS] =
|
||||
unsafe { MaybeUninit::uninit().assume_init() };
|
||||
|
||||
let mut res = httparse::Response::new(&mut parsed);
|
||||
@@ -326,7 +328,7 @@ pub(crate) struct HeaderIndex {
|
||||
impl HeaderIndex {
|
||||
pub(crate) fn record(
|
||||
bytes: &[u8],
|
||||
headers: &[httparse::Header],
|
||||
headers: &[httparse::Header<'_>],
|
||||
indices: &mut [HeaderIndex],
|
||||
) {
|
||||
let bytes_ptr = bytes.as_ptr() as usize;
|
||||
@@ -475,7 +477,7 @@ macro_rules! byte (
|
||||
($rdr:ident) => ({
|
||||
if $rdr.len() > 0 {
|
||||
let b = $rdr[0];
|
||||
$rdr.split_to(1);
|
||||
$rdr.advance(1);
|
||||
b
|
||||
} else {
|
||||
return Poll::Pending
|
||||
|
@@ -8,7 +8,7 @@ use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed, FramedParts};
|
||||
use actix_rt::time::{delay_until, Delay, Instant};
|
||||
use actix_service::Service;
|
||||
use bitflags::bitflags;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use bytes::{Buf, BytesMut};
|
||||
use log::{error, trace};
|
||||
|
||||
use crate::body::{Body, BodySize, MessageBody, ResponseBody};
|
||||
@@ -264,7 +264,7 @@ where
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
{
|
||||
fn can_read(&self, cx: &mut Context) -> bool {
|
||||
fn can_read(&self, cx: &mut Context<'_>) -> bool {
|
||||
if self
|
||||
.flags
|
||||
.intersects(Flags::READ_DISCONNECT | Flags::UPGRADE)
|
||||
@@ -290,7 +290,7 @@ where
|
||||
///
|
||||
/// true - got whouldblock
|
||||
/// false - didnt get whouldblock
|
||||
fn poll_flush(&mut self, cx: &mut Context) -> Result<bool, DispatchError> {
|
||||
fn poll_flush(&mut self, cx: &mut Context<'_>) -> Result<bool, DispatchError> {
|
||||
if self.write_buf.is_empty() {
|
||||
return Ok(false);
|
||||
}
|
||||
@@ -312,7 +312,7 @@ where
|
||||
}
|
||||
Poll::Pending => {
|
||||
if written > 0 {
|
||||
let _ = self.write_buf.split_to(written);
|
||||
self.write_buf.advance(written);
|
||||
}
|
||||
return Ok(true);
|
||||
}
|
||||
@@ -322,7 +322,7 @@ where
|
||||
if written == self.write_buf.len() {
|
||||
unsafe { self.write_buf.set_len(0) }
|
||||
} else {
|
||||
let _ = self.write_buf.split_to(written);
|
||||
self.write_buf.advance(written);
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
@@ -355,7 +355,7 @@ where
|
||||
|
||||
fn poll_response(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Result<PollResponse, DispatchError> {
|
||||
loop {
|
||||
let state = match self.state {
|
||||
@@ -459,7 +459,7 @@ where
|
||||
fn handle_request(
|
||||
&mut self,
|
||||
req: Request,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Result<State<S, B, X>, DispatchError> {
|
||||
// Handle `EXPECT: 100-Continue` header
|
||||
let req = if req.head().expect() {
|
||||
@@ -500,7 +500,7 @@ where
|
||||
/// Process one incoming requests
|
||||
pub(self) fn poll_request(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Result<bool, DispatchError> {
|
||||
// limit a mount of non processed requests
|
||||
if self.messages.len() >= MAX_PIPELINED_MESSAGES || !self.can_read(cx) {
|
||||
@@ -604,7 +604,7 @@ where
|
||||
}
|
||||
|
||||
/// keep-alive timer
|
||||
fn poll_keepalive(&mut self, cx: &mut Context) -> Result<(), DispatchError> {
|
||||
fn poll_keepalive(&mut self, cx: &mut Context<'_>) -> Result<(), DispatchError> {
|
||||
if self.ka_timer.is_none() {
|
||||
// shutdown timeout
|
||||
if self.flags.contains(Flags::SHUTDOWN) {
|
||||
@@ -710,7 +710,7 @@ where
|
||||
type Output = Result<(), DispatchError>;
|
||||
|
||||
#[inline]
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.as_mut().inner {
|
||||
DispatcherState::Normal(ref mut inner) => {
|
||||
inner.poll_keepalive(cx)?;
|
||||
@@ -750,8 +750,10 @@ where
|
||||
};
|
||||
|
||||
loop {
|
||||
if inner.write_buf.remaining_mut() < LW_BUFFER_SIZE {
|
||||
inner.write_buf.reserve(HW_BUFFER_SIZE);
|
||||
let remaining =
|
||||
inner.write_buf.capacity() - inner.write_buf.len();
|
||||
if remaining < LW_BUFFER_SIZE {
|
||||
inner.write_buf.reserve(HW_BUFFER_SIZE - remaining);
|
||||
}
|
||||
let result = inner.poll_response(cx)?;
|
||||
let drain = result == PollResponse::DrainWriteBuf;
|
||||
@@ -832,7 +834,7 @@ where
|
||||
}
|
||||
|
||||
fn read_available<T>(
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
io: &mut T,
|
||||
buf: &mut BytesMut,
|
||||
) -> Result<Option<bool>, io::Error>
|
||||
@@ -841,8 +843,9 @@ where
|
||||
{
|
||||
let mut read_some = false;
|
||||
loop {
|
||||
if buf.remaining_mut() < LW_BUFFER_SIZE {
|
||||
buf.reserve(HW_BUFFER_SIZE);
|
||||
let remaining = buf.capacity() - buf.len();
|
||||
if remaining < LW_BUFFER_SIZE {
|
||||
buf.reserve(HW_BUFFER_SIZE - remaining);
|
||||
}
|
||||
|
||||
match read(cx, io, buf) {
|
||||
@@ -874,7 +877,7 @@ where
|
||||
}
|
||||
|
||||
fn read<T>(
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
io: &mut T,
|
||||
buf: &mut BytesMut,
|
||||
) -> Poll<Result<usize, io::Error>>
|
||||
@@ -887,7 +890,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix_service::IntoService;
|
||||
use futures::future::{lazy, ok};
|
||||
use futures_util::future::{lazy, ok};
|
||||
|
||||
use super::*;
|
||||
use crate::error::Error;
|
||||
|
@@ -1,25 +1,18 @@
|
||||
#![allow(unused_imports, unused_variables, dead_code)]
|
||||
use std::fmt::Write as FmtWrite;
|
||||
use std::io::Write;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr::copy_nonoverlapping;
|
||||
use std::rc::Rc;
|
||||
use std::slice::from_raw_parts_mut;
|
||||
use std::str::FromStr;
|
||||
use std::{cmp, fmt, io, mem};
|
||||
use std::{cmp, io};
|
||||
|
||||
use bytes::{buf::BufMutExt, BufMut, Bytes, BytesMut};
|
||||
use bytes::{buf::BufMutExt, BufMut, BytesMut};
|
||||
|
||||
use crate::body::BodySize;
|
||||
use crate::config::ServiceConfig;
|
||||
use crate::header::{map, ContentEncoding};
|
||||
use crate::header::map;
|
||||
use crate::helpers;
|
||||
use crate::http::header::{
|
||||
HeaderValue, ACCEPT_ENCODING, CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING,
|
||||
};
|
||||
use crate::http::{HeaderMap, Method, StatusCode, Version};
|
||||
use crate::message::{ConnectionType, Head, RequestHead, RequestHeadType, ResponseHead};
|
||||
use crate::request::Request;
|
||||
use crate::http::header::{CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING};
|
||||
use crate::http::{HeaderMap, StatusCode, Version};
|
||||
use crate::message::{ConnectionType, RequestHeadType};
|
||||
use crate::response::Response;
|
||||
|
||||
const AVERAGE_HEADER_SIZE: usize = 30;
|
||||
@@ -108,6 +101,7 @@ pub(crate) trait MessageType: Sized {
|
||||
} else {
|
||||
dst.put_slice(b"\r\ncontent-length: ");
|
||||
}
|
||||
#[allow(clippy::write_with_newline)]
|
||||
write!(dst.writer(), "{}\r\n", len)?;
|
||||
}
|
||||
BodySize::None => dst.put_slice(b"\r\n"),
|
||||
@@ -527,12 +521,14 @@ fn write_camel_case(value: &[u8], buffer: &mut [u8]) {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::rc::Rc;
|
||||
|
||||
use bytes::Bytes;
|
||||
//use std::rc::Rc;
|
||||
use http::header::AUTHORIZATION;
|
||||
|
||||
use super::*;
|
||||
use crate::http::header::{HeaderValue, CONTENT_TYPE};
|
||||
use http::header::AUTHORIZATION;
|
||||
use crate::RequestHead;
|
||||
|
||||
#[test]
|
||||
fn test_chunked_te() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use futures::future::{ok, Ready};
|
||||
use futures_util::future::{ok, Ready};
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::request::Request;
|
||||
@@ -28,7 +28,7 @@ impl Service for ExpectHandler {
|
||||
type Error = Error;
|
||||
type Future = Ready<Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@ use std::task::{Context, Poll};
|
||||
|
||||
use actix_utils::task::LocalWaker;
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
use futures_core::Stream;
|
||||
|
||||
use crate::error::PayloadError;
|
||||
|
||||
@@ -82,7 +82,7 @@ impl Payload {
|
||||
#[inline]
|
||||
pub fn readany(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||
self.inner.borrow_mut().readany(cx)
|
||||
}
|
||||
@@ -93,7 +93,7 @@ impl Stream for Payload {
|
||||
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||
self.inner.borrow_mut().readany(cx)
|
||||
}
|
||||
@@ -127,7 +127,7 @@ impl PayloadSender {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn need_read(&self, cx: &mut Context) -> PayloadStatus {
|
||||
pub fn need_read(&self, cx: &mut Context<'_>) -> PayloadStatus {
|
||||
// we check need_read only if Payload (other side) is alive,
|
||||
// otherwise always return true (consume payload)
|
||||
if let Some(shared) = self.inner.upgrade() {
|
||||
@@ -194,7 +194,7 @@ impl Inner {
|
||||
|
||||
fn readany(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||
if let Some(data) = self.items.pop_front() {
|
||||
self.len -= data.len();
|
||||
@@ -226,7 +226,7 @@ impl Inner {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use futures::future::poll_fn;
|
||||
use futures_util::future::poll_fn;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_unread_data() {
|
||||
|
@@ -8,8 +8,8 @@ use std::{fmt, net};
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_service::{pipeline_factory, IntoServiceFactory, Service, ServiceFactory};
|
||||
use futures::future::{ok, Ready};
|
||||
use futures::ready;
|
||||
use futures_core::ready;
|
||||
use futures_util::future::{ok, Ready};
|
||||
|
||||
use crate::body::MessageBody;
|
||||
use crate::cloneable::CloneableService;
|
||||
@@ -72,7 +72,7 @@ where
|
||||
Request = (Request, Framed<TcpStream, Codec>),
|
||||
Response = (),
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
U::InitError: fmt::Debug,
|
||||
{
|
||||
/// Create simple tcp stream service
|
||||
@@ -115,7 +115,7 @@ mod openssl {
|
||||
Request = (Request, Framed<SslStream<TcpStream>, Codec>),
|
||||
Response = (),
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
U::InitError: fmt::Debug,
|
||||
{
|
||||
/// Create openssl based service
|
||||
@@ -165,7 +165,7 @@ mod rustls {
|
||||
Request = (Request, Framed<TlsStream<TcpStream>, Codec>),
|
||||
Response = (),
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
U::InitError: fmt::Debug,
|
||||
{
|
||||
/// Create rustls based service
|
||||
@@ -255,7 +255,7 @@ where
|
||||
X::Error: Into<Error>,
|
||||
X::InitError: fmt::Debug,
|
||||
U: ServiceFactory<Config = (), Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
U::InitError: fmt::Debug,
|
||||
{
|
||||
type Config = ();
|
||||
@@ -324,7 +324,7 @@ where
|
||||
{
|
||||
type Output = Result<H1ServiceHandler<T, S::Service, B, X::Service, U::Service>, ()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
if let Some(fut) = this.fut_ex.as_pin_mut() {
|
||||
@@ -412,14 +412,14 @@ where
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
{
|
||||
type Request = (T, Option<net::SocketAddr>);
|
||||
type Response = ();
|
||||
type Error = DispatchError;
|
||||
type Future = Dispatcher<T, S, B, X, U>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
let ready = self
|
||||
.expect
|
||||
.poll_ready(cx)
|
||||
@@ -441,6 +441,19 @@ where
|
||||
.is_ready()
|
||||
&& ready;
|
||||
|
||||
let ready = if let Some(ref mut upg) = self.upgrade {
|
||||
upg.poll_ready(cx)
|
||||
.map_err(|e| {
|
||||
let e = e.into();
|
||||
log::error!("Http service readiness error: {:?}", e);
|
||||
DispatchError::Service(e)
|
||||
})?
|
||||
.is_ready()
|
||||
&& ready
|
||||
} else {
|
||||
ready
|
||||
};
|
||||
|
||||
if ready {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
@@ -523,7 +536,7 @@ where
|
||||
type Error = ParseError;
|
||||
type Future = OneRequestServiceResponse<T>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
@@ -548,7 +561,7 @@ where
|
||||
{
|
||||
type Output = Result<(Request, Framed<T, Codec>), ParseError>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.framed.as_mut().unwrap().next_item(cx) {
|
||||
Poll::Ready(Some(Ok(req))) => match req {
|
||||
Message::Item(req) => {
|
||||
|
@@ -3,7 +3,7 @@ use std::task::{Context, Poll};
|
||||
|
||||
use actix_codec::Framed;
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use futures::future::Ready;
|
||||
use futures_util::future::Ready;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::h1::Codec;
|
||||
@@ -31,7 +31,7 @@ impl<T> Service for UpgradeHandler<T> {
|
||||
type Error = Error;
|
||||
type Future = Ready<Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
|
@@ -39,7 +39,7 @@ where
|
||||
{
|
||||
type Output = Result<Framed<T, Codec>, Error>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
|
||||
loop {
|
||||
|
@@ -1,28 +1,23 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::convert::TryFrom;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::net;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::{fmt, mem, net};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use actix_rt::time::{Delay, Instant};
|
||||
use actix_service::Service;
|
||||
use bitflags::bitflags;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::{ready, Sink, Stream};
|
||||
use h2::server::{Connection, SendResponse};
|
||||
use h2::{RecvStream, SendStream};
|
||||
use http::header::{
|
||||
HeaderValue, ACCEPT_ENCODING, CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING,
|
||||
};
|
||||
use log::{debug, error, trace};
|
||||
use h2::SendStream;
|
||||
use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING};
|
||||
use log::{error, trace};
|
||||
|
||||
use crate::body::{Body, BodySize, MessageBody, ResponseBody};
|
||||
use crate::body::{BodySize, MessageBody, ResponseBody};
|
||||
use crate::cloneable::CloneableService;
|
||||
use crate::config::ServiceConfig;
|
||||
use crate::error::{DispatchError, Error, ParseError, PayloadError, ResponseError};
|
||||
use crate::error::{DispatchError, Error};
|
||||
use crate::helpers::DataFactory;
|
||||
use crate::httpmessage::HttpMessage;
|
||||
use crate::message::ResponseHead;
|
||||
@@ -106,7 +101,7 @@ where
|
||||
type Output = Result<(), DispatchError>;
|
||||
|
||||
#[inline]
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
|
||||
loop {
|
||||
@@ -252,7 +247,7 @@ where
|
||||
{
|
||||
type Output = ();
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
match this.state {
|
||||
|
@@ -1,11 +1,9 @@
|
||||
#![allow(dead_code, unused_imports)]
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
//! HTTP/2 implementation
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
use futures_core::Stream;
|
||||
use h2::RecvStream;
|
||||
|
||||
mod dispatcher;
|
||||
@@ -29,7 +27,10 @@ impl Payload {
|
||||
impl Stream for Payload {
|
||||
type Item = Result<Bytes, PayloadError>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
let this = self.get_mut();
|
||||
|
||||
match Pin::new(&mut this.pl).poll_data(cx) {
|
||||
|
@@ -1,32 +1,28 @@
|
||||
use std::fmt::Debug;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::{io, net, rc};
|
||||
use std::{net, rc};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use actix_codec::{AsyncRead, AsyncWrite};
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_service::{
|
||||
factory_fn, pipeline_factory, service_fn2, IntoServiceFactory, Service,
|
||||
fn_factory, fn_service, pipeline_factory, IntoServiceFactory, Service,
|
||||
ServiceFactory,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use futures::future::{ok, Ready};
|
||||
use futures::{ready, Stream};
|
||||
use h2::server::{self, Connection, Handshake};
|
||||
use h2::RecvStream;
|
||||
use futures_core::ready;
|
||||
use futures_util::future::ok;
|
||||
use h2::server::{self, Handshake};
|
||||
use log::error;
|
||||
|
||||
use crate::body::MessageBody;
|
||||
use crate::cloneable::CloneableService;
|
||||
use crate::config::{KeepAlive, ServiceConfig};
|
||||
use crate::error::{DispatchError, Error, ParseError, ResponseError};
|
||||
use crate::config::ServiceConfig;
|
||||
use crate::error::{DispatchError, Error};
|
||||
use crate::helpers::DataFactory;
|
||||
use crate::payload::Payload;
|
||||
use crate::request::Request;
|
||||
use crate::response::Response;
|
||||
use crate::Protocol;
|
||||
|
||||
use super::dispatcher::Dispatcher;
|
||||
|
||||
@@ -87,9 +83,9 @@ where
|
||||
Error = DispatchError,
|
||||
InitError = S::InitError,
|
||||
> {
|
||||
pipeline_factory(factory_fn(|| {
|
||||
pipeline_factory(fn_factory(|| {
|
||||
async {
|
||||
Ok::<_, S::InitError>(service_fn2(|io: TcpStream| {
|
||||
Ok::<_, S::InitError>(fn_service(|io: TcpStream| {
|
||||
let peer_addr = io.peer_addr().ok();
|
||||
ok::<_, DispatchError>((io, peer_addr))
|
||||
}))
|
||||
@@ -101,7 +97,7 @@ where
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
mod openssl {
|
||||
use actix_service::{factory_fn, service_fn2};
|
||||
use actix_service::{fn_factory, fn_service};
|
||||
use actix_tls::openssl::{Acceptor, SslAcceptor, SslStream};
|
||||
use actix_tls::{openssl::HandshakeError, SslError};
|
||||
|
||||
@@ -131,8 +127,8 @@ mod openssl {
|
||||
.map_err(SslError::Ssl)
|
||||
.map_init_err(|_| panic!()),
|
||||
)
|
||||
.and_then(factory_fn(|| {
|
||||
ok::<_, S::InitError>(service_fn2(|io: SslStream<TcpStream>| {
|
||||
.and_then(fn_factory(|| {
|
||||
ok::<_, S::InitError>(fn_service(|io: SslStream<TcpStream>| {
|
||||
let peer_addr = io.get_ref().peer_addr().ok();
|
||||
ok((io, peer_addr))
|
||||
}))
|
||||
@@ -145,9 +141,9 @@ mod openssl {
|
||||
#[cfg(feature = "rustls")]
|
||||
mod rustls {
|
||||
use super::*;
|
||||
use actix_tls::rustls::{Acceptor, ServerConfig, Session, TlsStream};
|
||||
use actix_tls::rustls::{Acceptor, ServerConfig, TlsStream};
|
||||
use actix_tls::SslError;
|
||||
use std::{fmt, io};
|
||||
use std::io;
|
||||
|
||||
impl<S, B> H2Service<TlsStream<TcpStream>, S, B>
|
||||
where
|
||||
@@ -176,8 +172,8 @@ mod rustls {
|
||||
.map_err(SslError::Ssl)
|
||||
.map_init_err(|_| panic!()),
|
||||
)
|
||||
.and_then(factory_fn(|| {
|
||||
ok::<_, S::InitError>(service_fn2(|io: TlsStream<TcpStream>| {
|
||||
.and_then(fn_factory(|| {
|
||||
ok::<_, S::InitError>(fn_service(|io: TlsStream<TcpStream>| {
|
||||
let peer_addr = io.get_ref().0.peer_addr().ok();
|
||||
ok((io, peer_addr))
|
||||
}))
|
||||
@@ -235,7 +231,7 @@ where
|
||||
{
|
||||
type Output = Result<H2ServiceHandler<T, S::Service, B>, S::InitError>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.as_mut().project();
|
||||
|
||||
Poll::Ready(ready!(this.fut.poll(cx)).map(|service| {
|
||||
@@ -293,7 +289,7 @@ where
|
||||
type Error = DispatchError;
|
||||
type Future = H2ServiceHandlerResponse<T, S, B>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.srv.poll_ready(cx).map_err(|e| {
|
||||
let e = e.into();
|
||||
error!("Service readiness error: {:?}", e);
|
||||
@@ -358,7 +354,7 @@ where
|
||||
{
|
||||
type Output = Result<(), DispatchError>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.state {
|
||||
State::Incoming(ref mut disp) => Pin::new(disp).poll(cx),
|
||||
State::Handshake(
|
||||
|
@@ -74,7 +74,7 @@ impl Header for CacheControl {
|
||||
}
|
||||
|
||||
impl fmt::Display for CacheControl {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt_comma_delimited(f, &self[..])
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ pub enum CacheDirective {
|
||||
}
|
||||
|
||||
impl fmt::Display for CacheDirective {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use self::CacheDirective::*;
|
||||
fmt::Display::fmt(
|
||||
match *self {
|
||||
|
@@ -486,7 +486,7 @@ impl Header for ContentDisposition {
|
||||
}
|
||||
|
||||
impl fmt::Display for DispositionType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
DispositionType::Inline => write!(f, "inline"),
|
||||
DispositionType::Attachment => write!(f, "attachment"),
|
||||
@@ -497,7 +497,7 @@ impl fmt::Display for DispositionType {
|
||||
}
|
||||
|
||||
impl fmt::Display for DispositionParam {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// All ASCII control characters (0-30, 127) including horizontal tab, double quote, and
|
||||
// backslash should be escaped in quoted-string (i.e. "foobar").
|
||||
// Ref: RFC6266 S4.1 -> RFC2616 S3.6
|
||||
@@ -555,7 +555,7 @@ impl fmt::Display for DispositionParam {
|
||||
}
|
||||
|
||||
impl fmt::Display for ContentDisposition {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.disposition)?;
|
||||
self.parameters
|
||||
.iter()
|
||||
|
@@ -166,7 +166,7 @@ impl FromStr for ContentRangeSpec {
|
||||
}
|
||||
|
||||
impl Display for ContentRangeSpec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ContentRangeSpec::Bytes {
|
||||
range,
|
||||
|
@@ -87,7 +87,7 @@ impl Header for IfRange {
|
||||
}
|
||||
|
||||
impl Display for IfRange {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
IfRange::EntityTag(ref x) => Display::fmt(x, f),
|
||||
IfRange::Date(ref x) => Display::fmt(x, f),
|
||||
|
@@ -159,7 +159,7 @@ macro_rules! header {
|
||||
}
|
||||
impl std::fmt::Display for $id {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
$crate::http::header::fmt_comma_delimited(f, &self.0[..])
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ macro_rules! header {
|
||||
}
|
||||
impl std::fmt::Display for $id {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
$crate::http::header::fmt_comma_delimited(f, &self.0[..])
|
||||
}
|
||||
}
|
||||
@@ -231,7 +231,7 @@ macro_rules! header {
|
||||
}
|
||||
impl std::fmt::Display for $id {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
@@ -276,7 +276,7 @@ macro_rules! header {
|
||||
}
|
||||
impl std::fmt::Display for $id {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match *self {
|
||||
$id::Any => f.write_str("*"),
|
||||
$id::Items(ref fields) => $crate::http::header::fmt_comma_delimited(
|
||||
|
@@ -143,7 +143,7 @@ impl HeaderMap {
|
||||
/// Returns `None` if there are no values associated with the key.
|
||||
///
|
||||
/// [`GetAll`]: struct.GetAll.html
|
||||
pub fn get_all<N: AsName>(&self, name: N) -> GetAll {
|
||||
pub fn get_all<N: AsName>(&self, name: N) -> GetAll<'_> {
|
||||
GetAll {
|
||||
idx: 0,
|
||||
item: self.get2(name),
|
||||
@@ -187,7 +187,7 @@ impl HeaderMap {
|
||||
/// The iteration order is arbitrary, but consistent across platforms for
|
||||
/// the same crate version. Each key will be yielded once per associated
|
||||
/// value. So, if a key has 3 associated values, it will be yielded 3 times.
|
||||
pub fn iter(&self) -> Iter {
|
||||
pub fn iter(&self) -> Iter<'_> {
|
||||
Iter::new(self.inner.iter())
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ impl HeaderMap {
|
||||
/// The iteration order is arbitrary, but consistent across platforms for
|
||||
/// the same crate version. Each key will be yielded only once even if it
|
||||
/// has multiple associated values.
|
||||
pub fn keys(&self) -> Keys {
|
||||
pub fn keys(&self) -> Keys<'_> {
|
||||
Keys(self.inner.keys())
|
||||
}
|
||||
|
||||
|
@@ -217,7 +217,7 @@ impl fmt::Write for Writer {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
|
||||
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
|
||||
fmt::write(self, args)
|
||||
}
|
||||
}
|
||||
@@ -259,7 +259,7 @@ pub fn from_one_raw_str<T: FromStr>(val: Option<&HeaderValue>) -> Result<T, Pars
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
/// Format an array into a comma-delimited string.
|
||||
pub fn fmt_comma_delimited<T>(f: &mut fmt::Formatter, parts: &[T]) -> fmt::Result
|
||||
pub fn fmt_comma_delimited<T>(f: &mut fmt::Formatter<'_>, parts: &[T]) -> fmt::Result
|
||||
where
|
||||
T: fmt::Display,
|
||||
{
|
||||
@@ -361,7 +361,7 @@ pub fn parse_extended_value(
|
||||
}
|
||||
|
||||
impl fmt::Display for ExtendedValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let encoded_value =
|
||||
percent_encoding::percent_encode(&self.value[..], HTTP_VALUE);
|
||||
if let Some(ref lang) = self.language_tag {
|
||||
@@ -376,7 +376,7 @@ impl fmt::Display for ExtendedValue {
|
||||
/// [https://tools.ietf.org/html/rfc5987#section-3.2][url]
|
||||
///
|
||||
/// [url]: https://tools.ietf.org/html/rfc5987#section-3.2
|
||||
pub fn http_percent_encode(f: &mut fmt::Formatter, bytes: &[u8]) -> fmt::Result {
|
||||
pub fn http_percent_encode(f: &mut fmt::Formatter<'_>, bytes: &[u8]) -> fmt::Result {
|
||||
let encoded = percent_encoding::percent_encode(bytes, HTTP_VALUE);
|
||||
fmt::Display::fmt(&encoded, f)
|
||||
}
|
||||
|
@@ -98,7 +98,7 @@ impl Charset {
|
||||
}
|
||||
|
||||
impl Display for Charset {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.label())
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ pub enum Encoding {
|
||||
}
|
||||
|
||||
impl fmt::Display for Encoding {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match *self {
|
||||
Chunked => "chunked",
|
||||
Brotli => "br",
|
||||
|
@@ -113,7 +113,7 @@ impl EntityTag {
|
||||
}
|
||||
|
||||
impl Display for EntityTag {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.weak {
|
||||
write!(f, "W/\"{}\"", self.tag)
|
||||
} else {
|
||||
|
@@ -28,7 +28,7 @@ impl FromStr for HttpDate {
|
||||
}
|
||||
|
||||
impl Display for HttpDate {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0.to_utc().rfc822(), f)
|
||||
}
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ impl<T: PartialEq> cmp::PartialOrd for QualityItem<T> {
|
||||
}
|
||||
|
||||
impl<T: fmt::Display> fmt::Display for QualityItem<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.item, f)?;
|
||||
match self.quality.0 {
|
||||
1000 => Ok(()),
|
||||
|
@@ -25,10 +25,10 @@ pub trait HttpMessage: Sized {
|
||||
fn take_payload(&mut self) -> Payload<Self::Stream>;
|
||||
|
||||
/// Request's extensions container
|
||||
fn extensions(&self) -> Ref<Extensions>;
|
||||
fn extensions(&self) -> Ref<'_, Extensions>;
|
||||
|
||||
/// Mutable reference to a the request's extensions container
|
||||
fn extensions_mut(&self) -> RefMut<Extensions>;
|
||||
fn extensions_mut(&self) -> RefMut<'_, Extensions>;
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Get a header
|
||||
@@ -105,7 +105,7 @@ pub trait HttpMessage: Sized {
|
||||
|
||||
/// Load request cookies.
|
||||
#[inline]
|
||||
fn cookies(&self) -> Result<Ref<Vec<Cookie<'static>>>, CookieParseError> {
|
||||
fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
|
||||
if self.extensions().get::<Cookies>().is_none() {
|
||||
let mut cookies = Vec::new();
|
||||
for hdr in self.headers().get_all(header::COOKIE) {
|
||||
@@ -153,12 +153,12 @@ where
|
||||
}
|
||||
|
||||
/// Request's extensions container
|
||||
fn extensions(&self) -> Ref<Extensions> {
|
||||
fn extensions(&self) -> Ref<'_, Extensions> {
|
||||
(**self).extensions()
|
||||
}
|
||||
|
||||
/// Mutable reference to a the request's extensions container
|
||||
fn extensions_mut(&self) -> RefMut<Extensions> {
|
||||
fn extensions_mut(&self) -> RefMut<'_, Extensions> {
|
||||
(**self).extensions_mut()
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
//! Basic http primitives for actix-net framework.
|
||||
#![deny(rust_2018_idioms, warnings)]
|
||||
#![allow(
|
||||
clippy::type_complexity,
|
||||
clippy::too_many_arguments,
|
||||
clippy::new_without_default,
|
||||
clippy::borrow_interior_mutable_const,
|
||||
clippy::write_with_newline
|
||||
clippy::borrow_interior_mutable_const
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
@@ -15,6 +15,7 @@ mod builder;
|
||||
pub mod client;
|
||||
mod cloneable;
|
||||
mod config;
|
||||
#[cfg(feature = "compress")]
|
||||
pub mod encoding;
|
||||
mod extensions;
|
||||
mod header;
|
||||
|
@@ -78,13 +78,13 @@ impl Head for RequestHead {
|
||||
impl RequestHead {
|
||||
/// Message extensions
|
||||
#[inline]
|
||||
pub fn extensions(&self) -> Ref<Extensions> {
|
||||
pub fn extensions(&self) -> Ref<'_, Extensions> {
|
||||
self.extensions.borrow()
|
||||
}
|
||||
|
||||
/// Mutable reference to a the message's extensions
|
||||
#[inline]
|
||||
pub fn extensions_mut(&self) -> RefMut<Extensions> {
|
||||
pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
|
||||
self.extensions.borrow_mut()
|
||||
}
|
||||
|
||||
@@ -237,13 +237,13 @@ impl ResponseHead {
|
||||
|
||||
/// Message extensions
|
||||
#[inline]
|
||||
pub fn extensions(&self) -> Ref<Extensions> {
|
||||
pub fn extensions(&self) -> Ref<'_, Extensions> {
|
||||
self.extensions.borrow()
|
||||
}
|
||||
|
||||
/// Mutable reference to a the message's extensions
|
||||
#[inline]
|
||||
pub fn extensions_mut(&self) -> RefMut<Extensions> {
|
||||
pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
|
||||
self.extensions.borrow_mut()
|
||||
}
|
||||
|
||||
|
@@ -2,7 +2,7 @@ use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
use futures_core::Stream;
|
||||
use h2::RecvStream;
|
||||
|
||||
use crate::error::PayloadError;
|
||||
@@ -56,7 +56,10 @@ where
|
||||
type Item = Result<Bytes, PayloadError>;
|
||||
|
||||
#[inline]
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
match self.get_mut() {
|
||||
Payload::None => Poll::Ready(None),
|
||||
Payload::H1(ref mut pl) => pl.readany(cx),
|
||||
|
@@ -25,13 +25,13 @@ impl<P> HttpMessage for Request<P> {
|
||||
|
||||
/// Request extensions
|
||||
#[inline]
|
||||
fn extensions(&self) -> Ref<Extensions> {
|
||||
fn extensions(&self) -> Ref<'_, Extensions> {
|
||||
self.head.extensions()
|
||||
}
|
||||
|
||||
/// Mutable reference to a the request's extensions
|
||||
#[inline]
|
||||
fn extensions_mut(&self) -> RefMut<Extensions> {
|
||||
fn extensions_mut(&self) -> RefMut<'_, Extensions> {
|
||||
self.head.extensions_mut()
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ impl<P> Request<P> {
|
||||
}
|
||||
|
||||
impl<P> fmt::Debug for Request<P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(
|
||||
f,
|
||||
"\nRequest {:?} {}:{}",
|
||||
|
@@ -7,7 +7,7 @@ use std::task::{Context, Poll};
|
||||
use std::{fmt, str};
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::stream::Stream;
|
||||
use futures_core::Stream;
|
||||
use serde::Serialize;
|
||||
use serde_json;
|
||||
|
||||
@@ -130,7 +130,7 @@ impl<B> Response<B> {
|
||||
|
||||
/// Get an iterator for the cookies set by this response
|
||||
#[inline]
|
||||
pub fn cookies(&self) -> CookieIter {
|
||||
pub fn cookies(&self) -> CookieIter<'_> {
|
||||
CookieIter {
|
||||
iter: self.head.headers.get_all(header::SET_COOKIE),
|
||||
}
|
||||
@@ -138,7 +138,7 @@ impl<B> Response<B> {
|
||||
|
||||
/// Add a cookie to this response
|
||||
#[inline]
|
||||
pub fn add_cookie(&mut self, cookie: &Cookie) -> Result<(), HttpError> {
|
||||
pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
|
||||
let h = &mut self.head.headers;
|
||||
HeaderValue::from_str(&cookie.to_string())
|
||||
.map(|c| {
|
||||
@@ -186,13 +186,13 @@ impl<B> Response<B> {
|
||||
|
||||
/// Responses extensions
|
||||
#[inline]
|
||||
pub fn extensions(&self) -> Ref<Extensions> {
|
||||
pub fn extensions(&self) -> Ref<'_, Extensions> {
|
||||
self.head.extensions.borrow()
|
||||
}
|
||||
|
||||
/// Mutable reference to a the response's extensions
|
||||
#[inline]
|
||||
pub fn extensions_mut(&mut self) -> RefMut<Extensions> {
|
||||
pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
|
||||
self.head.extensions.borrow_mut()
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ impl<B> Response<B> {
|
||||
}
|
||||
|
||||
impl<B: MessageBody> fmt::Debug for Response<B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let res = writeln!(
|
||||
f,
|
||||
"\nResponse {:?} {}{}",
|
||||
@@ -285,7 +285,7 @@ impl<B: MessageBody> fmt::Debug for Response<B> {
|
||||
impl Future for Response {
|
||||
type Output = Result<Response, Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, _: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Poll::Ready(Ok(Response {
|
||||
head: self.head.take(),
|
||||
body: self.body.take_body(),
|
||||
@@ -354,7 +354,6 @@ impl ResponseBuilder {
|
||||
/// ))
|
||||
/// .finish())
|
||||
/// }
|
||||
/// fn main() {}
|
||||
/// ```
|
||||
#[doc(hidden)]
|
||||
pub fn set<H: Header>(&mut self, hdr: H) -> &mut Self {
|
||||
@@ -380,7 +379,6 @@ impl ResponseBuilder {
|
||||
/// .header(http::header::CONTENT_TYPE, "application/json")
|
||||
/// .finish()
|
||||
/// }
|
||||
/// fn main() {}
|
||||
/// ```
|
||||
pub fn header<K, V>(&mut self, key: K, value: V) -> &mut Self
|
||||
where
|
||||
@@ -413,7 +411,6 @@ impl ResponseBuilder {
|
||||
/// .set_header(http::header::CONTENT_TYPE, "application/json")
|
||||
/// .finish()
|
||||
/// }
|
||||
/// fn main() {}
|
||||
/// ```
|
||||
pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
|
||||
where
|
||||
@@ -588,14 +585,14 @@ impl ResponseBuilder {
|
||||
|
||||
/// Responses extensions
|
||||
#[inline]
|
||||
pub fn extensions(&self) -> Ref<Extensions> {
|
||||
pub fn extensions(&self) -> Ref<'_, Extensions> {
|
||||
let head = self.head.as_ref().expect("cannot reuse response builder");
|
||||
head.extensions.borrow()
|
||||
}
|
||||
|
||||
/// Mutable reference to a the response's extensions
|
||||
#[inline]
|
||||
pub fn extensions_mut(&mut self) -> RefMut<Extensions> {
|
||||
pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
|
||||
let head = self.head.as_ref().expect("cannot reuse response builder");
|
||||
head.extensions.borrow_mut()
|
||||
}
|
||||
@@ -765,13 +762,13 @@ impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
||||
impl Future for ResponseBuilder {
|
||||
type Output = Result<Response, Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, _: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Poll::Ready(Ok(self.finish()))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ResponseBuilder {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let head = self.head.as_ref().unwrap();
|
||||
|
||||
let res = writeln!(
|
||||
|
@@ -7,7 +7,8 @@ use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_service::{pipeline_factory, IntoServiceFactory, Service, ServiceFactory};
|
||||
use bytes::Bytes;
|
||||
use futures::{future::ok, ready, Future};
|
||||
use futures_core::{ready, Future};
|
||||
use futures_util::future::ok;
|
||||
use h2::server::{self, Handshake};
|
||||
use pin_project::{pin_project, project};
|
||||
|
||||
@@ -168,7 +169,7 @@ where
|
||||
Request = (Request, Framed<TcpStream, h1::Codec>),
|
||||
Response = (),
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
U::InitError: fmt::Debug,
|
||||
<U::Service as Service>::Future: 'static,
|
||||
{
|
||||
@@ -213,7 +214,7 @@ mod openssl {
|
||||
Request = (Request, Framed<SslStream<TcpStream>, h1::Codec>),
|
||||
Response = (),
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
U::InitError: fmt::Debug,
|
||||
<U::Service as Service>::Future: 'static,
|
||||
{
|
||||
@@ -275,7 +276,7 @@ mod rustls {
|
||||
Request = (Request, Framed<TlsStream<TcpStream>, h1::Codec>),
|
||||
Response = (),
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
U::InitError: fmt::Debug,
|
||||
<U::Service as Service>::Future: 'static,
|
||||
{
|
||||
@@ -334,7 +335,7 @@ where
|
||||
Request = (Request, Framed<T, h1::Codec>),
|
||||
Response = (),
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
U::InitError: fmt::Debug,
|
||||
<U::Service as Service>::Future: 'static,
|
||||
{
|
||||
@@ -403,7 +404,7 @@ where
|
||||
type Output =
|
||||
Result<HttpServiceHandler<T, S::Service, B, X::Service, U::Service>, ()>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
if let Some(fut) = this.fut_ex.as_pin_mut() {
|
||||
@@ -492,14 +493,14 @@ where
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, h1::Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Error: fmt::Display + Into<Error>,
|
||||
{
|
||||
type Request = (T, Protocol, Option<net::SocketAddr>);
|
||||
type Response = ();
|
||||
type Error = DispatchError;
|
||||
type Future = HttpServiceHandlerResponse<T, S, B, X, U>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
let ready = self
|
||||
.expect
|
||||
.poll_ready(cx)
|
||||
@@ -521,6 +522,19 @@ where
|
||||
.is_ready()
|
||||
&& ready;
|
||||
|
||||
let ready = if let Some(ref mut upg) = self.upgrade {
|
||||
upg.poll_ready(cx)
|
||||
.map_err(|e| {
|
||||
let e = e.into();
|
||||
log::error!("Http service readiness error: {:?}", e);
|
||||
DispatchError::Service(e)
|
||||
})?
|
||||
.is_ready()
|
||||
&& ready
|
||||
} else {
|
||||
ready
|
||||
};
|
||||
|
||||
if ready {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
@@ -619,7 +633,7 @@ where
|
||||
{
|
||||
type Output = Result<(), DispatchError>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
self.project().state.poll(cx)
|
||||
}
|
||||
}
|
||||
@@ -639,7 +653,7 @@ where
|
||||
#[project]
|
||||
fn poll(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Result<(), DispatchError>> {
|
||||
#[project]
|
||||
match self.as_mut().project() {
|
||||
|
@@ -21,8 +21,6 @@ use crate::Request;
|
||||
/// Test `Request` builder
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// # extern crate http;
|
||||
/// # extern crate actix_web;
|
||||
/// # use http::{header, StatusCode};
|
||||
/// # use actix_web::*;
|
||||
/// use actix_web::test::TestRequest;
|
||||
@@ -35,15 +33,13 @@ use crate::Request;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let resp = TestRequest::with_header("content-type", "text/plain")
|
||||
/// .run(&index)
|
||||
/// .unwrap();
|
||||
/// assert_eq!(resp.status(), StatusCode::OK);
|
||||
/// let resp = TestRequest::with_header("content-type", "text/plain")
|
||||
/// .run(&index)
|
||||
/// .unwrap();
|
||||
/// assert_eq!(resp.status(), StatusCode::OK);
|
||||
///
|
||||
/// let resp = TestRequest::default().run(&index).unwrap();
|
||||
/// assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||
/// }
|
||||
/// let resp = TestRequest::default().run(&index).unwrap();
|
||||
/// assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||
/// ```
|
||||
pub struct TestRequest(Option<Inner>);
|
||||
|
||||
|
@@ -12,10 +12,12 @@ pub enum Message {
|
||||
Text(String),
|
||||
/// Binary message
|
||||
Binary(Bytes),
|
||||
/// Continuation
|
||||
Continuation(Item),
|
||||
/// Ping message
|
||||
Ping(String),
|
||||
Ping(Bytes),
|
||||
/// Pong message
|
||||
Pong(String),
|
||||
Pong(Bytes),
|
||||
/// Close message with optional reason
|
||||
Close(Option<CloseReason>),
|
||||
/// No-op. Useful for actix-net services
|
||||
@@ -26,22 +28,41 @@ pub enum Message {
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Frame {
|
||||
/// Text frame, codec does not verify utf8 encoding
|
||||
Text(Option<BytesMut>),
|
||||
Text(Bytes),
|
||||
/// Binary frame
|
||||
Binary(Option<BytesMut>),
|
||||
Binary(Bytes),
|
||||
/// Continuation
|
||||
Continuation(Item),
|
||||
/// Ping message
|
||||
Ping(String),
|
||||
Ping(Bytes),
|
||||
/// Pong message
|
||||
Pong(String),
|
||||
Pong(Bytes),
|
||||
/// Close message with optional reason
|
||||
Close(Option<CloseReason>),
|
||||
}
|
||||
|
||||
/// `WebSocket` continuation item
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Item {
|
||||
FirstText(Bytes),
|
||||
FirstBinary(Bytes),
|
||||
Continue(Bytes),
|
||||
Last(Bytes),
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
/// WebSockets protocol codec
|
||||
pub struct Codec {
|
||||
flags: Flags,
|
||||
max_size: usize,
|
||||
server: bool,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
struct Flags: u8 {
|
||||
const SERVER = 0b0000_0001;
|
||||
const CONTINUATION = 0b0000_0010;
|
||||
const W_CONTINUATION = 0b0000_0100;
|
||||
}
|
||||
}
|
||||
|
||||
impl Codec {
|
||||
@@ -49,7 +70,7 @@ impl Codec {
|
||||
pub fn new() -> Codec {
|
||||
Codec {
|
||||
max_size: 65_536,
|
||||
server: true,
|
||||
flags: Flags::SERVER,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +86,7 @@ impl Codec {
|
||||
///
|
||||
/// By default decoder works in server mode.
|
||||
pub fn client_mode(mut self) -> Self {
|
||||
self.server = false;
|
||||
self.flags.remove(Flags::SERVER);
|
||||
self
|
||||
}
|
||||
}
|
||||
@@ -76,19 +97,94 @@ impl Encoder for Codec {
|
||||
|
||||
fn encode(&mut self, item: Message, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||
match item {
|
||||
Message::Text(txt) => {
|
||||
Parser::write_message(dst, txt, OpCode::Text, true, !self.server)
|
||||
Message::Text(txt) => Parser::write_message(
|
||||
dst,
|
||||
txt,
|
||||
OpCode::Text,
|
||||
true,
|
||||
!self.flags.contains(Flags::SERVER),
|
||||
),
|
||||
Message::Binary(bin) => Parser::write_message(
|
||||
dst,
|
||||
bin,
|
||||
OpCode::Binary,
|
||||
true,
|
||||
!self.flags.contains(Flags::SERVER),
|
||||
),
|
||||
Message::Ping(txt) => Parser::write_message(
|
||||
dst,
|
||||
txt,
|
||||
OpCode::Ping,
|
||||
true,
|
||||
!self.flags.contains(Flags::SERVER),
|
||||
),
|
||||
Message::Pong(txt) => Parser::write_message(
|
||||
dst,
|
||||
txt,
|
||||
OpCode::Pong,
|
||||
true,
|
||||
!self.flags.contains(Flags::SERVER),
|
||||
),
|
||||
Message::Close(reason) => {
|
||||
Parser::write_close(dst, reason, !self.flags.contains(Flags::SERVER))
|
||||
}
|
||||
Message::Binary(bin) => {
|
||||
Parser::write_message(dst, bin, OpCode::Binary, true, !self.server)
|
||||
}
|
||||
Message::Ping(txt) => {
|
||||
Parser::write_message(dst, txt, OpCode::Ping, true, !self.server)
|
||||
}
|
||||
Message::Pong(txt) => {
|
||||
Parser::write_message(dst, txt, OpCode::Pong, true, !self.server)
|
||||
}
|
||||
Message::Close(reason) => Parser::write_close(dst, reason, !self.server),
|
||||
Message::Continuation(cont) => match cont {
|
||||
Item::FirstText(data) => {
|
||||
if self.flags.contains(Flags::W_CONTINUATION) {
|
||||
return Err(ProtocolError::ContinuationStarted);
|
||||
} else {
|
||||
self.flags.insert(Flags::W_CONTINUATION);
|
||||
Parser::write_message(
|
||||
dst,
|
||||
&data[..],
|
||||
OpCode::Binary,
|
||||
false,
|
||||
!self.flags.contains(Flags::SERVER),
|
||||
)
|
||||
}
|
||||
}
|
||||
Item::FirstBinary(data) => {
|
||||
if self.flags.contains(Flags::W_CONTINUATION) {
|
||||
return Err(ProtocolError::ContinuationStarted);
|
||||
} else {
|
||||
self.flags.insert(Flags::W_CONTINUATION);
|
||||
Parser::write_message(
|
||||
dst,
|
||||
&data[..],
|
||||
OpCode::Text,
|
||||
false,
|
||||
!self.flags.contains(Flags::SERVER),
|
||||
)
|
||||
}
|
||||
}
|
||||
Item::Continue(data) => {
|
||||
if self.flags.contains(Flags::W_CONTINUATION) {
|
||||
Parser::write_message(
|
||||
dst,
|
||||
&data[..],
|
||||
OpCode::Continue,
|
||||
false,
|
||||
!self.flags.contains(Flags::SERVER),
|
||||
)
|
||||
} else {
|
||||
return Err(ProtocolError::ContinuationNotStarted);
|
||||
}
|
||||
}
|
||||
Item::Last(data) => {
|
||||
if self.flags.contains(Flags::W_CONTINUATION) {
|
||||
self.flags.remove(Flags::W_CONTINUATION);
|
||||
Parser::write_message(
|
||||
dst,
|
||||
&data[..],
|
||||
OpCode::Continue,
|
||||
true,
|
||||
!self.flags.contains(Flags::SERVER),
|
||||
)
|
||||
} else {
|
||||
return Err(ProtocolError::ContinuationNotStarted);
|
||||
}
|
||||
}
|
||||
},
|
||||
Message::Nop => (),
|
||||
}
|
||||
Ok(())
|
||||
@@ -100,15 +196,64 @@ impl Decoder for Codec {
|
||||
type Error = ProtocolError;
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
match Parser::parse(src, self.server, self.max_size) {
|
||||
match Parser::parse(src, self.flags.contains(Flags::SERVER), self.max_size) {
|
||||
Ok(Some((finished, opcode, payload))) => {
|
||||
// continuation is not supported
|
||||
if !finished {
|
||||
return Err(ProtocolError::NoContinuation);
|
||||
return match opcode {
|
||||
OpCode::Continue => {
|
||||
if self.flags.contains(Flags::CONTINUATION) {
|
||||
Ok(Some(Frame::Continuation(Item::Continue(
|
||||
payload
|
||||
.map(|pl| pl.freeze())
|
||||
.unwrap_or_else(Bytes::new),
|
||||
))))
|
||||
} else {
|
||||
Err(ProtocolError::ContinuationNotStarted)
|
||||
}
|
||||
}
|
||||
OpCode::Binary => {
|
||||
if !self.flags.contains(Flags::CONTINUATION) {
|
||||
self.flags.insert(Flags::CONTINUATION);
|
||||
Ok(Some(Frame::Continuation(Item::FirstBinary(
|
||||
payload
|
||||
.map(|pl| pl.freeze())
|
||||
.unwrap_or_else(Bytes::new),
|
||||
))))
|
||||
} else {
|
||||
Err(ProtocolError::ContinuationStarted)
|
||||
}
|
||||
}
|
||||
OpCode::Text => {
|
||||
if !self.flags.contains(Flags::CONTINUATION) {
|
||||
self.flags.insert(Flags::CONTINUATION);
|
||||
Ok(Some(Frame::Continuation(Item::FirstText(
|
||||
payload
|
||||
.map(|pl| pl.freeze())
|
||||
.unwrap_or_else(Bytes::new),
|
||||
))))
|
||||
} else {
|
||||
Err(ProtocolError::ContinuationStarted)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unfinished fragment {:?}", opcode);
|
||||
Err(ProtocolError::ContinuationFragment(opcode))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
match opcode {
|
||||
OpCode::Continue => Err(ProtocolError::NoContinuation),
|
||||
OpCode::Continue => {
|
||||
if self.flags.contains(Flags::CONTINUATION) {
|
||||
self.flags.remove(Flags::CONTINUATION);
|
||||
Ok(Some(Frame::Continuation(Item::Last(
|
||||
payload.map(|pl| pl.freeze()).unwrap_or_else(Bytes::new),
|
||||
))))
|
||||
} else {
|
||||
Err(ProtocolError::ContinuationNotStarted)
|
||||
}
|
||||
}
|
||||
OpCode::Bad => Err(ProtocolError::BadOpCode),
|
||||
OpCode::Close => {
|
||||
if let Some(ref pl) = payload {
|
||||
@@ -118,29 +263,18 @@ impl Decoder for Codec {
|
||||
Ok(Some(Frame::Close(None)))
|
||||
}
|
||||
}
|
||||
OpCode::Ping => {
|
||||
if let Some(ref pl) = payload {
|
||||
Ok(Some(Frame::Ping(String::from_utf8_lossy(pl).into())))
|
||||
} else {
|
||||
Ok(Some(Frame::Ping(String::new())))
|
||||
}
|
||||
}
|
||||
OpCode::Pong => {
|
||||
if let Some(ref pl) = payload {
|
||||
Ok(Some(Frame::Pong(String::from_utf8_lossy(pl).into())))
|
||||
} else {
|
||||
Ok(Some(Frame::Pong(String::new())))
|
||||
}
|
||||
}
|
||||
OpCode::Binary => Ok(Some(Frame::Binary(payload))),
|
||||
OpCode::Text => {
|
||||
Ok(Some(Frame::Text(payload)))
|
||||
//let tmp = Vec::from(payload.as_ref());
|
||||
//match String::from_utf8(tmp) {
|
||||
// Ok(s) => Ok(Some(Message::Text(s))),
|
||||
// Err(_) => Err(ProtocolError::BadEncoding),
|
||||
//}
|
||||
}
|
||||
OpCode::Ping => Ok(Some(Frame::Ping(
|
||||
payload.map(|pl| pl.freeze()).unwrap_or_else(Bytes::new),
|
||||
))),
|
||||
OpCode::Pong => Ok(Some(Frame::Pong(
|
||||
payload.map(|pl| pl.freeze()).unwrap_or_else(Bytes::new),
|
||||
))),
|
||||
OpCode::Binary => Ok(Some(Frame::Binary(
|
||||
payload.map(|pl| pl.freeze()).unwrap_or_else(Bytes::new),
|
||||
))),
|
||||
OpCode::Text => Ok(Some(Frame::Text(
|
||||
payload.map(|pl| pl.freeze()).unwrap_or_else(Bytes::new),
|
||||
))),
|
||||
}
|
||||
}
|
||||
Ok(None) => Ok(None),
|
||||
|
@@ -4,19 +4,19 @@ use std::task::{Context, Poll};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use actix_service::{IntoService, Service};
|
||||
use actix_utils::framed::{FramedTransport, FramedTransportError};
|
||||
use actix_utils::framed;
|
||||
|
||||
use super::{Codec, Frame, Message};
|
||||
|
||||
pub struct Transport<S, T>
|
||||
pub struct Dispatcher<S, T>
|
||||
where
|
||||
S: Service<Request = Frame, Response = Message> + 'static,
|
||||
T: AsyncRead + AsyncWrite,
|
||||
{
|
||||
inner: FramedTransport<S, T, Codec>,
|
||||
inner: framed::Dispatcher<S, T, Codec>,
|
||||
}
|
||||
|
||||
impl<S, T> Transport<S, T>
|
||||
impl<S, T> Dispatcher<S, T>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
S: Service<Request = Frame, Response = Message>,
|
||||
@@ -24,28 +24,28 @@ where
|
||||
S::Error: 'static,
|
||||
{
|
||||
pub fn new<F: IntoService<S>>(io: T, service: F) -> Self {
|
||||
Transport {
|
||||
inner: FramedTransport::new(Framed::new(io, Codec::new()), service),
|
||||
Dispatcher {
|
||||
inner: framed::Dispatcher::new(Framed::new(io, Codec::new()), service),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with<F: IntoService<S>>(framed: Framed<T, Codec>, service: F) -> Self {
|
||||
Transport {
|
||||
inner: FramedTransport::new(framed, service),
|
||||
Dispatcher {
|
||||
inner: framed::Dispatcher::new(framed, service),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T> Future for Transport<S, T>
|
||||
impl<S, T> Future for Dispatcher<S, T>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
S: Service<Request = Frame, Response = Message>,
|
||||
S::Future: 'static,
|
||||
S::Error: 'static,
|
||||
{
|
||||
type Output = Result<(), FramedTransportError<S::Error, Codec>>;
|
||||
type Output = Result<(), framed::DispatcherError<S::Error, Codec>>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Pin::new(&mut self.inner).poll(cx)
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use bytes::{BufMut, Bytes, BytesMut};
|
||||
use bytes::{Buf, BufMut, BytesMut};
|
||||
use log::debug;
|
||||
use rand;
|
||||
|
||||
@@ -108,7 +108,7 @@ impl Parser {
|
||||
}
|
||||
|
||||
// remove prefix
|
||||
src.split_to(idx);
|
||||
src.advance(idx);
|
||||
|
||||
// no need for body
|
||||
if length == 0 {
|
||||
@@ -154,14 +154,14 @@ impl Parser {
|
||||
}
|
||||
|
||||
/// Generate binary representation
|
||||
pub fn write_message<B: Into<Bytes>>(
|
||||
pub fn write_message<B: AsRef<[u8]>>(
|
||||
dst: &mut BytesMut,
|
||||
pl: B,
|
||||
op: OpCode,
|
||||
fin: bool,
|
||||
mask: bool,
|
||||
) {
|
||||
let payload = pl.into();
|
||||
let payload = pl.as_ref();
|
||||
let one: u8 = if fin {
|
||||
0x80 | Into::<u8>::into(op)
|
||||
} else {
|
||||
|
@@ -51,7 +51,7 @@ pub(crate) fn apply_mask(buf: &mut [u8], mask_u32: u32) {
|
||||
// inefficient, it could be done better. The compiler does not understand that
|
||||
// a `ShortSlice` must be smaller than a u64.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
fn xor_short(buf: ShortSlice, mask: u64) {
|
||||
fn xor_short(buf: ShortSlice<'_>, mask: u64) {
|
||||
// Unsafe: we know that a `ShortSlice` fits in a u64
|
||||
unsafe {
|
||||
let (ptr, len) = (buf.0.as_mut_ptr(), buf.0.len());
|
||||
@@ -77,7 +77,7 @@ unsafe fn cast_slice(buf: &mut [u8]) -> &mut [u64] {
|
||||
#[inline]
|
||||
// Splits a slice into three parts: an unaligned short head and tail, plus an aligned
|
||||
// u64 mid section.
|
||||
fn align_buf(buf: &mut [u8]) -> (ShortSlice, &mut [u64], ShortSlice) {
|
||||
fn align_buf(buf: &mut [u8]) -> (ShortSlice<'_>, &mut [u64], ShortSlice<'_>) {
|
||||
let start_ptr = buf.as_ptr() as usize;
|
||||
let end_ptr = start_ptr + buf.len();
|
||||
|
||||
|
@@ -13,15 +13,15 @@ use crate::message::RequestHead;
|
||||
use crate::response::{Response, ResponseBuilder};
|
||||
|
||||
mod codec;
|
||||
mod dispatcher;
|
||||
mod frame;
|
||||
mod mask;
|
||||
mod proto;
|
||||
mod transport;
|
||||
|
||||
pub use self::codec::{Codec, Frame, Message};
|
||||
pub use self::codec::{Codec, Frame, Item, Message};
|
||||
pub use self::dispatcher::Dispatcher;
|
||||
pub use self::frame::Parser;
|
||||
pub use self::proto::{hash_key, CloseCode, CloseReason, OpCode};
|
||||
pub use self::transport::Transport;
|
||||
|
||||
/// Websocket protocol errors
|
||||
#[derive(Debug, Display, From)]
|
||||
@@ -44,12 +44,15 @@ pub enum ProtocolError {
|
||||
/// A payload reached size limit.
|
||||
#[display(fmt = "A payload reached size limit.")]
|
||||
Overflow,
|
||||
/// Continuation is not supported
|
||||
#[display(fmt = "Continuation is not supported.")]
|
||||
NoContinuation,
|
||||
/// Bad utf-8 encoding
|
||||
#[display(fmt = "Bad utf-8 encoding.")]
|
||||
BadEncoding,
|
||||
/// Continuation is not started
|
||||
#[display(fmt = "Continuation is not started.")]
|
||||
ContinuationNotStarted,
|
||||
/// Received new continuation but it is already started
|
||||
#[display(fmt = "Received new continuation but it is already started")]
|
||||
ContinuationStarted,
|
||||
/// Unknown continuation fragment
|
||||
#[display(fmt = "Unknown continuation fragment.")]
|
||||
ContinuationFragment(OpCode),
|
||||
/// Io error
|
||||
#[display(fmt = "io error: {}", _0)]
|
||||
Io(io::Error),
|
||||
|
@@ -24,7 +24,7 @@ pub enum OpCode {
|
||||
}
|
||||
|
||||
impl fmt::Display for OpCode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
Continue => write!(f, "CONTINUE"),
|
||||
Text => write!(f, "TEXT"),
|
||||
@@ -95,7 +95,7 @@ pub enum CloseCode {
|
||||
Abnormal,
|
||||
/// Indicates that an endpoint is terminating the connection
|
||||
/// because it has received data within a message that was not
|
||||
/// consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
|
||||
/// consistent with the type of the message (e.g., non-UTF-8 \[RFC3629\]
|
||||
/// data within a text message).
|
||||
Invalid,
|
||||
/// Indicates that an endpoint is terminating the connection
|
||||
|
@@ -3,7 +3,7 @@ use bytes::Bytes;
|
||||
use futures::future::{self, ok};
|
||||
|
||||
use actix_http::{http, HttpService, Request, Response};
|
||||
use actix_http_test::TestServer;
|
||||
use actix_http_test::test_server;
|
||||
|
||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
@@ -29,7 +29,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_v2() {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.tcp()
|
||||
@@ -56,7 +56,7 @@ async fn test_h1_v2() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_connection_close() {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.tcp()
|
||||
@@ -69,7 +69,7 @@ async fn test_connection_close() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_with_query_parameter() {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
if req.uri().query().unwrap().contains("qp=") {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#![cfg(feature = "openssl")]
|
||||
use std::io;
|
||||
|
||||
use actix_http_test::TestServer;
|
||||
use actix_service::{service_fn, ServiceFactory};
|
||||
use actix_http_test::test_server;
|
||||
use actix_service::{fn_service, ServiceFactory};
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::{err, ok, ready};
|
||||
@@ -62,7 +62,7 @@ fn ssl_acceptor() -> SslAcceptor {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2() -> io::Result<()> {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, Error>(Response::Ok().finish()))
|
||||
.openssl(ssl_acceptor())
|
||||
@@ -76,7 +76,7 @@ async fn test_h2() -> io::Result<()> {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_1() -> io::Result<()> {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
@@ -95,7 +95,7 @@ async fn test_h2_1() -> io::Result<()> {
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_body() -> io::Result<()> {
|
||||
let data = "HELLOWORLD".to_owned().repeat(64 * 1024);
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|mut req: Request<_>| {
|
||||
async move {
|
||||
@@ -117,7 +117,7 @@ async fn test_h2_body() -> io::Result<()> {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_content_length() {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|req: Request| {
|
||||
let indx: usize = req.uri().path()[1..].parse().unwrap();
|
||||
@@ -168,7 +168,7 @@ async fn test_h2_headers() {
|
||||
let data = STR.repeat(10);
|
||||
let data2 = data.clone();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
let data = data.clone();
|
||||
HttpService::build().h2(move |_| {
|
||||
let mut builder = Response::Ok();
|
||||
@@ -228,7 +228,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_body2() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.openssl(ssl_acceptor())
|
||||
@@ -245,7 +245,7 @@ async fn test_h2_body2() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_head_empty() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.openssl(ssl_acceptor())
|
||||
@@ -268,7 +268,7 @@ async fn test_h2_head_empty() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_head_binary() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
ok::<_, ()>(Response::Ok().content_length(STR.len() as u64).body(STR))
|
||||
@@ -292,7 +292,7 @@ async fn test_h2_head_binary() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_head_binary2() {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.openssl(ssl_acceptor())
|
||||
@@ -310,7 +310,7 @@ async fn test_h2_head_binary2() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_body_length() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||
@@ -332,7 +332,7 @@ async fn test_h2_body_length() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_body_chunked_explicit() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
@@ -359,9 +359,9 @@ async fn test_h2_body_chunked_explicit() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_response_http_error_handling() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(service_fn(|_| {
|
||||
.h2(fn_service(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
@@ -383,7 +383,7 @@ async fn test_h2_response_http_error_handling() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_service_error() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| err::<Response, Error>(ErrorBadRequest("error")))
|
||||
.openssl(ssl_acceptor())
|
||||
@@ -400,7 +400,7 @@ async fn test_h2_service_error() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_on_connect() {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.on_connect(|_| 10usize)
|
||||
.h2(|req: Request| {
|
||||
|
@@ -3,8 +3,8 @@ use actix_http::error::PayloadError;
|
||||
use actix_http::http::header::{self, HeaderName, HeaderValue};
|
||||
use actix_http::http::{Method, StatusCode, Version};
|
||||
use actix_http::{body, error, Error, HttpService, Request, Response};
|
||||
use actix_http_test::TestServer;
|
||||
use actix_service::{factory_fn_cfg, service_fn2};
|
||||
use actix_http_test::test_server;
|
||||
use actix_service::{fn_factory_with_config, fn_service};
|
||||
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::future::{self, err, ok};
|
||||
@@ -41,7 +41,7 @@ fn ssl_acceptor() -> RustlsServerConfig {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1() -> io::Result<()> {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h1(|_| future::ok::<_, Error>(Response::Ok().finish()))
|
||||
.rustls(ssl_acceptor())
|
||||
@@ -54,7 +54,7 @@ async fn test_h1() -> io::Result<()> {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2() -> io::Result<()> {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| future::ok::<_, Error>(Response::Ok().finish()))
|
||||
.rustls(ssl_acceptor())
|
||||
@@ -67,7 +67,7 @@ async fn test_h2() -> io::Result<()> {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_1() -> io::Result<()> {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h1(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
@@ -84,7 +84,7 @@ async fn test_h1_1() -> io::Result<()> {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_1() -> io::Result<()> {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|req: Request| {
|
||||
assert!(req.peer_addr().is_some());
|
||||
@@ -102,7 +102,7 @@ async fn test_h2_1() -> io::Result<()> {
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_body1() -> io::Result<()> {
|
||||
let data = "HELLOWORLD".to_owned().repeat(64 * 1024);
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|mut req: Request<_>| {
|
||||
async move {
|
||||
@@ -123,7 +123,7 @@ async fn test_h2_body1() -> io::Result<()> {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_content_length() {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|req: Request| {
|
||||
let indx: usize = req.uri().path()[1..].parse().unwrap();
|
||||
@@ -172,7 +172,7 @@ async fn test_h2_headers() {
|
||||
let data = STR.repeat(10);
|
||||
let data2 = data.clone();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
let data = data.clone();
|
||||
HttpService::build().h2(move |_| {
|
||||
let mut config = Response::Ok();
|
||||
@@ -231,7 +231,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_body2() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.rustls(ssl_acceptor())
|
||||
@@ -247,7 +247,7 @@ async fn test_h2_body2() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_head_empty() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.rustls(ssl_acceptor())
|
||||
@@ -272,7 +272,7 @@ async fn test_h2_head_empty() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_head_binary() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
ok::<_, ()>(Response::Ok().content_length(STR.len() as u64).body(STR))
|
||||
@@ -298,7 +298,7 @@ async fn test_h2_head_binary() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_head_binary2() {
|
||||
let srv = TestServer::start(move || {
|
||||
let srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.rustls(ssl_acceptor())
|
||||
@@ -318,7 +318,7 @@ async fn test_h2_head_binary2() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_body_length() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||
@@ -339,7 +339,7 @@ async fn test_h2_body_length() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_body_chunked_explicit() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| {
|
||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
@@ -365,10 +365,10 @@ async fn test_h2_body_chunked_explicit() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_response_http_error_handling() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(factory_fn_cfg(|_: ()| {
|
||||
ok::<_, ()>(service_fn2(|_| {
|
||||
.h2(fn_factory_with_config(|_: ()| {
|
||||
ok::<_, ()>(fn_service(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
@@ -390,7 +390,7 @@ async fn test_h2_response_http_error_handling() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h2_service_error() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h2(|_| err::<Response, Error>(error::ErrorBadRequest("error")))
|
||||
.rustls(ssl_acceptor())
|
||||
@@ -406,7 +406,7 @@ async fn test_h2_service_error() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_service_error() {
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
HttpService::build()
|
||||
.h1(|_| err::<Response, Error>(error::ErrorBadRequest("error")))
|
||||
.rustls(ssl_acceptor())
|
||||
|
@@ -2,9 +2,9 @@ use std::io::{Read, Write};
|
||||
use std::time::Duration;
|
||||
use std::{net, thread};
|
||||
|
||||
use actix_http_test::TestServer;
|
||||
use actix_http_test::test_server;
|
||||
use actix_rt::time::delay_for;
|
||||
use actix_service::service_fn;
|
||||
use actix_service::fn_service;
|
||||
use bytes::Bytes;
|
||||
use futures::future::{self, err, ok, ready, FutureExt};
|
||||
use futures::stream::{once, StreamExt};
|
||||
@@ -17,7 +17,7 @@ use actix_http::{
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.keep_alive(KeepAlive::Disabled)
|
||||
.client_timeout(1000)
|
||||
@@ -35,7 +35,7 @@ async fn test_h1() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_2() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.keep_alive(KeepAlive::Disabled)
|
||||
.client_timeout(1000)
|
||||
@@ -54,9 +54,9 @@ async fn test_h1_2() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_expect_continue() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.expect(service_fn(|req: Request| {
|
||||
.expect(fn_service(|req: Request| {
|
||||
if req.head().uri.query() == Some("yes=") {
|
||||
ok(req)
|
||||
} else {
|
||||
@@ -82,9 +82,9 @@ async fn test_expect_continue() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_expect_continue_h1() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.expect(service_fn(|req: Request| {
|
||||
.expect(fn_service(|req: Request| {
|
||||
delay_for(Duration::from_millis(20)).then(move |_| {
|
||||
if req.head().uri.query() == Some("yes=") {
|
||||
ok(req)
|
||||
@@ -93,7 +93,7 @@ async fn test_expect_continue_h1() {
|
||||
}
|
||||
})
|
||||
}))
|
||||
.h1(service_fn(|_| future::ok::<_, ()>(Response::Ok().finish())))
|
||||
.h1(fn_service(|_| future::ok::<_, ()>(Response::Ok().finish())))
|
||||
.tcp()
|
||||
});
|
||||
|
||||
@@ -115,9 +115,9 @@ async fn test_chunked_payload() {
|
||||
let chunk_sizes = vec![32768, 32, 32768];
|
||||
let total_size: usize = chunk_sizes.iter().sum();
|
||||
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(service_fn(|mut request: Request| {
|
||||
.h1(fn_service(|mut request: Request| {
|
||||
request
|
||||
.take_payload()
|
||||
.map(|res| match res {
|
||||
@@ -167,7 +167,7 @@ async fn test_chunked_payload() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_slow_request() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.client_timeout(100)
|
||||
.finish(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
||||
@@ -183,7 +183,7 @@ async fn test_slow_request() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_http1_malformed_request() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
||||
.tcp()
|
||||
@@ -198,7 +198,7 @@ async fn test_http1_malformed_request() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_http1_keepalive() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
||||
.tcp()
|
||||
@@ -218,7 +218,7 @@ async fn test_http1_keepalive() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_http1_keepalive_timeout() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.keep_alive(1)
|
||||
.h1(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
||||
@@ -239,7 +239,7 @@ async fn test_http1_keepalive_timeout() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_http1_keepalive_close() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
||||
.tcp()
|
||||
@@ -259,7 +259,7 @@ async fn test_http1_keepalive_close() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_http10_keepalive_default_close() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
||||
.tcp()
|
||||
@@ -278,7 +278,7 @@ async fn test_http10_keepalive_default_close() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_http10_keepalive() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
||||
.tcp()
|
||||
@@ -304,7 +304,7 @@ async fn test_http10_keepalive() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_http1_keepalive_disabled() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.keep_alive(KeepAlive::Disabled)
|
||||
.h1(|_| future::ok::<_, ()>(Response::Ok().finish()))
|
||||
@@ -329,7 +329,7 @@ async fn test_content_length() {
|
||||
StatusCode,
|
||||
};
|
||||
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|req: Request| {
|
||||
let indx: usize = req.uri().path()[1..].parse().unwrap();
|
||||
@@ -373,7 +373,7 @@ async fn test_h1_headers() {
|
||||
let data = STR.repeat(10);
|
||||
let data2 = data.clone();
|
||||
|
||||
let mut srv = TestServer::start(move || {
|
||||
let mut srv = test_server(move || {
|
||||
let data = data.clone();
|
||||
HttpService::build().h1(move |_| {
|
||||
let mut builder = Response::Ok();
|
||||
@@ -431,7 +431,7 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_body() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.tcp()
|
||||
@@ -447,7 +447,7 @@ async fn test_h1_body() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_head_empty() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.tcp()
|
||||
@@ -471,7 +471,7 @@ async fn test_h1_head_empty() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_head_binary() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| {
|
||||
ok::<_, ()>(Response::Ok().content_length(STR.len() as u64).body(STR))
|
||||
@@ -497,7 +497,7 @@ async fn test_h1_head_binary() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_head_binary2() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| ok::<_, ()>(Response::Ok().body(STR)))
|
||||
.tcp()
|
||||
@@ -517,7 +517,7 @@ async fn test_h1_head_binary2() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_body_length() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| {
|
||||
let body = once(ok(Bytes::from_static(STR.as_ref())));
|
||||
@@ -538,7 +538,7 @@ async fn test_h1_body_length() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_body_chunked_explicit() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| {
|
||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
@@ -572,7 +572,7 @@ async fn test_h1_body_chunked_explicit() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_body_chunked_implicit() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| {
|
||||
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
|
||||
@@ -600,9 +600,9 @@ async fn test_h1_body_chunked_implicit() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_response_http_error_handling() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(service_fn(|_| {
|
||||
.h1(fn_service(|_| {
|
||||
let broken_header = Bytes::from_static(b"\0\0\0");
|
||||
ok::<_, ()>(
|
||||
Response::Ok()
|
||||
@@ -623,7 +623,7 @@ async fn test_h1_response_http_error_handling() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_service_error() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
let mut srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.h1(|_| future::err::<Response, Error>(error::ErrorBadRequest("error")))
|
||||
.tcp()
|
||||
@@ -639,7 +639,7 @@ async fn test_h1_service_error() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_h1_on_connect() {
|
||||
let srv = TestServer::start(|| {
|
||||
let srv = test_server(|| {
|
||||
HttpService::build()
|
||||
.on_connect(|_| 10usize)
|
||||
.h1(|req: Request| {
|
||||
|
@@ -1,33 +1,80 @@
|
||||
use std::cell::Cell;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use actix_http::{body, h1, ws, Error, HttpService, Request, Response};
|
||||
use actix_http_test::TestServer;
|
||||
use actix_utils::framed::FramedTransport;
|
||||
use bytes::BytesMut;
|
||||
use actix_http_test::test_server;
|
||||
use actix_service::{fn_factory, Service};
|
||||
use actix_utils::framed::Dispatcher;
|
||||
use bytes::Bytes;
|
||||
use futures::future;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use futures::task::{Context, Poll};
|
||||
use futures::{Future, SinkExt, StreamExt};
|
||||
|
||||
async fn ws_service<T: AsyncRead + AsyncWrite + Unpin>(
|
||||
(req, mut framed): (Request, Framed<T, h1::Codec>),
|
||||
) -> Result<(), Error> {
|
||||
let res = ws::handshake(req.head()).unwrap().message_body(());
|
||||
struct WsService<T>(Arc<Mutex<(PhantomData<T>, Cell<bool>)>>);
|
||||
|
||||
framed
|
||||
.send((res, body::BodySize::None).into())
|
||||
.await
|
||||
.unwrap();
|
||||
impl<T> WsService<T> {
|
||||
fn new() -> Self {
|
||||
WsService(Arc::new(Mutex::new((PhantomData, Cell::new(false)))))
|
||||
}
|
||||
|
||||
FramedTransport::new(framed.into_framed(ws::Codec::new()), service)
|
||||
.await
|
||||
.map_err(|_| panic!())
|
||||
fn set_polled(&mut self) {
|
||||
*self.0.lock().unwrap().1.get_mut() = true;
|
||||
}
|
||||
|
||||
fn was_polled(&self) -> bool {
|
||||
self.0.lock().unwrap().1.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for WsService<T> {
|
||||
fn clone(&self) -> Self {
|
||||
WsService(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Service for WsService<T>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin + 'static,
|
||||
{
|
||||
type Request = (Request, Framed<T, h1::Codec>);
|
||||
type Response = ();
|
||||
type Error = Error;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<(), Error>>>>;
|
||||
|
||||
fn poll_ready(&mut self, _ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.set_polled();
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, (req, mut framed): Self::Request) -> Self::Future {
|
||||
let fut = async move {
|
||||
let res = ws::handshake(req.head()).unwrap().message_body(());
|
||||
|
||||
framed
|
||||
.send((res, body::BodySize::None).into())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Dispatcher::new(framed.into_framed(ws::Codec::new()), service)
|
||||
.await
|
||||
.map_err(|_| panic!())
|
||||
};
|
||||
|
||||
Box::pin(fut)
|
||||
}
|
||||
}
|
||||
|
||||
async fn service(msg: ws::Frame) -> Result<ws::Message, Error> {
|
||||
let msg = match msg {
|
||||
ws::Frame::Ping(msg) => ws::Message::Pong(msg),
|
||||
ws::Frame::Text(text) => {
|
||||
ws::Message::Text(String::from_utf8_lossy(&text.unwrap()).to_string())
|
||||
ws::Message::Text(String::from_utf8_lossy(&text).to_string())
|
||||
}
|
||||
ws::Frame::Binary(bin) => ws::Message::Binary(bin.unwrap().freeze()),
|
||||
ws::Frame::Binary(bin) => ws::Message::Binary(bin),
|
||||
ws::Frame::Continuation(item) => ws::Message::Continuation(item),
|
||||
ws::Frame::Close(reason) => ws::Message::Close(reason),
|
||||
_ => panic!(),
|
||||
};
|
||||
@@ -36,11 +83,16 @@ async fn service(msg: ws::Frame) -> Result<ws::Message, Error> {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_simple() {
|
||||
let mut srv = TestServer::start(|| {
|
||||
HttpService::build()
|
||||
.upgrade(actix_service::service_fn(ws_service))
|
||||
.finish(|_| future::ok::<_, ()>(Response::NotFound()))
|
||||
.tcp()
|
||||
let ws_service = WsService::new();
|
||||
let mut srv = test_server({
|
||||
let ws_service = ws_service.clone();
|
||||
move || {
|
||||
let ws_service = ws_service.clone();
|
||||
HttpService::build()
|
||||
.upgrade(fn_factory(move || future::ok::<_, ()>(ws_service.clone())))
|
||||
.finish(|_| future::ok::<_, ()>(Response::NotFound()))
|
||||
.tcp()
|
||||
}
|
||||
});
|
||||
|
||||
// client service
|
||||
@@ -52,7 +104,7 @@ async fn test_simple() {
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Text(Some(BytesMut::from("text")))
|
||||
ws::Frame::Text(Bytes::from_static(b"text"))
|
||||
);
|
||||
|
||||
framed
|
||||
@@ -62,7 +114,7 @@ async fn test_simple() {
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Binary(Some(BytesMut::from(&b"text"[..]).into()))
|
||||
ws::Frame::Binary(Bytes::from_static(&b"text"[..]))
|
||||
);
|
||||
|
||||
framed.send(ws::Message::Ping("text".into())).await.unwrap();
|
||||
@@ -72,6 +124,61 @@ async fn test_simple() {
|
||||
ws::Frame::Pong("text".to_string().into())
|
||||
);
|
||||
|
||||
framed
|
||||
.send(ws::Message::Continuation(ws::Item::FirstText(
|
||||
"text".into(),
|
||||
)))
|
||||
.await
|
||||
.unwrap();
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Continuation(ws::Item::FirstText(Bytes::from_static(b"text")))
|
||||
);
|
||||
|
||||
assert!(framed
|
||||
.send(ws::Message::Continuation(ws::Item::FirstText(
|
||||
"text".into()
|
||||
)))
|
||||
.await
|
||||
.is_err());
|
||||
assert!(framed
|
||||
.send(ws::Message::Continuation(ws::Item::FirstBinary(
|
||||
"text".into()
|
||||
)))
|
||||
.await
|
||||
.is_err());
|
||||
|
||||
framed
|
||||
.send(ws::Message::Continuation(ws::Item::Continue("text".into())))
|
||||
.await
|
||||
.unwrap();
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Continuation(ws::Item::Continue(Bytes::from_static(b"text")))
|
||||
);
|
||||
|
||||
framed
|
||||
.send(ws::Message::Continuation(ws::Item::Last("text".into())))
|
||||
.await
|
||||
.unwrap();
|
||||
let (item, mut framed) = framed.into_future().await;
|
||||
assert_eq!(
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Continuation(ws::Item::Last(Bytes::from_static(b"text")))
|
||||
);
|
||||
|
||||
assert!(framed
|
||||
.send(ws::Message::Continuation(ws::Item::Continue("text".into())))
|
||||
.await
|
||||
.is_err());
|
||||
|
||||
assert!(framed
|
||||
.send(ws::Message::Continuation(ws::Item::Last("text".into())))
|
||||
.await
|
||||
.is_err());
|
||||
|
||||
framed
|
||||
.send(ws::Message::Close(Some(ws::CloseCode::Normal.into())))
|
||||
.await
|
||||
@@ -82,4 +189,6 @@ async fn test_simple() {
|
||||
item.unwrap().unwrap(),
|
||||
ws::Frame::Close(Some(ws::CloseCode::Normal.into()))
|
||||
);
|
||||
|
||||
assert!(ws_service.was_polled());
|
||||
}
|
||||
|
@@ -1,5 +1,9 @@
|
||||
# Changes
|
||||
|
||||
## [0.2.0] - 2019-12-20
|
||||
|
||||
* Use actix-web 2.0
|
||||
|
||||
## [0.1.0] - 2019-06-xx
|
||||
|
||||
* Move identity middleware to separate crate
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-identity"
|
||||
version = "0.2.0-alpha.3"
|
||||
version = "0.2.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Identity service for actix web framework."
|
||||
readme = "README.md"
|
||||
@@ -17,14 +17,14 @@ name = "actix_identity"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-web = { version = "2.0.0-alpha.3", default-features = false, features = ["secure-cookies"] }
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-web = { version = "2.0.0-rc", default-features = false, features = ["secure-cookies"] }
|
||||
actix-service = "1.0.0"
|
||||
futures = "0.3.1"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
time = "0.1.42"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-http = "1.0.0-alpha.3"
|
||||
bytes = "0.5.2"
|
||||
actix-rt = "1.0.0"
|
||||
actix-http = "1.0.1"
|
||||
bytes = "0.5.3"
|
@@ -1,5 +1,13 @@
|
||||
# Changes
|
||||
|
||||
## [0.2.0] - 2019-12-20
|
||||
|
||||
* Release
|
||||
|
||||
## [0.2.0-alpha.4] - 2019-12-xx
|
||||
|
||||
* Multipart handling now handles Pending during read of boundary #1205
|
||||
|
||||
## [0.2.0-alpha.2] - 2019-12-03
|
||||
|
||||
* Migrate to `std::future`
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-multipart"
|
||||
version = "0.2.0-alpha.3"
|
||||
version = "0.2.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Multipart support for actix web framework."
|
||||
readme = "README.md"
|
||||
@@ -9,8 +9,6 @@ homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-web.git"
|
||||
documentation = "https://docs.rs/actix-multipart/"
|
||||
license = "MIT/Apache-2.0"
|
||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||
workspace = ".."
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
@@ -18,10 +16,10 @@ name = "actix_multipart"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-web = { version = "2.0.0-alpha.3", default-features = false }
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-utils = "1.0.0-alpha.3"
|
||||
bytes = "0.5.2"
|
||||
actix-web = { version = "2.0.0-rc", default-features = false }
|
||||
actix-service = "1.0.0"
|
||||
actix-utils = "1.0.3"
|
||||
bytes = "0.5.3"
|
||||
derive_more = "0.99.2"
|
||||
httparse = "1.3"
|
||||
futures = "0.3.1"
|
||||
@@ -31,5 +29,5 @@ time = "0.1"
|
||||
twoway = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-http = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0"
|
||||
actix-http = "1.0.0"
|
@@ -610,7 +610,7 @@ impl InnerField {
|
||||
}
|
||||
|
||||
match payload.readline() {
|
||||
Ok(None) => Poll::Ready(None),
|
||||
Ok(None) => Poll::Pending,
|
||||
Ok(Some(line)) => {
|
||||
if line.as_ref() != b"\r\n" {
|
||||
log::warn!("multipart field did not read all the data or it is malformed");
|
||||
@@ -867,6 +867,45 @@ mod tests {
|
||||
|
||||
(tx, rx.map(|res| res.map_err(|_| panic!())))
|
||||
}
|
||||
// Stream that returns from a Bytes, one char at a time and Pending every other poll()
|
||||
struct SlowStream {
|
||||
bytes: Bytes,
|
||||
pos: usize,
|
||||
ready: bool,
|
||||
}
|
||||
|
||||
impl SlowStream {
|
||||
fn new(bytes: Bytes) -> SlowStream {
|
||||
return SlowStream {
|
||||
bytes: bytes,
|
||||
pos: 0,
|
||||
ready: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for SlowStream {
|
||||
type Item = Result<Bytes, PayloadError>;
|
||||
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
let this = self.get_mut();
|
||||
if !this.ready {
|
||||
this.ready = true;
|
||||
cx.waker().wake_by_ref();
|
||||
return Poll::Pending;
|
||||
}
|
||||
if this.pos == this.bytes.len() {
|
||||
return Poll::Ready(None);
|
||||
}
|
||||
let res = Poll::Ready(Some(Ok(this.bytes.slice(this.pos..(this.pos + 1)))));
|
||||
this.pos += 1;
|
||||
this.ready = false;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
fn create_simple_request_with_header() -> (Bytes, HeaderMap) {
|
||||
let bytes = Bytes::from(
|
||||
@@ -969,12 +1008,22 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
// Loops, collecting all bytes until end-of-field
|
||||
async fn get_whole_field(field: &mut Field) -> BytesMut {
|
||||
let mut b = BytesMut::new();
|
||||
loop {
|
||||
match field.next().await {
|
||||
Some(Ok(chunk)) => b.extend_from_slice(&chunk),
|
||||
None => return b,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_stream() {
|
||||
let (sender, payload) = create_stream();
|
||||
let (bytes, headers) = create_simple_request_with_header();
|
||||
|
||||
sender.send(Ok(bytes)).unwrap();
|
||||
let payload = SlowStream::new(bytes);
|
||||
|
||||
let mut multipart = Multipart::new(&headers, payload);
|
||||
match multipart.next().await.unwrap() {
|
||||
@@ -986,14 +1035,7 @@ mod tests {
|
||||
assert_eq!(field.content_type().type_(), mime::TEXT);
|
||||
assert_eq!(field.content_type().subtype(), mime::PLAIN);
|
||||
|
||||
match field.next().await.unwrap() {
|
||||
Ok(chunk) => assert_eq!(chunk, "test"),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
match field.next().await {
|
||||
None => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
assert_eq!(get_whole_field(&mut field).await, "test");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@@ -1003,14 +1045,7 @@ mod tests {
|
||||
assert_eq!(field.content_type().type_(), mime::TEXT);
|
||||
assert_eq!(field.content_type().subtype(), mime::PLAIN);
|
||||
|
||||
match field.next().await {
|
||||
Some(Ok(chunk)) => assert_eq!(chunk, "data"),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
match field.next().await {
|
||||
None => (),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
assert_eq!(get_whole_field(&mut field).await, "data");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@@ -1,5 +1,13 @@
|
||||
# Changes
|
||||
|
||||
## [0.3.0] - 2019-12-20
|
||||
|
||||
* Release
|
||||
|
||||
## [0.3.0-alpha.4] - 2019-12-xx
|
||||
|
||||
* Allow access to sessions also from not mutable references to the request
|
||||
|
||||
## [0.3.0-alpha.3] - 2019-12-xx
|
||||
|
||||
* Add access to the session from RequestHead for use of session from guard methods
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-session"
|
||||
version = "0.3.0-alpha.3"
|
||||
version = "0.3.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Session for actix web framework."
|
||||
readme = "README.md"
|
||||
@@ -9,8 +9,6 @@ homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-web.git"
|
||||
documentation = "https://docs.rs/actix-session/"
|
||||
license = "MIT/Apache-2.0"
|
||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||
workspace = ".."
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
@@ -24,9 +22,9 @@ default = ["cookie-session"]
|
||||
cookie-session = ["actix-web/secure-cookies"]
|
||||
|
||||
[dependencies]
|
||||
actix-web = "2.0.0-alpha.3"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
bytes = "0.5.2"
|
||||
actix-web = "2.0.0-rc"
|
||||
actix-service = "1.0.0"
|
||||
bytes = "0.5.3"
|
||||
derive_more = "0.99.2"
|
||||
futures = "0.3.1"
|
||||
serde = "1.0"
|
||||
@@ -34,4 +32,4 @@ serde_json = "1.0"
|
||||
time = "0.1.42"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0"
|
||||
|
@@ -12,7 +12,7 @@
|
||||
//! [*Session*](struct.Session.html) extractor must be used. Session
|
||||
//! extractor allows us to get or set session data.
|
||||
//!
|
||||
//! ```rust
|
||||
//! ```rust,no_run
|
||||
//! use actix_web::{web, App, HttpServer, HttpResponse, Error};
|
||||
//! use actix_session::{Session, CookieSession};
|
||||
//!
|
||||
@@ -28,8 +28,8 @@
|
||||
//! Ok("Welcome!")
|
||||
//! }
|
||||
//!
|
||||
//! fn main() -> std::io::Result<()> {
|
||||
//! # std::thread::spawn(||
|
||||
//! #[actix_rt::main]
|
||||
//! async fn main() -> std::io::Result<()> {
|
||||
//! HttpServer::new(
|
||||
//! || App::new().wrap(
|
||||
//! CookieSession::signed(&[0; 32]) // <- create cookie based session middleware
|
||||
@@ -37,9 +37,8 @@
|
||||
//! )
|
||||
//! .service(web::resource("/").to(|| HttpResponse::Ok())))
|
||||
//! .bind("127.0.0.1:59880")?
|
||||
//! .run()
|
||||
//! # );
|
||||
//! # Ok(())
|
||||
//! .start()
|
||||
//! .await
|
||||
//! }
|
||||
//! ```
|
||||
use std::cell::RefCell;
|
||||
@@ -86,23 +85,23 @@ pub struct Session(Rc<RefCell<SessionInner>>);
|
||||
|
||||
/// Helper trait that allows to get session
|
||||
pub trait UserSession {
|
||||
fn get_session(&mut self) -> Session;
|
||||
fn get_session(&self) -> Session;
|
||||
}
|
||||
|
||||
impl UserSession for HttpRequest {
|
||||
fn get_session(&mut self) -> Session {
|
||||
fn get_session(&self) -> Session {
|
||||
Session::get_session(&mut *self.extensions_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl UserSession for ServiceRequest {
|
||||
fn get_session(&mut self) -> Session {
|
||||
fn get_session(&self) -> Session {
|
||||
Session::get_session(&mut *self.extensions_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl UserSession for RequestHead {
|
||||
fn get_session(&mut self) -> Session {
|
||||
fn get_session(&self) -> Session {
|
||||
Session::get_session(&mut *self.extensions_mut())
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,17 @@
|
||||
# Changes
|
||||
|
||||
## [2.0.0] - 2019-12-20
|
||||
|
||||
* Release
|
||||
|
||||
## [2.0.0-alpha.1] - 2019-12-15
|
||||
|
||||
* Migrate to actix-web 2.0.0
|
||||
|
||||
## [1.0.4] - 2019-12-07
|
||||
|
||||
* Allow comma-separated websocket subprotocols without spaces (#1172)
|
||||
|
||||
## [1.0.3] - 2019-11-14
|
||||
|
||||
* Update actix-web and actix-http dependencies
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-web-actors"
|
||||
version = "1.0.3"
|
||||
version = "2.0.0"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix actors support for actix web framework."
|
||||
readme = "README.md"
|
||||
@@ -9,8 +9,6 @@ homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-web.git"
|
||||
documentation = "https://docs.rs/actix-web-actors/"
|
||||
license = "MIT/Apache-2.0"
|
||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||
workspace = ".."
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
@@ -18,13 +16,14 @@ name = "actix_web_actors"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.8.3"
|
||||
actix-web = "1.0.9"
|
||||
actix-http = "0.2.11"
|
||||
actix-codec = "0.1.2"
|
||||
bytes = "0.4"
|
||||
futures = "0.1.25"
|
||||
actix = "0.9.0"
|
||||
actix-web = "2.0.0-rc"
|
||||
actix-http = "1.0.1"
|
||||
actix-codec = "0.2.0"
|
||||
bytes = "0.5.2"
|
||||
futures = "0.3.1"
|
||||
pin-project = "0.4.6"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0"
|
||||
env_logger = "0.6"
|
||||
actix-http-test = { version = "0.2.4", features=["ssl"] }
|
||||
|
@@ -1,4 +1,6 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix::dev::{
|
||||
AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, ToEnvelope,
|
||||
@@ -7,10 +9,10 @@ use actix::fut::ActorFuture;
|
||||
use actix::{
|
||||
Actor, ActorContext, ActorState, Addr, AsyncContext, Handler, Message, SpawnHandle,
|
||||
};
|
||||
use actix_web::error::{Error, ErrorInternalServerError};
|
||||
use actix_web::error::Error;
|
||||
use bytes::Bytes;
|
||||
use futures::sync::oneshot::Sender;
|
||||
use futures::{Async, Future, Poll, Stream};
|
||||
use futures::channel::oneshot::Sender;
|
||||
use futures::{Future, Stream};
|
||||
|
||||
/// Execution context for http actors
|
||||
pub struct HttpContext<A>
|
||||
@@ -43,7 +45,7 @@ where
|
||||
#[inline]
|
||||
fn spawn<F>(&mut self, fut: F) -> SpawnHandle
|
||||
where
|
||||
F: ActorFuture<Item = (), Error = (), Actor = A> + 'static,
|
||||
F: ActorFuture<Output = (), Actor = A> + 'static,
|
||||
{
|
||||
self.inner.spawn(fut)
|
||||
}
|
||||
@@ -51,7 +53,7 @@ where
|
||||
#[inline]
|
||||
fn wait<F>(&mut self, fut: F)
|
||||
where
|
||||
F: ActorFuture<Item = (), Error = (), Actor = A> + 'static,
|
||||
F: ActorFuture<Output = (), Actor = A> + 'static,
|
||||
{
|
||||
self.inner.wait(fut)
|
||||
}
|
||||
@@ -81,7 +83,7 @@ where
|
||||
{
|
||||
#[inline]
|
||||
/// Create a new HTTP Context from a request and an actor
|
||||
pub fn create(actor: A) -> impl Stream<Item = Bytes, Error = Error> {
|
||||
pub fn create(actor: A) -> impl Stream<Item = Result<Bytes, Error>> {
|
||||
let mb = Mailbox::default();
|
||||
let ctx = HttpContext {
|
||||
inner: ContextParts::new(mb.sender_producer()),
|
||||
@@ -91,7 +93,7 @@ where
|
||||
}
|
||||
|
||||
/// Create a new HTTP Context
|
||||
pub fn with_factory<F>(f: F) -> impl Stream<Item = Bytes, Error = Error>
|
||||
pub fn with_factory<F>(f: F) -> impl Stream<Item = Result<Bytes, Error>>
|
||||
where
|
||||
F: FnOnce(&mut Self) -> A + 'static,
|
||||
{
|
||||
@@ -160,24 +162,23 @@ impl<A> Stream for HttpContextFut<A>
|
||||
where
|
||||
A: Actor<Context = HttpContext<A>>,
|
||||
{
|
||||
type Item = Bytes;
|
||||
type Error = Error;
|
||||
type Item = Result<Bytes, Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<Bytes>, Error> {
|
||||
fn poll_next(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
if self.fut.alive() {
|
||||
match self.fut.poll() {
|
||||
Ok(Async::NotReady) | Ok(Async::Ready(())) => (),
|
||||
Err(_) => return Err(ErrorInternalServerError("error")),
|
||||
}
|
||||
let _ = Pin::new(&mut self.fut).poll(cx);
|
||||
}
|
||||
|
||||
// frames
|
||||
if let Some(data) = self.fut.ctx().stream.pop_front() {
|
||||
Ok(Async::Ready(data))
|
||||
Poll::Ready(data.map(|b| Ok(b)))
|
||||
} else if self.fut.alive() {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
} else {
|
||||
Ok(Async::Ready(None))
|
||||
Poll::Ready(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,9 +200,9 @@ mod tests {
|
||||
|
||||
use actix::Actor;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::test::{block_on, call_service, init_service, TestRequest};
|
||||
use actix_web::test::{call_service, init_service, read_body, TestRequest};
|
||||
use actix_web::{web, App, HttpResponse};
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use bytes::Bytes;
|
||||
|
||||
use super::*;
|
||||
|
||||
@@ -223,31 +224,25 @@ mod tests {
|
||||
if self.count > 3 {
|
||||
ctx.write_eof()
|
||||
} else {
|
||||
ctx.write(Bytes::from(format!("LINE-{}", self.count).as_bytes()));
|
||||
ctx.write(Bytes::from(format!("LINE-{}", self.count)));
|
||||
ctx.run_later(Duration::from_millis(100), |slf, ctx| slf.write(ctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_resource() {
|
||||
#[actix_rt::test]
|
||||
async fn test_default_resource() {
|
||||
let mut srv =
|
||||
init_service(App::new().service(web::resource("/test").to(|| {
|
||||
HttpResponse::Ok().streaming(HttpContext::create(MyActor { count: 0 }))
|
||||
})));
|
||||
})))
|
||||
.await;
|
||||
|
||||
let req = TestRequest::with_uri("/test").to_request();
|
||||
let mut resp = call_service(&mut srv, req);
|
||||
let resp = call_service(&mut srv, req).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
||||
let body = block_on(resp.take_body().fold(
|
||||
BytesMut::new(),
|
||||
move |mut body, chunk| {
|
||||
body.extend_from_slice(&chunk);
|
||||
Ok::<_, Error>(body)
|
||||
},
|
||||
))
|
||||
.unwrap();
|
||||
assert_eq!(body.freeze(), Bytes::from_static(b"LINE-1LINE-2LINE-3"));
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"LINE-1LINE-2LINE-3"));
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,8 @@
|
||||
//! Websocket integration
|
||||
use std::collections::VecDeque;
|
||||
use std::io;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix::dev::{
|
||||
AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, StreamHandler,
|
||||
@@ -16,20 +18,20 @@ use actix_http::ws::{hash_key, Codec};
|
||||
pub use actix_http::ws::{
|
||||
CloseCode, CloseReason, Frame, HandshakeError, Message, ProtocolError,
|
||||
};
|
||||
|
||||
use actix_web::dev::HttpResponseBuilder;
|
||||
use actix_web::error::{Error, ErrorInternalServerError, PayloadError};
|
||||
use actix_web::error::{Error, PayloadError};
|
||||
use actix_web::http::{header, Method, StatusCode};
|
||||
use actix_web::{HttpRequest, HttpResponse};
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::sync::oneshot::Sender;
|
||||
use futures::{Async, Future, Poll, Stream};
|
||||
use futures::channel::oneshot::Sender;
|
||||
use futures::{Future, Stream};
|
||||
|
||||
/// Do websocket handshake and start ws actor.
|
||||
pub fn start<A, T>(actor: A, req: &HttpRequest, stream: T) -> Result<HttpResponse, Error>
|
||||
where
|
||||
A: Actor<Context = WebsocketContext<A>> + StreamHandler<Message, ProtocolError>,
|
||||
T: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
A: Actor<Context = WebsocketContext<A>>
|
||||
+ StreamHandler<Result<Message, ProtocolError>>,
|
||||
T: Stream<Item = Result<Bytes, PayloadError>> + 'static,
|
||||
{
|
||||
let mut res = handshake(req)?;
|
||||
Ok(res.streaming(WebsocketContext::create(actor, stream)))
|
||||
@@ -52,8 +54,9 @@ pub fn start_with_addr<A, T>(
|
||||
stream: T,
|
||||
) -> Result<(Addr<A>, HttpResponse), Error>
|
||||
where
|
||||
A: Actor<Context = WebsocketContext<A>> + StreamHandler<Message, ProtocolError>,
|
||||
T: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
A: Actor<Context = WebsocketContext<A>>
|
||||
+ StreamHandler<Result<Message, ProtocolError>>,
|
||||
T: Stream<Item = Result<Bytes, PayloadError>> + 'static,
|
||||
{
|
||||
let mut res = handshake(req)?;
|
||||
let (addr, out_stream) = WebsocketContext::create_with_addr(actor, stream);
|
||||
@@ -70,8 +73,9 @@ pub fn start_with_protocols<A, T>(
|
||||
stream: T,
|
||||
) -> Result<HttpResponse, Error>
|
||||
where
|
||||
A: Actor<Context = WebsocketContext<A>> + StreamHandler<Message, ProtocolError>,
|
||||
T: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
A: Actor<Context = WebsocketContext<A>>
|
||||
+ StreamHandler<Result<Message, ProtocolError>>,
|
||||
T: Stream<Item = Result<Bytes, PayloadError>> + 'static,
|
||||
{
|
||||
let mut res = handshake_with_protocols(req, protocols)?;
|
||||
Ok(res.streaming(WebsocketContext::create(actor, stream)))
|
||||
@@ -152,7 +156,8 @@ pub fn handshake_with_protocols(
|
||||
.and_then(|req_protocols| {
|
||||
let req_protocols = req_protocols.to_str().ok()?;
|
||||
req_protocols
|
||||
.split(", ")
|
||||
.split(',')
|
||||
.map(|req_p| req_p.trim())
|
||||
.find(|req_p| protocols.iter().any(|p| p == req_p))
|
||||
});
|
||||
|
||||
@@ -201,14 +206,14 @@ where
|
||||
{
|
||||
fn spawn<F>(&mut self, fut: F) -> SpawnHandle
|
||||
where
|
||||
F: ActorFuture<Item = (), Error = (), Actor = A> + 'static,
|
||||
F: ActorFuture<Output = (), Actor = A> + 'static,
|
||||
{
|
||||
self.inner.spawn(fut)
|
||||
}
|
||||
|
||||
fn wait<F>(&mut self, fut: F)
|
||||
where
|
||||
F: ActorFuture<Item = (), Error = (), Actor = A> + 'static,
|
||||
F: ActorFuture<Output = (), Actor = A> + 'static,
|
||||
{
|
||||
self.inner.wait(fut)
|
||||
}
|
||||
@@ -237,10 +242,10 @@ where
|
||||
{
|
||||
#[inline]
|
||||
/// Create a new Websocket context from a request and an actor
|
||||
pub fn create<S>(actor: A, stream: S) -> impl Stream<Item = Bytes, Error = Error>
|
||||
pub fn create<S>(actor: A, stream: S) -> impl Stream<Item = Result<Bytes, Error>>
|
||||
where
|
||||
A: StreamHandler<Message, ProtocolError>,
|
||||
S: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
A: StreamHandler<Result<Message, ProtocolError>>,
|
||||
S: Stream<Item = Result<Bytes, PayloadError>> + 'static,
|
||||
{
|
||||
let (_, stream) = WebsocketContext::create_with_addr(actor, stream);
|
||||
stream
|
||||
@@ -255,10 +260,10 @@ where
|
||||
pub fn create_with_addr<S>(
|
||||
actor: A,
|
||||
stream: S,
|
||||
) -> (Addr<A>, impl Stream<Item = Bytes, Error = Error>)
|
||||
) -> (Addr<A>, impl Stream<Item = Result<Bytes, Error>>)
|
||||
where
|
||||
A: StreamHandler<Message, ProtocolError>,
|
||||
S: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
A: StreamHandler<Result<Message, ProtocolError>>,
|
||||
S: Stream<Item = Result<Bytes, PayloadError>> + 'static,
|
||||
{
|
||||
let mb = Mailbox::default();
|
||||
let mut ctx = WebsocketContext {
|
||||
@@ -278,10 +283,10 @@ where
|
||||
actor: A,
|
||||
stream: S,
|
||||
codec: Codec,
|
||||
) -> impl Stream<Item = Bytes, Error = Error>
|
||||
) -> impl Stream<Item = Result<Bytes, Error>>
|
||||
where
|
||||
A: StreamHandler<Message, ProtocolError>,
|
||||
S: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
A: StreamHandler<Result<Message, ProtocolError>>,
|
||||
S: Stream<Item = Result<Bytes, PayloadError>> + 'static,
|
||||
{
|
||||
let mb = Mailbox::default();
|
||||
let mut ctx = WebsocketContext {
|
||||
@@ -297,11 +302,11 @@ where
|
||||
pub fn with_factory<S, F>(
|
||||
stream: S,
|
||||
f: F,
|
||||
) -> impl Stream<Item = Bytes, Error = Error>
|
||||
) -> impl Stream<Item = Result<Bytes, Error>>
|
||||
where
|
||||
F: FnOnce(&mut Self) -> A + 'static,
|
||||
A: StreamHandler<Message, ProtocolError>,
|
||||
S: Stream<Item = Bytes, Error = PayloadError> + 'static,
|
||||
A: StreamHandler<Result<Message, ProtocolError>>,
|
||||
S: Stream<Item = Result<Bytes, PayloadError>> + 'static,
|
||||
{
|
||||
let mb = Mailbox::default();
|
||||
let mut ctx = WebsocketContext {
|
||||
@@ -345,14 +350,14 @@ where
|
||||
|
||||
/// Send ping frame
|
||||
#[inline]
|
||||
pub fn ping(&mut self, message: &str) {
|
||||
self.write_raw(Message::Ping(message.to_string()));
|
||||
pub fn ping(&mut self, message: &[u8]) {
|
||||
self.write_raw(Message::Ping(Bytes::copy_from_slice(message)));
|
||||
}
|
||||
|
||||
/// Send pong frame
|
||||
#[inline]
|
||||
pub fn pong(&mut self, message: &str) {
|
||||
self.write_raw(Message::Pong(message.to_string()));
|
||||
pub fn pong(&mut self, message: &[u8]) {
|
||||
self.write_raw(Message::Pong(Bytes::copy_from_slice(message)));
|
||||
}
|
||||
|
||||
/// Send close frame
|
||||
@@ -414,30 +419,34 @@ impl<A> Stream for WebsocketContextFut<A>
|
||||
where
|
||||
A: Actor<Context = WebsocketContext<A>>,
|
||||
{
|
||||
type Item = Bytes;
|
||||
type Error = Error;
|
||||
type Item = Result<Bytes, Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<Bytes>, Error> {
|
||||
if self.fut.alive() && self.fut.poll().is_err() {
|
||||
return Err(ErrorInternalServerError("error"));
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
let this = self.get_mut();
|
||||
|
||||
if this.fut.alive() {
|
||||
let _ = Pin::new(&mut this.fut).poll(cx);
|
||||
}
|
||||
|
||||
// encode messages
|
||||
while let Some(item) = self.fut.ctx().messages.pop_front() {
|
||||
while let Some(item) = this.fut.ctx().messages.pop_front() {
|
||||
if let Some(msg) = item {
|
||||
self.encoder.encode(msg, &mut self.buf)?;
|
||||
this.encoder.encode(msg, &mut this.buf)?;
|
||||
} else {
|
||||
self.closed = true;
|
||||
this.closed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !self.buf.is_empty() {
|
||||
Ok(Async::Ready(Some(self.buf.take().freeze())))
|
||||
} else if self.fut.alive() && !self.closed {
|
||||
Ok(Async::NotReady)
|
||||
if !this.buf.is_empty() {
|
||||
Poll::Ready(Some(Ok(this.buf.split().freeze())))
|
||||
} else if this.fut.alive() && !this.closed {
|
||||
Poll::Pending
|
||||
} else {
|
||||
Ok(Async::Ready(None))
|
||||
Poll::Ready(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,7 +462,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[pin_project::pin_project]
|
||||
struct WsStream<S> {
|
||||
#[pin]
|
||||
stream: S,
|
||||
decoder: Codec,
|
||||
buf: BytesMut,
|
||||
@@ -462,7 +473,7 @@ struct WsStream<S> {
|
||||
|
||||
impl<S> WsStream<S>
|
||||
where
|
||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
||||
S: Stream<Item = Result<Bytes, PayloadError>>,
|
||||
{
|
||||
fn new(stream: S, codec: Codec) -> Self {
|
||||
Self {
|
||||
@@ -476,62 +487,64 @@ where
|
||||
|
||||
impl<S> Stream for WsStream<S>
|
||||
where
|
||||
S: Stream<Item = Bytes, Error = PayloadError>,
|
||||
S: Stream<Item = Result<Bytes, PayloadError>>,
|
||||
{
|
||||
type Item = Message;
|
||||
type Error = ProtocolError;
|
||||
type Item = Result<Message, ProtocolError>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
if !self.closed {
|
||||
fn poll_next(
|
||||
mut self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
let mut this = self.as_mut().project();
|
||||
|
||||
if !*this.closed {
|
||||
loop {
|
||||
match self.stream.poll() {
|
||||
Ok(Async::Ready(Some(chunk))) => {
|
||||
self.buf.extend_from_slice(&chunk[..]);
|
||||
this = self.as_mut().project();
|
||||
match Pin::new(&mut this.stream).poll_next(cx) {
|
||||
Poll::Ready(Some(Ok(chunk))) => {
|
||||
this.buf.extend_from_slice(&chunk[..]);
|
||||
}
|
||||
Ok(Async::Ready(None)) => {
|
||||
self.closed = true;
|
||||
Poll::Ready(None) => {
|
||||
*this.closed = true;
|
||||
break;
|
||||
}
|
||||
Ok(Async::NotReady) => break,
|
||||
Err(e) => {
|
||||
return Err(ProtocolError::Io(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{}", e),
|
||||
)));
|
||||
Poll::Pending => break,
|
||||
Poll::Ready(Some(Err(e))) => {
|
||||
return Poll::Ready(Some(Err(ProtocolError::Io(
|
||||
io::Error::new(io::ErrorKind::Other, format!("{}", e)),
|
||||
))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match self.decoder.decode(&mut self.buf)? {
|
||||
match this.decoder.decode(this.buf)? {
|
||||
None => {
|
||||
if self.closed {
|
||||
Ok(Async::Ready(None))
|
||||
if *this.closed {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
Some(frm) => {
|
||||
let msg = match frm {
|
||||
Frame::Text(data) => {
|
||||
if let Some(data) = data {
|
||||
Message::Text(
|
||||
std::str::from_utf8(&data)
|
||||
.map_err(|_| ProtocolError::BadEncoding)?
|
||||
.to_string(),
|
||||
)
|
||||
} else {
|
||||
Message::Text(String::new())
|
||||
}
|
||||
}
|
||||
Frame::Binary(data) => Message::Binary(
|
||||
data.map(|b| b.freeze()).unwrap_or_else(Bytes::new),
|
||||
Frame::Text(data) => Message::Text(
|
||||
std::str::from_utf8(&data)
|
||||
.map_err(|e| {
|
||||
ProtocolError::Io(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{}", e),
|
||||
))
|
||||
})?
|
||||
.to_string(),
|
||||
),
|
||||
Frame::Binary(data) => Message::Binary(data),
|
||||
Frame::Ping(s) => Message::Ping(s),
|
||||
Frame::Pong(s) => Message::Pong(s),
|
||||
Frame::Close(reason) => Message::Close(reason),
|
||||
Frame::Continuation(item) => Message::Continuation(item),
|
||||
};
|
||||
Ok(Async::Ready(Some(msg)))
|
||||
Poll::Ready(Some(Ok(msg)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -736,5 +749,46 @@ mod tests {
|
||||
.headers()
|
||||
.get(&header::SEC_WEBSOCKET_PROTOCOL)
|
||||
);
|
||||
|
||||
let req = TestRequest::default()
|
||||
.header(
|
||||
header::UPGRADE,
|
||||
header::HeaderValue::from_static("websocket"),
|
||||
)
|
||||
.header(
|
||||
header::CONNECTION,
|
||||
header::HeaderValue::from_static("upgrade"),
|
||||
)
|
||||
.header(
|
||||
header::SEC_WEBSOCKET_VERSION,
|
||||
header::HeaderValue::from_static("13"),
|
||||
)
|
||||
.header(
|
||||
header::SEC_WEBSOCKET_KEY,
|
||||
header::HeaderValue::from_static("13"),
|
||||
)
|
||||
.header(
|
||||
header::SEC_WEBSOCKET_PROTOCOL,
|
||||
header::HeaderValue::from_static("p1,p2,p3"),
|
||||
)
|
||||
.to_http_request();
|
||||
|
||||
let protocols = vec!["p3", "p2"];
|
||||
|
||||
assert_eq!(
|
||||
StatusCode::SWITCHING_PROTOCOLS,
|
||||
handshake_with_protocols(&req, &protocols)
|
||||
.unwrap()
|
||||
.finish()
|
||||
.status()
|
||||
);
|
||||
assert_eq!(
|
||||
Some(&header::HeaderValue::from_static("p2")),
|
||||
handshake_with_protocols(&req, &protocols)
|
||||
.unwrap()
|
||||
.finish()
|
||||
.headers()
|
||||
.get(&header::SEC_WEBSOCKET_PROTOCOL)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,8 @@
|
||||
use actix::prelude::*;
|
||||
use actix_http::HttpService;
|
||||
use actix_http_test::TestServer;
|
||||
use actix_web::{web, App, HttpRequest};
|
||||
use actix_web::{test, web, App, HttpRequest};
|
||||
use actix_web_actors::*;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::{Sink, Stream};
|
||||
use bytes::Bytes;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
|
||||
struct Ws;
|
||||
|
||||
@@ -12,9 +10,13 @@ impl Actor for Ws {
|
||||
type Context = ws::WebsocketContext<Self>;
|
||||
}
|
||||
|
||||
impl StreamHandler<ws::Message, ws::ProtocolError> for Ws {
|
||||
fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) {
|
||||
match msg {
|
||||
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for Ws {
|
||||
fn handle(
|
||||
&mut self,
|
||||
msg: Result<ws::Message, ws::ProtocolError>,
|
||||
ctx: &mut Self::Context,
|
||||
) {
|
||||
match msg.unwrap() {
|
||||
ws::Message::Ping(msg) => ctx.pong(&msg),
|
||||
ws::Message::Text(text) => ctx.text(text),
|
||||
ws::Message::Binary(bin) => ctx.binary(bin),
|
||||
@@ -24,45 +26,42 @@ impl StreamHandler<ws::Message, ws::ProtocolError> for Ws {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simple() {
|
||||
let mut srv =
|
||||
TestServer::new(|| {
|
||||
HttpService::new(App::new().service(web::resource("/").to(
|
||||
|req: HttpRequest, stream: web::Payload| ws::start(Ws, &req, stream),
|
||||
)))
|
||||
});
|
||||
#[actix_rt::test]
|
||||
async fn test_simple() {
|
||||
let mut srv = test::start(|| {
|
||||
App::new().service(web::resource("/").to(
|
||||
|req: HttpRequest, stream: web::Payload| {
|
||||
async move { ws::start(Ws, &req, stream) }
|
||||
},
|
||||
))
|
||||
});
|
||||
|
||||
// client service
|
||||
let framed = srv.ws().unwrap();
|
||||
let framed = srv
|
||||
.block_on(framed.send(ws::Message::Text("text".to_string())))
|
||||
.unwrap();
|
||||
let (item, framed) = srv.block_on(framed.into_future()).map_err(|_| ()).unwrap();
|
||||
assert_eq!(item, Some(ws::Frame::Text(Some(BytesMut::from("text")))));
|
||||
|
||||
let framed = srv
|
||||
.block_on(framed.send(ws::Message::Binary("text".into())))
|
||||
.unwrap();
|
||||
let (item, framed) = srv.block_on(framed.into_future()).map_err(|_| ()).unwrap();
|
||||
assert_eq!(
|
||||
item,
|
||||
Some(ws::Frame::Binary(Some(Bytes::from_static(b"text").into())))
|
||||
);
|
||||
|
||||
let framed = srv
|
||||
.block_on(framed.send(ws::Message::Ping("text".into())))
|
||||
.unwrap();
|
||||
let (item, framed) = srv.block_on(framed.into_future()).map_err(|_| ()).unwrap();
|
||||
assert_eq!(item, Some(ws::Frame::Pong("text".to_string().into())));
|
||||
|
||||
let framed = srv
|
||||
.block_on(framed.send(ws::Message::Close(Some(ws::CloseCode::Normal.into()))))
|
||||
let mut framed = srv.ws().await.unwrap();
|
||||
framed
|
||||
.send(ws::Message::Text("text".to_string()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (item, _framed) = srv.block_on(framed.into_future()).map_err(|_| ()).unwrap();
|
||||
assert_eq!(
|
||||
item,
|
||||
Some(ws::Frame::Close(Some(ws::CloseCode::Normal.into())))
|
||||
);
|
||||
let item = framed.next().await.unwrap().unwrap();
|
||||
assert_eq!(item, ws::Frame::Text(Bytes::from_static(b"text")));
|
||||
|
||||
framed
|
||||
.send(ws::Message::Binary("text".into()))
|
||||
.await
|
||||
.unwrap();
|
||||
let item = framed.next().await.unwrap().unwrap();
|
||||
assert_eq!(item, ws::Frame::Binary(Bytes::from_static(b"text").into()));
|
||||
|
||||
framed.send(ws::Message::Ping("text".into())).await.unwrap();
|
||||
let item = framed.next().await.unwrap().unwrap();
|
||||
assert_eq!(item, ws::Frame::Pong(Bytes::copy_from_slice(b"text")));
|
||||
|
||||
framed
|
||||
.send(ws::Message::Close(Some(ws::CloseCode::Normal.into())))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let item = framed.next().await.unwrap().unwrap();
|
||||
assert_eq!(item, ws::Frame::Close(Some(ws::CloseCode::Normal.into())));
|
||||
}
|
||||
|
@@ -1,5 +1,9 @@
|
||||
# Changes
|
||||
|
||||
## [0.2.0] - 2019-12-13
|
||||
|
||||
* Generate code for actix-web 2.0
|
||||
|
||||
## [0.1.3] - 2019-10-14
|
||||
|
||||
* Bump up `syn` & `quote` to 1.0
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-web-codegen"
|
||||
version = "0.2.0-alpha.2"
|
||||
version = "0.2.0"
|
||||
description = "Actix web proc macros"
|
||||
readme = "README.md"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
@@ -17,8 +17,6 @@ syn = { version = "^1", features = ["full", "parsing"] }
|
||||
proc-macro2 = "^1"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = { version = "1.0.0-alpha.2" }
|
||||
actix-web = { version = "2.0.0-alpha.2" }
|
||||
actix-http = { version = "0.3.0-alpha.2", features=["openssl"] }
|
||||
actix-http-test = { version = "0.3.0-alpha.2", features=["openssl"] }
|
||||
actix-rt = { version = "1.0.0" }
|
||||
actix-web = { version = "2.0.0-rc" }
|
||||
futures = { version = "0.3.1" }
|
||||
|
@@ -1,11 +1,9 @@
|
||||
use actix_http::HttpService;
|
||||
use actix_http_test::TestServer;
|
||||
use actix_web::{http, web::Path, App, HttpResponse, Responder};
|
||||
use actix_web::{http, test, web::Path, App, HttpResponse, Responder};
|
||||
use actix_web_codegen::{connect, delete, get, head, options, patch, post, put, trace};
|
||||
use futures::{future, Future};
|
||||
|
||||
#[get("/test")]
|
||||
async fn test() -> impl Responder {
|
||||
async fn test_handler() -> impl Responder {
|
||||
HttpResponse::Ok()
|
||||
}
|
||||
|
||||
@@ -71,14 +69,11 @@ async fn get_param_test(_: Path<String>) -> impl Responder {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_params() {
|
||||
let srv = TestServer::start(|| {
|
||||
HttpService::new(
|
||||
App::new()
|
||||
.service(get_param_test)
|
||||
.service(put_param_test)
|
||||
.service(delete_param_test),
|
||||
)
|
||||
.tcp()
|
||||
let srv = test::start(|| {
|
||||
App::new()
|
||||
.service(get_param_test)
|
||||
.service(put_param_test)
|
||||
.service(delete_param_test)
|
||||
});
|
||||
|
||||
let request = srv.request(http::Method::GET, srv.url("/test/it"));
|
||||
@@ -96,19 +91,16 @@ async fn test_params() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_body() {
|
||||
let srv = TestServer::start(|| {
|
||||
HttpService::new(
|
||||
App::new()
|
||||
.service(post_test)
|
||||
.service(put_test)
|
||||
.service(head_test)
|
||||
.service(connect_test)
|
||||
.service(options_test)
|
||||
.service(trace_test)
|
||||
.service(patch_test)
|
||||
.service(test),
|
||||
)
|
||||
.tcp()
|
||||
let srv = test::start(|| {
|
||||
App::new()
|
||||
.service(post_test)
|
||||
.service(put_test)
|
||||
.service(head_test)
|
||||
.service(connect_test)
|
||||
.service(options_test)
|
||||
.service(trace_test)
|
||||
.service(patch_test)
|
||||
.service(test_handler)
|
||||
});
|
||||
let request = srv.request(http::Method::GET, srv.url("/test"));
|
||||
let response = request.send().await.unwrap();
|
||||
@@ -151,8 +143,7 @@ async fn test_body() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_auto_async() {
|
||||
let srv =
|
||||
TestServer::start(|| HttpService::new(App::new().service(auto_async)).tcp());
|
||||
let srv = test::start(|| App::new().service(auto_async));
|
||||
|
||||
let request = srv.request(http::Method::GET, srv.url("/test"));
|
||||
let response = request.send().await.unwrap();
|
||||
|
@@ -1,5 +1,14 @@
|
||||
# Changes
|
||||
|
||||
## [1.0.1] - 2019-12-15
|
||||
|
||||
* Fix compilation with default features off
|
||||
|
||||
|
||||
## [1.0.0] - 2019-12-13
|
||||
|
||||
* Release
|
||||
|
||||
## [1.0.0-alpha.3]
|
||||
|
||||
* Migrate to `std::future`
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "awc"
|
||||
version = "1.0.0-alpha.3"
|
||||
version = "1.0.1"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix http client."
|
||||
readme = "README.md"
|
||||
@@ -12,19 +12,17 @@ categories = ["network-programming", "asynchronous",
|
||||
"web-programming::http-client",
|
||||
"web-programming::websocket"]
|
||||
license = "MIT/Apache-2.0"
|
||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||
edition = "2018"
|
||||
workspace = ".."
|
||||
|
||||
[lib]
|
||||
name = "awc"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["openssl", "rustls", "brotli", "flate2-zlib"]
|
||||
features = ["openssl", "rustls", "compress"]
|
||||
|
||||
[features]
|
||||
default = ["brotli", "flate2-zlib"]
|
||||
default = ["compress"]
|
||||
|
||||
# openssl
|
||||
openssl = ["open-ssl", "actix-http/openssl"]
|
||||
@@ -32,25 +30,19 @@ openssl = ["open-ssl", "actix-http/openssl"]
|
||||
# rustls
|
||||
rustls = ["rust-tls", "actix-http/rustls"]
|
||||
|
||||
# brotli encoding, requires c compiler
|
||||
brotli = ["actix-http/brotli"]
|
||||
|
||||
# miniz-sys backend for flate2 crate
|
||||
flate2-zlib = ["actix-http/flate2-zlib"]
|
||||
|
||||
# rust backend for flate2 crate
|
||||
flate2-rust = ["actix-http/flate2-rust"]
|
||||
# content-encoding support
|
||||
compress = ["actix-http/compress"]
|
||||
|
||||
[dependencies]
|
||||
actix-codec = "0.2.0-alpha.3"
|
||||
actix-service = "1.0.0-alpha.3"
|
||||
actix-http = "1.0.0-alpha.3"
|
||||
actix-rt = "1.0.0-alpha.3"
|
||||
actix-codec = "0.2.0"
|
||||
actix-service = "1.0.0"
|
||||
actix-http = "1.0.0"
|
||||
actix-rt = "1.0.0"
|
||||
|
||||
base64 = "0.11"
|
||||
bytes = "0.5.2"
|
||||
bytes = "0.5.3"
|
||||
derive_more = "0.99.2"
|
||||
futures = "0.3.1"
|
||||
futures-core = "0.3.1"
|
||||
log =" 0.4"
|
||||
mime = "0.3"
|
||||
percent-encoding = "2.1"
|
||||
@@ -62,14 +54,15 @@ open-ssl = { version="0.10", package="openssl", optional = true }
|
||||
rust-tls = { version = "0.16.0", package="rustls", optional = true, features = ["dangerous_configuration"] }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-connect = { version = "1.0.0-alpha.3", features=["openssl"] }
|
||||
actix-web = { version = "2.0.0-alpha.3", features=["openssl"] }
|
||||
actix-http = { version = "1.0.0-alpha.3", features=["openssl"] }
|
||||
actix-http-test = { version = "1.0.0-alpha.3", features=["openssl"] }
|
||||
actix-utils = "1.0.0-alpha.3"
|
||||
actix-server = { version = "1.0.0-alpha.3" }
|
||||
actix-tls = { version = "1.0.0-alpha.3", features=["openssl", "rustls"] }
|
||||
brotli2 = { version="0.3.2" }
|
||||
flate2 = { version="1.0.2" }
|
||||
actix-connect = { version = "1.0.1", features=["openssl"] }
|
||||
actix-web = { version = "2.0.0-rc", features=["openssl"] }
|
||||
actix-http = { version = "1.0.1", features=["openssl"] }
|
||||
actix-http-test = { version = "1.0.0", features=["openssl"] }
|
||||
actix-utils = "1.0.3"
|
||||
actix-server = "1.0.0"
|
||||
actix-tls = { version = "1.0.0", features=["openssl", "rustls"] }
|
||||
brotli2 = "0.3.2"
|
||||
flate2 = "1.0.13"
|
||||
futures = "0.3.1"
|
||||
env_logger = "0.6"
|
||||
webpki = { version = "0.21" }
|
||||
webpki = "0.21"
|
||||
|
@@ -1,3 +1,4 @@
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
@@ -12,7 +13,6 @@ use actix_http::h1::ClientCodec;
|
||||
use actix_http::http::HeaderMap;
|
||||
use actix_http::{RequestHead, RequestHeadType, ResponseHead};
|
||||
use actix_service::Service;
|
||||
use futures::future::{FutureExt, LocalBoxFuture};
|
||||
|
||||
use crate::response::ClientResponse;
|
||||
|
||||
@@ -24,7 +24,7 @@ pub(crate) trait Connect {
|
||||
head: RequestHead,
|
||||
body: Body,
|
||||
addr: Option<net::SocketAddr>,
|
||||
) -> LocalBoxFuture<'static, Result<ClientResponse, SendRequestError>>;
|
||||
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>>;
|
||||
|
||||
fn send_request_extra(
|
||||
&mut self,
|
||||
@@ -32,16 +32,22 @@ pub(crate) trait Connect {
|
||||
extra_headers: Option<HeaderMap>,
|
||||
body: Body,
|
||||
addr: Option<net::SocketAddr>,
|
||||
) -> LocalBoxFuture<'static, Result<ClientResponse, SendRequestError>>;
|
||||
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>>;
|
||||
|
||||
/// Send request, returns Response and Framed
|
||||
fn open_tunnel(
|
||||
&mut self,
|
||||
head: RequestHead,
|
||||
addr: Option<net::SocketAddr>,
|
||||
) -> LocalBoxFuture<
|
||||
'static,
|
||||
Result<(ResponseHead, Framed<BoxedSocket, ClientCodec>), SendRequestError>,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<
|
||||
Output = Result<
|
||||
(ResponseHead, Framed<BoxedSocket, ClientCodec>),
|
||||
SendRequestError,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
>;
|
||||
|
||||
/// Send request and extra headers, returns Response and Framed
|
||||
@@ -50,9 +56,15 @@ pub(crate) trait Connect {
|
||||
head: Rc<RequestHead>,
|
||||
extra_headers: Option<HeaderMap>,
|
||||
addr: Option<net::SocketAddr>,
|
||||
) -> LocalBoxFuture<
|
||||
'static,
|
||||
Result<(ResponseHead, Framed<BoxedSocket, ClientCodec>), SendRequestError>,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<
|
||||
Output = Result<
|
||||
(ResponseHead, Framed<BoxedSocket, ClientCodec>),
|
||||
SendRequestError,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
>;
|
||||
}
|
||||
|
||||
@@ -70,14 +82,14 @@ where
|
||||
head: RequestHead,
|
||||
body: Body,
|
||||
addr: Option<net::SocketAddr>,
|
||||
) -> LocalBoxFuture<'static, Result<ClientResponse, SendRequestError>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>> {
|
||||
// connect to the host
|
||||
let fut = self.0.call(ClientConnect {
|
||||
uri: head.uri.clone(),
|
||||
addr,
|
||||
});
|
||||
|
||||
async move {
|
||||
Box::pin(async move {
|
||||
let connection = fut.await?;
|
||||
|
||||
// send request
|
||||
@@ -85,8 +97,7 @@ where
|
||||
.send_request(RequestHeadType::from(head), body)
|
||||
.await
|
||||
.map(|(head, payload)| ClientResponse::new(head, payload))
|
||||
}
|
||||
.boxed_local()
|
||||
})
|
||||
}
|
||||
|
||||
fn send_request_extra(
|
||||
@@ -95,14 +106,14 @@ where
|
||||
extra_headers: Option<HeaderMap>,
|
||||
body: Body,
|
||||
addr: Option<net::SocketAddr>,
|
||||
) -> LocalBoxFuture<'static, Result<ClientResponse, SendRequestError>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>> {
|
||||
// connect to the host
|
||||
let fut = self.0.call(ClientConnect {
|
||||
uri: head.uri.clone(),
|
||||
addr,
|
||||
});
|
||||
|
||||
async move {
|
||||
Box::pin(async move {
|
||||
let connection = fut.await?;
|
||||
|
||||
// send request
|
||||
@@ -111,17 +122,22 @@ where
|
||||
.await?;
|
||||
|
||||
Ok(ClientResponse::new(head, payload))
|
||||
}
|
||||
.boxed_local()
|
||||
})
|
||||
}
|
||||
|
||||
fn open_tunnel(
|
||||
&mut self,
|
||||
head: RequestHead,
|
||||
addr: Option<net::SocketAddr>,
|
||||
) -> LocalBoxFuture<
|
||||
'static,
|
||||
Result<(ResponseHead, Framed<BoxedSocket, ClientCodec>), SendRequestError>,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<
|
||||
Output = Result<
|
||||
(ResponseHead, Framed<BoxedSocket, ClientCodec>),
|
||||
SendRequestError,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
// connect to the host
|
||||
let fut = self.0.call(ClientConnect {
|
||||
@@ -129,7 +145,7 @@ where
|
||||
addr,
|
||||
});
|
||||
|
||||
async move {
|
||||
Box::pin(async move {
|
||||
let connection = fut.await?;
|
||||
|
||||
// send request
|
||||
@@ -138,8 +154,7 @@ where
|
||||
|
||||
let framed = framed.map_io(|io| BoxedSocket(Box::new(Socket(io))));
|
||||
Ok((head, framed))
|
||||
}
|
||||
.boxed_local()
|
||||
})
|
||||
}
|
||||
|
||||
fn open_tunnel_extra(
|
||||
@@ -147,9 +162,15 @@ where
|
||||
head: Rc<RequestHead>,
|
||||
extra_headers: Option<HeaderMap>,
|
||||
addr: Option<net::SocketAddr>,
|
||||
) -> LocalBoxFuture<
|
||||
'static,
|
||||
Result<(ResponseHead, Framed<BoxedSocket, ClientCodec>), SendRequestError>,
|
||||
) -> Pin<
|
||||
Box<
|
||||
dyn Future<
|
||||
Output = Result<
|
||||
(ResponseHead, Framed<BoxedSocket, ClientCodec>),
|
||||
SendRequestError,
|
||||
>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
// connect to the host
|
||||
let fut = self.0.call(ClientConnect {
|
||||
@@ -157,7 +178,7 @@ where
|
||||
addr,
|
||||
});
|
||||
|
||||
async move {
|
||||
Box::pin(async move {
|
||||
let connection = fut.await?;
|
||||
|
||||
// send request
|
||||
@@ -167,8 +188,7 @@ where
|
||||
|
||||
let framed = framed.map_io(|io| BoxedSocket(Box::new(Socket(io))));
|
||||
Ok((head, framed))
|
||||
}
|
||||
.boxed_local()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +215,7 @@ impl<T: AsyncRead + AsyncWrite + Unpin> AsyncSocket for Socket<T> {
|
||||
pub struct BoxedSocket(Box<dyn AsyncSocket>);
|
||||
|
||||
impl fmt::Debug for BoxedSocket {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "BoxedSocket")
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ use std::rc::Rc;
|
||||
use std::time::Duration;
|
||||
|
||||
use bytes::Bytes;
|
||||
use futures::Stream;
|
||||
use futures_core::Stream;
|
||||
use serde::Serialize;
|
||||
|
||||
use actix_http::body::Body;
|
||||
|
@@ -1,4 +1,9 @@
|
||||
#![allow(clippy::borrow_interior_mutable_const)]
|
||||
#![deny(rust_2018_idioms, warnings)]
|
||||
#![allow(
|
||||
clippy::type_complexity,
|
||||
clippy::borrow_interior_mutable_const,
|
||||
clippy::needless_doctest_main
|
||||
)]
|
||||
//! An HTTP Client
|
||||
//!
|
||||
//! ```rust
|
||||
@@ -11,9 +16,9 @@
|
||||
//! let mut client = Client::default();
|
||||
//!
|
||||
//! let response = client.get("http://www.rust-lang.org") // <- Create request builder
|
||||
//! .header("User-Agent", "Actix-web")
|
||||
//! .send() // <- Send http request
|
||||
//! .await;
|
||||
//! .header("User-Agent", "Actix-web")
|
||||
//! .send() // <- Send http request
|
||||
//! .await;
|
||||
//!
|
||||
//! println!("Response: {:?}", response);
|
||||
//! }
|
||||
@@ -50,22 +55,18 @@ use self::connect::{Connect, ConnectorWrapper};
|
||||
/// An HTTP Client
|
||||
///
|
||||
/// ```rust
|
||||
/// use actix_rt::System;
|
||||
/// use awc::Client;
|
||||
///
|
||||
/// fn main() {
|
||||
/// System::new("test").block_on(async {
|
||||
/// let mut client = Client::default();
|
||||
/// #[actix_rt::main]
|
||||
/// async fn main() {
|
||||
/// let mut client = Client::default();
|
||||
///
|
||||
/// client.get("http://www.rust-lang.org") // <- Create request builder
|
||||
/// .header("User-Agent", "Actix-web")
|
||||
/// .send() // <- Send http request
|
||||
/// .await
|
||||
/// .and_then(|response| { // <- server http response
|
||||
/// println!("Response: {:?}", response);
|
||||
/// Ok(())
|
||||
/// })
|
||||
/// });
|
||||
/// let res = client.get("http://www.rust-lang.org") // <- Create request builder
|
||||
/// .header("User-Agent", "Actix-web")
|
||||
/// .send() // <- Send http request
|
||||
/// .await; // <- send request and wait for response
|
||||
///
|
||||
/// println!("Response: {:?}", res);
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user