Merge branch 'master' into tokio0.3

This commit is contained in:
fakeshadow 2020-12-29 17:47:04 +08:00 committed by GitHub
commit d6d8fa68e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 123 additions and 254 deletions

View File

@ -13,7 +13,7 @@ jobs:
fail-fast: false
matrix:
version:
- 1.42.0 # MSRV
- 1.46.0 # MSRV
- stable
- nightly
@ -30,6 +30,13 @@ jobs:
profile: minimal
override: true
- name: Generate Cargo.lock
uses: actions-rs/cargo@v1
with:
command: generate-lockfile
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.0.1
- name: check build
uses: actions-rs/cargo@v1
with:
@ -58,12 +65,17 @@ jobs:
args: --package=awc --no-default-features --features=rustls -- --nocapture
- name: Generate coverage file
if: matrix.version == 'stable' && (github.ref == 'refs/heads/master' || github.event_name == 'pull_request')
if: matrix.version == 'stable' && github.ref == 'refs/heads/master'
run: |
cargo install cargo-tarpaulin --vers "^0.13"
cargo tarpaulin --out Xml
- name: Upload to Codecov
if: matrix.version == 'stable' && (github.ref == 'refs/heads/master' || github.event_name == 'pull_request')
if: matrix.version == 'stable' && github.ref == 'refs/heads/master'
uses: codecov/codecov-action@v1
with:
file: cobertura.xml
- name: Clear the cargo caches
run: |
cargo install cargo-cache --no-default-features --features ci-autoclean
cargo-cache

View File

@ -29,6 +29,13 @@ jobs:
profile: minimal
override: true
- name: Generate Cargo.lock
uses: actions-rs/cargo@v1
with:
command: generate-lockfile
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.0.1
- name: check build
uses: actions-rs/cargo@v1
with:
@ -42,3 +49,8 @@ jobs:
args: --all --all-features --no-fail-fast -- --nocapture
--skip=test_h2_content_length
--skip=test_reading_deflate_encoding_large_random_rustls
- name: Clear the cargo caches
run: |
cargo install cargo-cache --no-default-features --features ci-autoclean
cargo-cache

View File

@ -41,6 +41,13 @@ jobs:
Get-ChildItem C:\vcpkg\installed\x64-windows\bin
Get-ChildItem C:\vcpkg\installed\x64-windows\lib
- name: Generate Cargo.lock
uses: actions-rs/cargo@v1
with:
command: generate-lockfile
- name: Cache Dependencies
uses: Swatinem/rust-cache@v1.0.1
- name: check build
uses: actions-rs/cargo@v1
with:
@ -62,3 +69,8 @@ jobs:
--skip=test_connection_force_close
--skip=test_connection_server_close
--skip=test_connection_wait_queue_force_close
- name: Clear the cargo caches
run: |
cargo install cargo-cache --no-default-features --features ci-autoclean
cargo-cache

View File

@ -5,6 +5,7 @@
* Bumped `rand` to `0.8`
* Update `rust-tls` to `0.19.0`
* Rename `Handler` to `HandlerService` and rename `Factory` to `Handler`. [#1852]
* MSRV is now 1.46.0.
### Fixed

View File

@ -7,7 +7,7 @@
[![crates.io](https://img.shields.io/crates/v/actix-web?label=latest)](https://crates.io/crates/actix-web)
[![Documentation](https://docs.rs/actix-web/badge.svg?version=3.3.2)](https://docs.rs/actix-web/3.3.2)
[![Version](https://img.shields.io/badge/rustc-1.42+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)
[![Version](https://img.shields.io/badge/rustc-1.46+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
![License](https://img.shields.io/crates/l/actix-web.svg)
[![Dependency Status](https://deps.rs/crate/actix-web/3.3.2/status.svg)](https://deps.rs/crate/actix-web/3.3.2)
<br />
@ -34,7 +34,7 @@
* Middlewares ([Logger, Session, CORS, etc](https://actix.rs/docs/middleware/))
* Includes an async [HTTP client](https://actix.rs/actix-web/actix_web/client/index.html)
* Supports [Actix actor framework](https://github.com/actix/actix)
* Runs on stable Rust 1.42+
* Runs on stable Rust 1.46+
## Documentation

View File

@ -2,6 +2,7 @@
## Unreleased - 2020-xx-xx
* Update `bytes` to `1`.
* `HttpRange::parse` now has its own error type.
## 0.5.0 - 2020-12-26

View File

@ -4,7 +4,7 @@
[![crates.io](https://img.shields.io/crates/v/actix-files?label=latest)](https://crates.io/crates/actix-files)
[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.5.0)](https://docs.rs/actix-files/0.5.0)
[![Version](https://img.shields.io/badge/rustc-1.42+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)
[![Version](https://img.shields.io/badge/rustc-1.46+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
![License](https://img.shields.io/crates/l/actix-files.svg)
<br />
[![dependency status](https://deps.rs/crate/actix-files/0.5.0/status.svg)](https://deps.rs/crate/actix-files/0.5.0)
@ -16,4 +16,4 @@
- [API Documentation](https://docs.rs/actix-files/)
- [Example Project](https://github.com/actix/examples/tree/master/static_index)
- [Chat on Gitter](https://gitter.im/actix/actix-web)
- Minimum supported Rust version: 1.42 or later
- Minimum supported Rust version: 1.46 or later

View File

@ -1,3 +1,5 @@
use derive_more::{Display, Error};
/// HTTP Range header representation.
#[derive(Debug, Clone, Copy)]
pub struct HttpRange {
@ -11,17 +13,21 @@ pub struct HttpRange {
const PREFIX: &str = "bytes=";
const PREFIX_LEN: usize = 6;
#[derive(Debug, Clone, Display, Error)]
#[display(fmt = "Parse HTTP Range failed")]
pub struct ParseRangeErr(#[error(not(source))] ());
impl HttpRange {
/// Parses Range HTTP header string as per RFC 2616.
///
/// `header` is HTTP Range header (e.g. `bytes=bytes=0-9`).
/// `size` is full size of response (file).
pub fn parse(header: &str, size: u64) -> Result<Vec<HttpRange>, ()> {
pub fn parse(header: &str, size: u64) -> Result<Vec<HttpRange>, ParseRangeErr> {
if header.is_empty() {
return Ok(Vec::new());
}
if !header.starts_with(PREFIX) {
return Err(());
return Err(ParseRangeErr(()));
}
let size_sig = size as i64;
@ -34,13 +40,14 @@ impl HttpRange {
.map(|ra| {
let mut start_end_iter = ra.split('-');
let start_str = start_end_iter.next().ok_or(())?.trim();
let end_str = start_end_iter.next().ok_or(())?.trim();
let start_str = start_end_iter.next().ok_or(ParseRangeErr(()))?.trim();
let end_str = start_end_iter.next().ok_or(ParseRangeErr(()))?.trim();
if start_str.is_empty() {
// If no start is specified, end specifies the
// range start relative to the end of the file.
let mut length: i64 = end_str.parse().map_err(|_| ())?;
let mut length: i64 =
end_str.parse().map_err(|_| ParseRangeErr(()))?;
if length > size_sig {
length = size_sig;
@ -51,10 +58,10 @@ impl HttpRange {
length: length as u64,
}))
} else {
let start: i64 = start_str.parse().map_err(|_| ())?;
let start: i64 = start_str.parse().map_err(|_| ParseRangeErr(()))?;
if start < 0 {
return Err(());
return Err(ParseRangeErr(()));
}
if start >= size_sig {
no_overlap = true;
@ -65,10 +72,11 @@ impl HttpRange {
// If no end is specified, range extends to end of the file.
size_sig - start
} else {
let mut end: i64 = end_str.parse().map_err(|_| ())?;
let mut end: i64 =
end_str.parse().map_err(|_| ParseRangeErr(()))?;
if start > end {
return Err(());
return Err(ParseRangeErr(()));
}
if end >= size_sig {
@ -89,7 +97,7 @@ impl HttpRange {
let ranges: Vec<HttpRange> = all_ranges.into_iter().filter_map(|x| x).collect();
if no_overlap && ranges.is_empty() {
return Err(());
return Err(ParseRangeErr(()));
}
Ok(ranges)
@ -333,8 +341,7 @@ mod tests {
if expected.is_empty() {
continue;
} else {
assert!(
false,
panic!(
"parse({}, {}) returned error {:?}",
header,
size,
@ -346,28 +353,24 @@ mod tests {
let got = res.unwrap();
if got.len() != expected.len() {
assert!(
false,
panic!(
"len(parseRange({}, {})) = {}, want {}",
header,
size,
got.len(),
expected.len()
);
continue;
}
for i in 0..expected.len() {
if got[i].start != expected[i].start {
assert!(
false,
panic!(
"parseRange({}, {})[{}].start = {}, want {}",
header, size, i, got[i].start, expected[i].start
)
}
if got[i].length != expected[i].length {
assert!(
false,
panic!(
"parseRange({}, {})[{}].length = {}, want {}",
header, size, i, got[i].length, expected[i].length
)

View File

@ -12,4 +12,4 @@
- [API Documentation](https://docs.rs/actix-http-test)
- [Chat on Gitter](https://gitter.im/actix/actix-web)
- Minimum Supported Rust Version (MSRV): 1.42.0
- Minimum Supported Rust Version (MSRV): 1.46.0

View File

@ -6,6 +6,13 @@
* Upgrade `bytes` to `1`
* Upgrade `h2` to `0.3`
### Removed
* Deprecated `on_connect` methods have been removed. Prefer the new
`on_connect_ext` technique. [#1857]
[#1857]: https://github.com/actix/actix-web/pull/1857
## 2.2.0 - 2020-11-25
### Added
* HttpResponse builders for 1xx status codes. [#1768]

View File

@ -12,7 +12,7 @@
- [API Documentation](https://docs.rs/actix-http)
- [Chat on Gitter](https://gitter.im/actix/actix-web)
- Minimum Supported Rust Version (MSRV): 1.42.0
- Minimum Supported Rust Version (MSRV): 1.46.0
## Example

View File

@ -10,7 +10,6 @@ use crate::config::{KeepAlive, ServiceConfig};
use crate::error::Error;
use crate::h1::{Codec, ExpectHandler, H1Service, UpgradeHandler};
use crate::h2::H2Service;
use crate::helpers::{Data, DataFactory};
use crate::request::Request;
use crate::response::Response;
use crate::service::HttpService;
@ -28,8 +27,6 @@ pub struct HttpServiceBuilder<T, S, X = ExpectHandler, U = UpgradeHandler> {
local_addr: Option<net::SocketAddr>,
expect: X,
upgrade: Option<U>,
// DEPRECATED: in favor of on_connect_ext
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<S>,
}
@ -51,7 +48,6 @@ where
local_addr: None,
expect: ExpectHandler,
upgrade: None,
on_connect: None,
on_connect_ext: None,
_t: PhantomData,
}
@ -141,7 +137,6 @@ where
local_addr: self.local_addr,
expect: expect.into_factory(),
upgrade: self.upgrade,
on_connect: self.on_connect,
on_connect_ext: self.on_connect_ext,
_t: PhantomData,
}
@ -167,26 +162,11 @@ where
local_addr: self.local_addr,
expect: self.expect,
upgrade: Some(upgrade.into_factory()),
on_connect: self.on_connect,
on_connect_ext: self.on_connect_ext,
_t: PhantomData,
}
}
/// Set on-connect callback.
///
/// Called once per connection. Return value of the call is stored in request extensions.
///
/// *SOFT DEPRECATED*: Prefer the `on_connect_ext` style callback.
pub fn on_connect<F, I>(mut self, f: F) -> Self
where
F: Fn(&T) -> I + 'static,
I: Clone + 'static,
{
self.on_connect = Some(Rc::new(move |io| Box::new(Data(f(io)))));
self
}
/// Sets the callback to be run on connection establishment.
///
/// Has mutable access to a data container that will be merged into request extensions.
@ -220,7 +200,6 @@ where
H1Service::with_config(cfg, service.into_factory())
.expect(self.expect)
.upgrade(self.upgrade)
.on_connect(self.on_connect)
.on_connect_ext(self.on_connect_ext)
}
@ -243,7 +222,6 @@ where
);
H2Service::with_config(cfg, service.into_factory())
.on_connect(self.on_connect)
.on_connect_ext(self.on_connect_ext)
}
@ -268,7 +246,6 @@ where
HttpService::with_config(cfg, service.into_factory())
.expect(self.expect)
.upgrade(self.upgrade)
.on_connect(self.on_connect)
.on_connect_ext(self.on_connect_ext)
}
}

View File

View File

@ -19,7 +19,6 @@ use crate::cloneable::CloneableService;
use crate::config::ServiceConfig;
use crate::error::{DispatchError, Error};
use crate::error::{ParseError, PayloadError};
use crate::helpers::DataFactory;
use crate::httpmessage::HttpMessage;
use crate::request::Request;
use crate::response::Response;
@ -96,7 +95,6 @@ where
service: CloneableService<S>,
expect: CloneableService<X>,
upgrade: Option<CloneableService<U>>,
on_connect: Option<Box<dyn DataFactory>>,
on_connect_data: Extensions,
flags: Flags,
peer_addr: Option<net::SocketAddr>,
@ -185,7 +183,6 @@ where
service: CloneableService<S>,
expect: CloneableService<X>,
upgrade: Option<CloneableService<U>>,
on_connect: Option<Box<dyn DataFactory>>,
on_connect_data: Extensions,
peer_addr: Option<net::SocketAddr>,
) -> Self {
@ -198,7 +195,6 @@ where
service,
expect,
upgrade,
on_connect,
on_connect_data,
peer_addr,
)
@ -214,7 +210,6 @@ where
service: CloneableService<S>,
expect: CloneableService<X>,
upgrade: Option<CloneableService<U>>,
on_connect: Option<Box<dyn DataFactory>>,
on_connect_data: Extensions,
peer_addr: Option<net::SocketAddr>,
) -> Self {
@ -247,7 +242,6 @@ where
service,
expect,
upgrade,
on_connect,
on_connect_data,
flags,
peer_addr,
@ -573,12 +567,6 @@ where
let pl = this.codec.message_type();
req.head_mut().peer_addr = *this.peer_addr;
// DEPRECATED
// set on_connect data
if let Some(ref on_connect) = this.on_connect {
on_connect.set(&mut req.extensions_mut());
}
// merge on_connect_ext data into request extensions
req.extensions_mut().drain_from(this.on_connect_data);
@ -1046,7 +1034,6 @@ mod tests {
CloneableService::new(ok_service()),
CloneableService::new(ExpectHandler),
None,
None,
Extensions::new(),
None,
);
@ -1087,7 +1074,6 @@ mod tests {
CloneableService::new(echo_path_service()),
CloneableService::new(ExpectHandler),
None,
None,
Extensions::new(),
None,
);
@ -1142,7 +1128,6 @@ mod tests {
CloneableService::new(echo_path_service()),
CloneableService::new(ExpectHandler),
None,
None,
Extensions::new(),
None,
);
@ -1192,7 +1177,6 @@ mod tests {
CloneableService::new(echo_payload_service()),
CloneableService::new(ExpectHandler),
None,
None,
Extensions::new(),
None,
);
@ -1264,7 +1248,6 @@ mod tests {
CloneableService::new(echo_path_service()),
CloneableService::new(ExpectHandler),
None,
None,
Extensions::new(),
None,
);
@ -1324,7 +1307,6 @@ mod tests {
CloneableService::new(ok_service()),
CloneableService::new(ExpectHandler),
Some(CloneableService::new(UpgradeHandler(PhantomData))),
None,
Extensions::new(),
None,
);

View File

@ -15,7 +15,6 @@ use crate::body::MessageBody;
use crate::cloneable::CloneableService;
use crate::config::ServiceConfig;
use crate::error::{DispatchError, Error};
use crate::helpers::DataFactory;
use crate::request::Request;
use crate::response::Response;
use crate::{ConnectCallback, Extensions};
@ -30,7 +29,6 @@ pub struct H1Service<T, S, B, X = ExpectHandler, U = UpgradeHandler> {
cfg: ServiceConfig,
expect: X,
upgrade: Option<U>,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<B>,
}
@ -53,7 +51,6 @@ where
srv: service.into_factory(),
expect: ExpectHandler,
upgrade: None,
on_connect: None,
on_connect_ext: None,
_t: PhantomData,
}
@ -213,7 +210,6 @@ where
cfg: self.cfg,
srv: self.srv,
upgrade: self.upgrade,
on_connect: self.on_connect,
on_connect_ext: self.on_connect_ext,
_t: PhantomData,
}
@ -230,21 +226,11 @@ where
cfg: self.cfg,
srv: self.srv,
expect: self.expect,
on_connect: self.on_connect,
on_connect_ext: self.on_connect_ext,
_t: PhantomData,
}
}
/// Set on connect callback.
pub(crate) fn on_connect(
mut self,
f: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
) -> Self {
self.on_connect = f;
self
}
/// Set on connect callback.
pub(crate) fn on_connect_ext(mut self, f: Option<Rc<ConnectCallback<T>>>) -> Self {
self.on_connect_ext = f;
@ -282,7 +268,6 @@ where
fut_upg: self.upgrade.as_ref().map(|f| f.new_service(())),
expect: None,
upgrade: None,
on_connect: self.on_connect.clone(),
on_connect_ext: self.on_connect_ext.clone(),
cfg: Some(self.cfg.clone()),
_t: PhantomData,
@ -312,7 +297,6 @@ where
fut_upg: Option<U::Future>,
expect: Option<X::Service>,
upgrade: Option<U::Service>,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
cfg: Option<ServiceConfig>,
_t: PhantomData<(T, B)>,
@ -369,7 +353,6 @@ where
service,
this.expect.take().unwrap(),
this.upgrade.take(),
this.on_connect.clone(),
this.on_connect_ext.clone(),
)
}))
@ -386,7 +369,6 @@ where
srv: CloneableService<S>,
expect: CloneableService<X>,
upgrade: Option<CloneableService<U>>,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
cfg: ServiceConfig,
_t: PhantomData<B>,
@ -408,7 +390,6 @@ where
srv: S,
expect: X,
upgrade: Option<U>,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
) -> H1ServiceHandler<T, S, B, X, U> {
H1ServiceHandler {
@ -416,7 +397,6 @@ where
expect: CloneableService::new(expect),
upgrade: upgrade.map(CloneableService::new),
cfg,
on_connect,
on_connect_ext,
_t: PhantomData,
}
@ -483,8 +463,6 @@ where
}
fn call(&mut self, (io, addr): (T, Option<net::SocketAddr>)) -> Self::Future {
let deprecated_on_connect = self.on_connect.as_ref().map(|handler| handler(&io));
let mut connect_extensions = Extensions::new();
if let Some(ref handler) = self.on_connect_ext {
// run on_connect_ext callback, populating connect extensions
@ -497,7 +475,6 @@ where
self.srv.clone(),
self.expect.clone(),
self.upgrade.clone(),
deprecated_on_connect,
connect_extensions,
addr,
)

View File

@ -18,7 +18,6 @@ use crate::body::{BodySize, MessageBody, ResponseBody};
use crate::cloneable::CloneableService;
use crate::config::ServiceConfig;
use crate::error::{DispatchError, Error};
use crate::helpers::DataFactory;
use crate::httpmessage::HttpMessage;
use crate::message::ResponseHead;
use crate::payload::Payload;
@ -38,7 +37,6 @@ where
{
service: CloneableService<S>,
connection: Connection<T, Bytes>,
on_connect: Option<Box<dyn DataFactory>>,
on_connect_data: Extensions,
config: ServiceConfig,
peer_addr: Option<net::SocketAddr>,
@ -59,7 +57,6 @@ where
pub(crate) fn new(
service: CloneableService<S>,
connection: Connection<T, Bytes>,
on_connect: Option<Box<dyn DataFactory>>,
on_connect_data: Extensions,
config: ServiceConfig,
timeout: Option<Sleep>,
@ -86,7 +83,6 @@ where
config,
peer_addr,
connection,
on_connect,
on_connect_data,
ka_expire,
ka_timer,
@ -136,12 +132,6 @@ where
head.headers = parts.headers.into();
head.peer_addr = this.peer_addr;
// DEPRECATED
// set on_connect data
if let Some(ref on_connect) = this.on_connect {
on_connect.set(&mut req.extensions_mut());
}
// merge on_connect_ext data into request extensions
req.extensions_mut().drain_from(&mut this.on_connect_data);

View File

@ -20,7 +20,6 @@ use crate::body::MessageBody;
use crate::cloneable::CloneableService;
use crate::config::ServiceConfig;
use crate::error::{DispatchError, Error};
use crate::helpers::DataFactory;
use crate::request::Request;
use crate::response::Response;
use crate::{ConnectCallback, Extensions};
@ -31,7 +30,6 @@ use super::dispatcher::Dispatcher;
pub struct H2Service<T, S, B> {
srv: S,
cfg: ServiceConfig,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<(T, B)>,
}
@ -51,23 +49,12 @@ where
) -> Self {
H2Service {
cfg,
on_connect: None,
on_connect_ext: None,
srv: service.into_factory(),
_t: PhantomData,
}
}
/// Set on connect callback.
pub(crate) fn on_connect(
mut self,
f: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
) -> Self {
self.on_connect = f;
self
}
/// Set on connect callback.
pub(crate) fn on_connect_ext(mut self, f: Option<Rc<ConnectCallback<T>>>) -> Self {
self.on_connect_ext = f;
@ -212,7 +199,6 @@ where
H2ServiceResponse {
fut: self.srv.new_service(()),
cfg: Some(self.cfg.clone()),
on_connect: self.on_connect.clone(),
on_connect_ext: self.on_connect_ext.clone(),
_t: PhantomData,
}
@ -228,7 +214,6 @@ where
#[pin]
fut: S::Future,
cfg: Option<ServiceConfig>,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<B>,
}
@ -251,7 +236,6 @@ where
let this = self.as_mut().project();
H2ServiceHandler::new(
this.cfg.take().unwrap(),
this.on_connect.clone(),
this.on_connect_ext.clone(),
service,
)
@ -266,7 +250,6 @@ where
{
srv: CloneableService<S>,
cfg: ServiceConfig,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<B>,
}
@ -281,13 +264,11 @@ where
{
fn new(
cfg: ServiceConfig,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
srv: S,
) -> H2ServiceHandler<T, S, B> {
H2ServiceHandler {
cfg,
on_connect,
on_connect_ext,
srv: CloneableService::new(srv),
_t: PhantomData,
@ -317,8 +298,6 @@ where
}
fn call(&mut self, (io, addr): (T, Option<net::SocketAddr>)) -> Self::Future {
let deprecated_on_connect = self.on_connect.as_ref().map(|handler| handler(&io));
let mut connect_extensions = Extensions::new();
if let Some(ref handler) = self.on_connect_ext {
// run on_connect_ext callback, populating connect extensions
@ -330,7 +309,6 @@ where
Some(self.srv.clone()),
Some(self.cfg.clone()),
addr,
deprecated_on_connect,
Some(connect_extensions),
server::handshake(io),
),
@ -348,7 +326,6 @@ where
Option<CloneableService<S>>,
Option<ServiceConfig>,
Option<net::SocketAddr>,
Option<Box<dyn DataFactory>>,
Option<Extensions>,
Handshake<T, Bytes>,
),
@ -384,7 +361,6 @@ where
ref mut srv,
ref mut config,
ref peer_addr,
ref mut on_connect,
ref mut on_connect_data,
ref mut handshake,
) => match Pin::new(handshake).poll(cx) {
@ -392,7 +368,6 @@ where
self.state = State::Incoming(Dispatcher::new(
srv.take().unwrap(),
conn,
on_connect.take(),
on_connect_data.take().unwrap(),
config.take().unwrap(),
None,

View File

@ -318,9 +318,8 @@ impl ContentDisposition {
return Err(crate::error::ParseError::Header);
}
left = new_left;
if param_name.ends_with('*') {
if let Some(param_name) = param_name.strip_suffix('*') {
// extended parameters
let param_name = &param_name[..param_name.len() - 1]; // trim asterisk
let (ext_value, new_left) = split_once_and_trim(left, ';');
left = new_left;
let ext_value = header::parse_extended_value(ext_value)?;

View File

@ -3,8 +3,6 @@ use std::io;
use bytes::{BufMut, BytesMut};
use http::Version;
use crate::extensions::Extensions;
const DIGITS_START: u8 = b'0';
pub(crate) fn write_status_line(version: Version, n: u16, bytes: &mut BytesMut) {
@ -56,18 +54,6 @@ impl<'a> io::Write for Writer<'a> {
}
}
pub(crate) trait DataFactory {
fn set(&self, ext: &mut Extensions);
}
pub(crate) struct Data<T>(pub(crate) T);
impl<T: Clone + 'static> DataFactory for Data<T> {
fn set(&self, ext: &mut Extensions) {
ext.insert(self.0.clone())
}
}
#[cfg(test)]
mod tests {
use std::str::from_utf8;

View File

@ -7,7 +7,6 @@
clippy::new_without_default,
clippy::borrow_interior_mutable_const
)]
#![allow(clippy::manual_strip)] // Allow this to keep MSRV(1.42).
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]

View File

@ -17,7 +17,6 @@ use crate::builder::HttpServiceBuilder;
use crate::cloneable::CloneableService;
use crate::config::{KeepAlive, ServiceConfig};
use crate::error::{DispatchError, Error};
use crate::helpers::DataFactory;
use crate::request::Request;
use crate::response::Response;
use crate::{h1, h2::Dispatcher, ConnectCallback, Extensions, Protocol};
@ -28,8 +27,6 @@ pub struct HttpService<T, S, B, X = h1::ExpectHandler, U = h1::UpgradeHandler> {
cfg: ServiceConfig,
expect: X,
upgrade: Option<U>,
// DEPRECATED: in favor of on_connect_ext
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<B>,
}
@ -67,7 +64,6 @@ where
srv: service.into_factory(),
expect: h1::ExpectHandler,
upgrade: None,
on_connect: None,
on_connect_ext: None,
_t: PhantomData,
}
@ -83,7 +79,6 @@ where
srv: service.into_factory(),
expect: h1::ExpectHandler,
upgrade: None,
on_connect: None,
on_connect_ext: None,
_t: PhantomData,
}
@ -116,7 +111,6 @@ where
cfg: self.cfg,
srv: self.srv,
upgrade: self.upgrade,
on_connect: self.on_connect,
on_connect_ext: self.on_connect_ext,
_t: PhantomData,
}
@ -138,21 +132,11 @@ where
cfg: self.cfg,
srv: self.srv,
expect: self.expect,
on_connect: self.on_connect,
on_connect_ext: self.on_connect_ext,
_t: PhantomData,
}
}
/// Set on connect callback.
pub(crate) fn on_connect(
mut self,
f: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
) -> Self {
self.on_connect = f;
self
}
/// Set connect callback with mutable access to request data container.
pub(crate) fn on_connect_ext(mut self, f: Option<Rc<ConnectCallback<T>>>) -> Self {
self.on_connect_ext = f;
@ -362,7 +346,6 @@ where
fut_upg: self.upgrade.as_ref().map(|f| f.new_service(())),
expect: None,
upgrade: None,
on_connect: self.on_connect.clone(),
on_connect_ext: self.on_connect_ext.clone(),
cfg: self.cfg.clone(),
_t: PhantomData,
@ -386,7 +369,6 @@ where
fut_upg: Option<U::Future>,
expect: Option<X::Service>,
upgrade: Option<U::Service>,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
cfg: ServiceConfig,
_t: PhantomData<(T, B)>,
@ -446,7 +428,6 @@ where
service,
this.expect.take().unwrap(),
this.upgrade.take(),
this.on_connect.clone(),
this.on_connect_ext.clone(),
)
}))
@ -464,7 +445,6 @@ where
expect: CloneableService<X>,
upgrade: Option<CloneableService<U>>,
cfg: ServiceConfig,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
_t: PhantomData<B>,
}
@ -486,12 +466,10 @@ where
srv: S,
expect: X,
upgrade: Option<U>,
on_connect: Option<Rc<dyn Fn(&T) -> Box<dyn DataFactory>>>,
on_connect_ext: Option<Rc<ConnectCallback<T>>>,
) -> HttpServiceHandler<T, S, B, X, U> {
HttpServiceHandler {
cfg,
on_connect,
on_connect_ext,
srv: CloneableService::new(srv),
expect: CloneableService::new(expect),
@ -567,7 +545,6 @@ where
) -> Self::Future {
let mut connect_extensions = Extensions::new();
let deprecated_on_connect = self.on_connect.as_ref().map(|handler| handler(&io));
if let Some(ref handler) = self.on_connect_ext {
handler(&io, &mut connect_extensions);
}
@ -578,7 +555,6 @@ where
server::handshake(io),
self.cfg.clone(),
self.srv.clone(),
deprecated_on_connect,
connect_extensions,
peer_addr,
))),
@ -591,7 +567,6 @@ where
self.srv.clone(),
self.expect.clone(),
self.upgrade.clone(),
deprecated_on_connect,
connect_extensions,
peer_addr,
)),
@ -620,7 +595,6 @@ where
Handshake<T, Bytes>,
ServiceConfig,
CloneableService<S>,
Option<Box<dyn DataFactory>>,
Extensions,
Option<net::SocketAddr>,
)>,
@ -697,12 +671,10 @@ where
} else {
panic!()
};
let (_, cfg, srv, on_connect, on_connect_data, peer_addr) =
data.take().unwrap();
let (_, cfg, srv, on_connect_data, peer_addr) = data.take().unwrap();
self.set(State::H2(Dispatcher::new(
srv,
conn,
on_connect,
on_connect_data,
cfg,
None,

View File

@ -410,10 +410,8 @@ async fn test_h2_service_error() {
async fn test_h2_on_connect() {
let srv = test_server(move || {
HttpService::build()
.on_connect(|_| 10usize)
.on_connect_ext(|_, data| data.insert(20isize))
.h2(|req: Request| {
assert!(req.extensions().contains::<usize>());
assert!(req.extensions().contains::<isize>());
ok::<_, ()>(Response::Ok().finish())
})

View File

@ -662,10 +662,8 @@ async fn test_h1_service_error() {
async fn test_h1_on_connect() {
let srv = test_server(|| {
HttpService::build()
.on_connect(|_| 10usize)
.on_connect_ext(|_, data| data.insert(20isize))
.h1(|req: Request| {
assert!(req.extensions().contains::<usize>());
assert!(req.extensions().contains::<isize>());
future::ok::<_, ()>(Response::Ok().finish())
})

View File

@ -4,7 +4,7 @@
[![crates.io](https://meritbadge.herokuapp.com/actix-web-codegen)](https://crates.io/crates/actix-web-codegen)
[![Documentation](https://docs.rs/actix-web-codegen/badge.svg)](https://docs.rs/actix-web-codegen/0.4.0/actix_web_codegen/)
[![Version](https://img.shields.io/badge/rustc-1.42+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html)
[![Version](https://img.shields.io/badge/rustc-1.46+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
[![Build Status](https://travis-ci.org/actix/actix-web.svg?branch=master)](https://travis-ci.org/actix/actix-web)
[![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web)
[![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@ -14,7 +14,7 @@
- [API Documentation](https://docs.rs/actix-web-codegen)
- [Chat on Gitter](https://gitter.im/actix/actix-web)
- Cargo package: [actix-web-codegen](https://crates.io/crates/actix-web-codegen)
- Minimum supported Rust version: 1.42 or later.
- Minimum supported Rust version: 1.46 or later.
## Compile Testing
Uses the [`trybuild`] crate. All compile fail tests should include a stderr file generated by `trybuild`. See the [workflow section](https://github.com/dtolnay/trybuild#workflow) of the trybuild docs for info on how to do this.

View File

@ -6,31 +6,15 @@ fn compile_macros() {
t.compile_fail("tests/trybuild/simple-fail.rs");
t.pass("tests/trybuild/route-ok.rs");
test_route_duplicate_unexpected_method(&t);
test_route_missing_method(&t)
}
#[rustversion::stable(1.42)]
fn test_route_missing_method(t: &trybuild::TestCases) {
t.compile_fail("tests/trybuild/route-missing-method-fail-msrv.rs");
}
#[rustversion::not(stable(1.42))]
#[rustversion::not(nightly)]
fn test_route_missing_method(t: &trybuild::TestCases) {
t.compile_fail("tests/trybuild/route-missing-method-fail.rs");
}
#[rustversion::nightly]
fn test_route_missing_method(_t: &trybuild::TestCases) {}
// FIXME: Re-test them on nightly once rust-lang/rust#77993 is fixed.
#[rustversion::not(nightly)]
fn test_route_duplicate_unexpected_method(t: &trybuild::TestCases) {
t.compile_fail("tests/trybuild/route-duplicate-method-fail.rs");
t.compile_fail("tests/trybuild/route-unexpected-method-fail.rs");
}
#[rustversion::nightly]
fn test_route_duplicate_unexpected_method(_t: &trybuild::TestCases) {}
// #[rustversion::not(nightly)]
// fn skip_on_nightly(t: &trybuild::TestCases) {
//
// }
// #[rustversion::nightly]
// fn skip_on_nightly(_t: &trybuild::TestCases) {}

View File

@ -1 +0,0 @@
route-missing-method-fail.rs

View File

@ -1,11 +0,0 @@
error: The #[route(..)] macro requires at least one `method` attribute
--> $DIR/route-missing-method-fail-msrv.rs:3:1
|
3 | #[route("/")]
| ^^^^^^^^^^^^^
error[E0425]: cannot find value `index` in this scope
--> $DIR/route-missing-method-fail-msrv.rs:12:49
|
12 | let srv = test::start(|| App::new().service(index));
| ^^^^^ not found in this scope

View File

@ -13,7 +13,7 @@
- [API Documentation](https://docs.rs/awc)
- [Example Project](https://github.com/actix/examples/tree/HEAD/awc_https)
- [Chat on Gitter](https://gitter.im/actix/actix-web)
- Minimum Supported Rust Version (MSRV): 1.42.0
- Minimum Supported Rust Version (MSRV): 1.46.0
## Example
```rust

View File

@ -2,12 +2,10 @@ digraph {
subgraph cluster_net {
label="actix/actix-net";
"actix-codec"
"actix-connect"
"actix-macros"
"actix-rt"
"actix-server"
"actix-service"
"actix-testing"
"actix-threadpool"
"actix-tls"
"actix-tracing"
@ -17,9 +15,7 @@ digraph {
"actix-utils" -> { "actix-service" "actix-rt" "actix-codec" }
"actix-tracing" -> { "actix-service" }
"actix-tls" -> { "actix-service" "actix-codec" "actix-utils" }
"actix-testing" -> { "actix-rt" "actix-macros" "actix-server" "actix-service" }
"actix-tls" -> { "actix-service" "actix-codec" "actix-utils" "actix-rt" }
"actix-server" -> { "actix-service" "actix-rt" "actix-codec" "actix-utils" }
"actix-rt" -> { "actix-macros" "actix-threadpool" }
"actix-connect" -> { "actix-service" "actix-codec" "actix-utils" "actix-rt" }
}

View File

@ -2,31 +2,29 @@ digraph {
subgraph cluster_web {
label="actix/actix-web"
"awc"
"web"
"files"
"http"
"multipart"
"web-actors"
"codegen"
"http-test"
"actix-web"
"actix-files"
"actix-http"
"actix-multipart"
"actix-web-actors"
"actix-web-codegen"
"actix-http-test"
}
"web" -> { "codec" "service" "utils" "router" "rt" "server" "testing" "macros" "threadpool" "tls" "codegen" "http" "awc" }
"awc" -> { "codec" "service" "http" "rt" }
"web-actors" -> { "actix" "web" "http" "codec" }
"multipart" -> { "web" "service" "utils" }
"http" -> { "service" "codec" "connect" "utils" "rt" "threadpool" }
"http" -> { "actix" "tls" }[color=blue] // optional
"files" -> { "web" }
"http-test" -> { "service" "codec" "connect" "utils" "rt" "server" "testing" "awc" }
"actix-web" -> { "actix-codec" "actix-service" "actix-utils" "actix-router" "actix-rt" "actix-server" "macros" "threadpool" "actix-tls" "actix-web-codegen" "actix-http" "awc" }
"awc" -> { "actix-codec" "actix-service" "actix-http" "actix-rt" }
"actix-web-actors" -> { "actix" "actix-web" "actix-http" "actix-codec" }
"actix-multipart" -> { "actix-web" "actix-service" "actix-utils" }
"actix-http" -> { "actix-service" "actix-codec" "actix-tls" "actix-utils" "actix-rt" "threadpool" }
"actix-http" -> { "actix" "actix-tls" }[color=blue] // optional
"actix-files" -> { "actix-web" }
"actix-http-test" -> { "actix-service" "actix-codec" "actix-tls" "actix-utils" "actix-rt" "actix-server" "awc" }
// net
"utils" -> { "service" "rt" "codec" }
"tracing" -> { "service" }
"tls" -> { "service" "codec" "utils" }
"testing" -> { "rt" "macros" "server" "service" }
"server" -> { "service" "rt" "codec" "utils" }
"rt" -> { "macros" "threadpool" }
"connect" -> { "service" "codec" "utils" "rt" }
"actix-utils" -> { "actix-service" "actix-rt" "actix-codec" }
"actix-tracing" -> { "actix-service" }
"actix-tls" -> { "actix-service" "actix-codec" "actix-utils" }
"actix-server" -> { "actix-service" "actix-rt" "actix-codec" "actix-utils" }
"actix-rt" -> { "macros" "threadpool" }
}

View File

@ -56,7 +56,7 @@
//! * Middlewares ([Logger, Session, CORS, etc](https://actix.rs/docs/middleware/))
//! * Includes an async [HTTP client](https://actix.rs/actix-web/actix_web/client/index.html)
//! * Supports [Actix actor framework](https://github.com/actix/actix)
//! * Runs on stable Rust 1.42+
//! * Runs on stable Rust 1.46+
//!
//! ## Crate Features
//!
@ -65,7 +65,7 @@
//! * `rustls` - HTTPS support via `rustls` crate, supports `HTTP/2`
//! * `secure-cookies` - secure cookies support
#![deny(rust_2018_idioms)]
#![deny(rust_2018_idioms, nonstandard_style)]
#![allow(clippy::needless_doctest_main, clippy::type_complexity)]
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]

View File

@ -177,6 +177,7 @@ mod tests {
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
}
#[allow(clippy::unnecessary_wraps)]
fn render_500_async<B: 'static>(
mut res: ServiceResponse<B>,
) -> Result<ErrorHandlerResponse<B>> {

View File

@ -66,6 +66,7 @@ async fn test_start() {
let _ = sys.stop();
}
#[allow(clippy::unnecessary_wraps)]
#[cfg(feature = "openssl")]
fn ssl_acceptor() -> std::io::Result<SslAcceptorBuilder> {
use open_ssl::ssl::{SslAcceptor, SslFiletype, SslMethod};