diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
new file mode 100644
index 000000000..875ce10b4
--- /dev/null
+++ b/.github/workflows/linux.yml
@@ -0,0 +1,90 @@
+name: CI (Linux)
+
+on: [push, pull_request]
+
+jobs:
+ build_and_test:
+ strategy:
+ fail-fast: false
+ matrix:
+ version:
+ - 1.39.0 # MSRV
+ - stable
+ - nightly
+
+ name: ${{ matrix.version }} - x86_64-unknown-linux-gnu
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@master
+
+ - name: Install ${{ matrix.version }}
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: ${{ matrix.version }}-x86_64-unknown-linux-gnu
+ profile: minimal
+ override: true
+
+ - name: Generate Cargo.lock
+ uses: actions-rs/cargo@v1
+ with:
+ command: generate-lockfile
+ - name: Cache cargo registry
+ uses: actions/cache@v1
+ with:
+ path: ~/.cargo/registry
+ key: ${{ matrix.version }}-x86_64-unknown-linux-gnu-cargo-registry-trimmed-${{ hashFiles('**/Cargo.lock') }}
+ - name: Cache cargo index
+ uses: actions/cache@v1
+ with:
+ path: ~/.cargo/git
+ key: ${{ matrix.version }}-x86_64-unknown-linux-gnu-cargo-index-trimmed-${{ hashFiles('**/Cargo.lock') }}
+ - name: Cache cargo build
+ uses: actions/cache@v1
+ with:
+ path: target
+ key: ${{ matrix.version }}-x86_64-unknown-linux-gnu-cargo-build-trimmed-${{ hashFiles('**/Cargo.lock') }}
+
+ - name: check build
+ uses: actions-rs/cargo@v1
+ with:
+ command: check
+ args: --all --bins --examples --tests
+
+ - name: tests
+ uses: actions-rs/cargo@v1
+ timeout-minutes: 40
+ with:
+ command: test
+ args: --all --all-features --no-fail-fast -- --nocapture
+
+ - name: tests (actix-http)
+ uses: actions-rs/cargo@v1
+ timeout-minutes: 40
+ with:
+ command: test
+ args: --package=actix-http --no-default-features --features=rustls -- --nocapture
+
+ - name: tests (awc)
+ uses: actions-rs/cargo@v1
+ timeout-minutes: 40
+ with:
+ command: test
+ args: --package=awc --no-default-features --features=rustls -- --nocapture
+
+ - name: Generate coverage file
+ if: matrix.version == 'stable' && (github.ref == 'master' || github.event_name == 'pull_request')
+ run: |
+ cargo install cargo-tarpaulin
+ cargo tarpaulin --out Xml
+ - name: Upload to Codecov
+ if: matrix.version == 'stable' && (github.ref == 'master' || github.event_name == 'pull_request')
+ uses: codecov/codecov-action@v1
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ file: cobertura.xml
+
+ - name: Clear the cargo caches
+ run: |
+ cargo install cargo-cache --no-default-features --features ci-autoclean
+ cargo-cache
diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml
new file mode 100644
index 000000000..388ae3704
--- /dev/null
+++ b/.github/workflows/upload-doc.yml
@@ -0,0 +1,35 @@
+name: Upload documentation
+
+on:
+ push:
+ branches:
+ - master
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: github.repository == 'actix/actix-web'
+
+ steps:
+ - uses: actions/checkout@master
+
+ - name: Install Rust
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: stable-x86_64-unknown-linux-gnu
+ profile: minimal
+ override: true
+
+ - name: check build
+ uses: actions-rs/cargo@v1
+ with:
+ command: doc
+ args: --no-deps --all-features
+
+ - name: Tweak HTML
+ run: echo "" > target/doc/index.html
+
+ - name: Upload documentation
+ run: |
+ git clone https://github.com/davisp/ghp-import.git
+ ./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -r https://${{ secrets.GITHUB_TOKEN }}@github.com/"${{ github.repository }}.git" target/doc
\ No newline at end of file
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 36b224ba6..5fd785fad 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -56,3 +56,4 @@ jobs:
--skip=test_slow_request
--skip=test_connection_force_close
--skip=test_connection_server_close
+ --skip=test_connection_wait_queue_force_close
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index f10f82a48..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,61 +0,0 @@
-language: rust
-sudo: required
-dist: trusty
-
-cache:
- # cargo: true
- apt: true
-
-matrix:
- include:
- - rust: stable
- - rust: beta
- - rust: nightly-2019-11-20
- allow_failures:
- - rust: nightly-2019-11-20
-
-env:
- global:
- # - RUSTFLAGS="-C link-dead-code"
- - OPENSSL_VERSION=openssl-1.0.2
-
-before_install:
- - sudo add-apt-repository -y ppa:0k53d-karl-f830m/openssl
- - sudo apt-get update -qq
- - sudo apt-get install -y openssl libssl-dev libelf-dev libdw-dev cmake gcc binutils-dev libiberty-dev
-
-before_cache: |
- if [[ "$TRAVIS_RUST_VERSION" == "nightly-2019-11-20" ]]; then
- RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install --version 0.6.11 cargo-tarpaulin
- fi
-
-# Add clippy
-before_script:
- - export PATH=$PATH:~/.cargo/bin
-
-script:
- - cargo update
- - cargo check --all --no-default-features
- - |
- if [[ "$TRAVIS_RUST_VERSION" == "stable" || "$TRAVIS_RUST_VERSION" == "beta" ]]; then
- cargo test --all-features --all -- --nocapture
- cd actix-http; cargo test --no-default-features --features="rustls" -- --nocapture; cd ..
- cd awc; cargo test --no-default-features --features="rustls" -- --nocapture; cd ..
- fi
-
-# Upload docs
-after_success:
- - |
- if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then
- cargo doc --no-deps --all-features &&
- echo "" > target/doc/index.html &&
- git clone https://github.com/davisp/ghp-import.git &&
- ./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -r https://"$GH_TOKEN"@github.com/"$TRAVIS_REPO_SLUG.git" target/doc &&
- echo "Uploaded documentation"
- fi
- - |
- if [[ "$TRAVIS_RUST_VERSION" == "nightly-2019-11-20" ]]; then
- taskset -c 0 cargo tarpaulin --out Xml --all --all-features
- bash <(curl -s https://codecov.io/bash)
- echo "Uploaded code coverage"
- fi
diff --git a/actix-files/src/error.rs b/actix-files/src/error.rs
index 49a46e58d..9b30cbaa2 100644
--- a/actix-files/src/error.rs
+++ b/actix-files/src/error.rs
@@ -5,6 +5,7 @@ use derive_more::Display;
#[derive(Display, Debug, PartialEq)]
pub enum FilesError {
/// Path is not a directory
+ #[allow(dead_code)]
#[display(fmt = "Path is not a directory. Unable to serve static files")]
IsNotDirectory,
diff --git a/actix-http/src/extensions.rs b/actix-http/src/extensions.rs
index d85ca184d..5114ce140 100644
--- a/actix-http/src/extensions.rs
+++ b/actix-http/src/extensions.rs
@@ -28,33 +28,30 @@ impl Extensions {
/// Check if container contains entry
pub fn contains(&self) -> bool {
- self.map.get(&TypeId::of::()).is_some()
+ self.map.contains_key(&TypeId::of::())
}
/// Get a reference to a type previously inserted on this `Extensions`.
pub fn get(&self) -> Option<&T> {
self.map
.get(&TypeId::of::())
- .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref())
+ .and_then(|boxed| boxed.downcast_ref())
}
/// Get a mutable reference to a type previously inserted on this `Extensions`.
pub fn get_mut(&mut self) -> Option<&mut T> {
self.map
.get_mut(&TypeId::of::())
- .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut())
+ .and_then(|boxed| boxed.downcast_mut())
}
/// Remove a type from this `Extensions`.
///
/// If a extension of this type existed, it will be returned.
pub fn remove(&mut self) -> Option {
- self.map.remove(&TypeId::of::()).and_then(|boxed| {
- (boxed as Box)
- .downcast()
- .ok()
- .map(|boxed| *boxed)
- })
+ self.map
+ .remove(&TypeId::of::())
+ .and_then(|boxed| boxed.downcast().ok().map(|boxed| *boxed))
}
/// Clear the `Extensions` of all inserted extensions.
@@ -70,6 +67,92 @@ impl fmt::Debug for Extensions {
}
}
+#[test]
+fn test_remove() {
+ let mut map = Extensions::new();
+
+ map.insert::(123);
+ assert!(map.get::().is_some());
+
+ map.remove::();
+ assert!(map.get::().is_none());
+}
+
+#[test]
+fn test_clear() {
+ let mut map = Extensions::new();
+
+ map.insert::(8);
+ map.insert::(16);
+ map.insert::(32);
+
+ assert!(map.contains::());
+ assert!(map.contains::());
+ assert!(map.contains::());
+
+ map.clear();
+
+ assert!(!map.contains::());
+ assert!(!map.contains::());
+ assert!(!map.contains::());
+
+ map.insert::(10);
+ assert_eq!(*map.get::().unwrap(), 10);
+}
+
+#[test]
+fn test_integers() {
+ let mut map = Extensions::new();
+
+ map.insert::(8);
+ map.insert::(16);
+ map.insert::(32);
+ map.insert::(64);
+ map.insert::(128);
+ map.insert::(8);
+ map.insert::(16);
+ map.insert::(32);
+ map.insert::(64);
+ map.insert::(128);
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+ assert!(map.get::().is_some());
+}
+
+#[test]
+fn test_composition() {
+ struct Magi(pub T);
+
+ struct Madoka {
+ pub god: bool,
+ }
+
+ struct Homura {
+ pub attempts: usize,
+ }
+
+ struct Mami {
+ pub guns: usize,
+ }
+
+ let mut map = Extensions::new();
+
+ map.insert(Magi(Madoka { god: false }));
+ map.insert(Magi(Homura { attempts: 0 }));
+ map.insert(Magi(Mami { guns: 999 }));
+
+ assert!(!map.get::>().unwrap().0.god);
+ assert_eq!(0, map.get::>().unwrap().0.attempts);
+ assert_eq!(999, map.get::>().unwrap().0.guns);
+}
+
#[test]
fn test_extensions() {
#[derive(Debug, PartialEq)]
diff --git a/awc/tests/test_rustls_client.rs b/awc/tests/test_rustls_client.rs
index 1d7eb7bc5..8863dfcbe 100644
--- a/awc/tests/test_rustls_client.rs
+++ b/awc/tests/test_rustls_client.rs
@@ -11,6 +11,7 @@ use futures::future::ok;
use open_ssl::ssl::{SslAcceptor, SslFiletype, SslMethod, SslVerifyMode};
use rust_tls::ClientConfig;
+#[allow(unused)]
fn ssl_acceptor() -> SslAcceptor {
// load ssl keys
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
diff --git a/examples/uds.rs b/examples/uds.rs
index 77f245d99..06aa87f4d 100644
--- a/examples/uds.rs
+++ b/examples/uds.rs
@@ -1,6 +1,6 @@
-use actix_web::{
- get, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer,
-};
+use actix_web::{get, web, HttpRequest};
+#[cfg(unix)]
+use actix_web::{middleware, App, Error, HttpResponse, HttpServer};
#[get("/resource1/{name}/index.html")]
async fn index(req: HttpRequest, name: web::Path) -> String {
@@ -8,6 +8,7 @@ async fn index(req: HttpRequest, name: web::Path) -> String {
format!("Hello: {}!\r\n", name)
}
+#[cfg(unix)]
async fn index_async(req: HttpRequest) -> Result<&'static str, Error> {
println!("REQ: {:?}", req);
Ok("Hello world!\r\n")