mirror of
https://github.com/actix/actix-extras.git
synced 2025-02-22 18:33:18 +01:00
Merge branch 'master' into master
This commit is contained in:
commit
9da8d57ff2
40
.github/workflows/ci-post-merge.yml
vendored
40
.github/workflows/ci-post-merge.yml
vendored
@ -42,7 +42,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
command: generate-lockfile
|
command: generate-lockfile
|
||||||
- name: Cache Dependencies
|
- name: Cache Dependencies
|
||||||
uses: Swatinem/rust-cache@v1.2.0
|
uses: Swatinem/rust-cache@v2.1.0
|
||||||
|
|
||||||
- name: check minimal
|
- name: check minimal
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
@ -72,7 +72,11 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
target:
|
target:
|
||||||
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
||||||
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
|
- {
|
||||||
|
name: Windows,
|
||||||
|
os: windows-latest,
|
||||||
|
triple: x86_64-pc-windows-msvc,
|
||||||
|
}
|
||||||
version:
|
version:
|
||||||
- nightly
|
- nightly
|
||||||
|
|
||||||
@ -83,44 +87,30 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install ${{ matrix.version }}
|
- name: Install ${{ matrix.version }}
|
||||||
uses: actions-rs/toolchain@v1
|
run: |
|
||||||
with:
|
rustup install ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||||
toolchain: ${{ matrix.version }}-${{ matrix.target.triple }}
|
rustup override set ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Install cargo-hack
|
- name: Install cargo-hack
|
||||||
uses: taiki-e/install-action@cargo-hack
|
uses: taiki-e/install-action@cargo-hack
|
||||||
|
|
||||||
- name: Generate Cargo.lock
|
- name: Generate Cargo.lock
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo generate-lockfile
|
||||||
with:
|
|
||||||
command: generate-lockfile
|
|
||||||
- name: Cache Dependencies
|
- name: Cache Dependencies
|
||||||
uses: Swatinem/rust-cache@v1.2.0
|
uses: Swatinem/rust-cache@v2.1.0
|
||||||
|
|
||||||
- name: check minimal
|
- name: check minimal
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-min
|
||||||
with: { command: ci-min }
|
|
||||||
|
|
||||||
- name: check minimal + examples
|
- name: check minimal + examples
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-check-min-examples
|
||||||
with: { command: ci-check-min-examples }
|
|
||||||
|
|
||||||
- name: check default
|
- name: check default
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-check
|
||||||
with: { command: ci-check }
|
|
||||||
|
|
||||||
- name: tests
|
- name: tests
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
timeout-minutes: 40
|
timeout-minutes: 40
|
||||||
with:
|
run: cargo ci-test --exclude=actix-redis --exclude=actix-session --exclude=actix-limitation -- --nocapture
|
||||||
command: ci-test
|
|
||||||
args: >-
|
|
||||||
--exclude=actix-redis
|
|
||||||
--exclude=actix-session
|
|
||||||
--exclude=actix-limitation
|
|
||||||
-- --nocapture
|
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: Clear the cargo caches
|
||||||
run: |
|
run: |
|
||||||
|
81
.github/workflows/ci.yml
vendored
81
.github/workflows/ci.yml
vendored
@ -36,38 +36,30 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install ${{ matrix.version }}
|
- name: Install ${{ matrix.version }}
|
||||||
uses: actions-rs/toolchain@v1
|
run: |
|
||||||
with:
|
rustup install ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||||
toolchain: ${{ matrix.version }}-${{ matrix.target.triple }}
|
rustup override set ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Install cargo-hack
|
- name: Install cargo-hack
|
||||||
uses: taiki-e/install-action@cargo-hack
|
uses: taiki-e/install-action@cargo-hack
|
||||||
|
|
||||||
- name: Generate Cargo.lock
|
- name: Generate Cargo.lock
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo generate-lockfile
|
||||||
with:
|
|
||||||
command: generate-lockfile
|
|
||||||
- name: Cache Dependencies
|
- name: Cache Dependencies
|
||||||
uses: Swatinem/rust-cache@v1.2.0
|
uses: Swatinem/rust-cache@v2.1.0
|
||||||
|
|
||||||
- name: check minimal
|
- name: check minimal
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-min
|
||||||
with: { command: ci-min }
|
|
||||||
|
|
||||||
- name: check minimal + examples
|
- name: check minimal + examples
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-check-min-examples
|
||||||
with: { command: ci-check-min-examples }
|
|
||||||
|
|
||||||
- name: check default
|
- name: check default
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-check
|
||||||
with: { command: ci-check }
|
|
||||||
|
|
||||||
- name: tests
|
- name: tests
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
timeout-minutes: 40
|
timeout-minutes: 40
|
||||||
with: { command: ci-test }
|
run: cargo ci-test
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: Clear the cargo caches
|
||||||
run: |
|
run: |
|
||||||
@ -80,7 +72,11 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
target:
|
target:
|
||||||
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
||||||
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
|
- {
|
||||||
|
name: Windows,
|
||||||
|
os: windows-latest,
|
||||||
|
triple: x86_64-pc-windows-msvc,
|
||||||
|
}
|
||||||
version:
|
version:
|
||||||
- 1.59 # MSRV
|
- 1.59 # MSRV
|
||||||
- stable
|
- stable
|
||||||
@ -92,43 +88,30 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install ${{ matrix.version }}
|
- name: Install ${{ matrix.version }}
|
||||||
uses: actions-rs/toolchain@v1
|
run: |
|
||||||
with:
|
rustup install ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||||
toolchain: ${{ matrix.version }}-${{ matrix.target.triple }}
|
rustup override set ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Install cargo-hack
|
- name: Install cargo-hack
|
||||||
uses: taiki-e/install-action@cargo-hack
|
uses: taiki-e/install-action@cargo-hack
|
||||||
|
|
||||||
- name: Generate Cargo.lock
|
- name: Generate Cargo.lock
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo generate-lockfile
|
||||||
with:
|
|
||||||
command: generate-lockfile
|
|
||||||
- name: Cache Dependencies
|
- name: Cache Dependencies
|
||||||
uses: Swatinem/rust-cache@v1.2.0
|
uses: Swatinem/rust-cache@v2.1.0
|
||||||
|
|
||||||
- name: check minimal
|
- name: check minimal
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-min
|
||||||
with: { command: ci-min }
|
|
||||||
|
|
||||||
- name: check minimal + examples
|
- name: check minimal + examples
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-check-min-examples
|
||||||
with: { command: ci-check-min-examples }
|
|
||||||
|
|
||||||
- name: check default
|
- name: check default
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo ci-check
|
||||||
with: { command: ci-check }
|
|
||||||
|
|
||||||
- name: tests
|
- name: tests
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
timeout-minutes: 40
|
timeout-minutes: 40
|
||||||
with:
|
run: cargo ci-test --exclude=actix-redis --exclude=actix-session --exclude=actix-limitation
|
||||||
command: ci-test
|
|
||||||
args: >-
|
|
||||||
--exclude=actix-redis
|
|
||||||
--exclude=actix-session
|
|
||||||
--exclude=actix-limitation
|
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: Clear the cargo caches
|
||||||
run: |
|
run: |
|
||||||
@ -142,21 +125,15 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Rust (nightly)
|
- name: Install Rust (nightly)
|
||||||
uses: actions-rs/toolchain@v1
|
run: |
|
||||||
with:
|
rustup install nightly
|
||||||
toolchain: nightly-x86_64-unknown-linux-gnu
|
rustup override set nightly
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Generate Cargo.lock
|
- name: Generate Cargo.lock
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo generate-lockfile
|
||||||
with: { command: generate-lockfile }
|
|
||||||
- name: Cache Dependencies
|
- name: Cache Dependencies
|
||||||
uses: Swatinem/rust-cache@v1.3.0
|
uses: Swatinem/rust-cache@v2.1.0
|
||||||
|
|
||||||
- name: doc tests
|
- name: doc tests
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
timeout-minutes: 40
|
timeout-minutes: 40
|
||||||
with:
|
run: cargo ci-doctest -- --nocapture
|
||||||
command: ci-doctest
|
|
||||||
args: -- --nocapture
|
|
||||||
|
15
.github/workflows/coverage.yml
vendored
15
.github/workflows/coverage.yml
vendored
@ -21,22 +21,19 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install stable
|
- name: Install stable
|
||||||
uses: actions-rs/toolchain@v1
|
run: |
|
||||||
with:
|
rustup override set stable
|
||||||
toolchain: stable-x86_64-unknown-linux-gnu
|
rustup update stable
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Generate Cargo.lock
|
- name: Generate Cargo.lock
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo generate-lockfile
|
||||||
with: { command: generate-lockfile }
|
|
||||||
- name: Cache Dependencies
|
- name: Cache Dependencies
|
||||||
uses: Swatinem/rust-cache@v1.2.0
|
uses: Swatinem/rust-cache@v2.1.0
|
||||||
|
|
||||||
- name: Generate coverage file
|
- name: Generate coverage file
|
||||||
run: |
|
run: |
|
||||||
cargo install cargo-tarpaulin --vers "^0.13"
|
cargo install cargo-tarpaulin --vers "^0.13"
|
||||||
cargo tarpaulin --workspace --out Xml --verbose
|
cargo tarpaulin --workspace --out Xml --verbose
|
||||||
- name: Upload to Codecov
|
- name: Upload to Codecov
|
||||||
uses: codecov/codecov-action@v1
|
uses: codecov/codecov-action@v3
|
||||||
with: { file: cobertura.xml }
|
with: { file: cobertura.xml }
|
||||||
|
27
.github/workflows/lint.yml
vendored
27
.github/workflows/lint.yml
vendored
@ -11,15 +11,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
run: |
|
||||||
with:
|
rustup override set nightly
|
||||||
toolchain: nightly
|
rustup update nightly
|
||||||
components: rustfmt
|
rustup component add rustfmt
|
||||||
- name: Check with rustfmt
|
- name: Check with rustfmt
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo fmt --all -- --check
|
||||||
with:
|
|
||||||
command: fmt
|
|
||||||
args: --all -- --check
|
|
||||||
|
|
||||||
clippy:
|
clippy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -27,13 +24,9 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
run: |
|
||||||
with:
|
rustup override set stable
|
||||||
toolchain: stable
|
rustup update stable
|
||||||
components: clippy
|
rustup component add rustfmt
|
||||||
override: true
|
|
||||||
- name: Check with Clippy
|
- name: Check with Clippy
|
||||||
uses: actions-rs/clippy-check@v1
|
run: cargo clippy --workspace --tests --all-features
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
args: --workspace --tests --all-features
|
|
||||||
|
13
.github/workflows/upload-doc.yml
vendored
13
.github/workflows/upload-doc.yml
vendored
@ -12,17 +12,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: actions-rs/toolchain@v1
|
run: |
|
||||||
with:
|
rustup override set nightly
|
||||||
toolchain: nightly-x86_64-unknown-linux-gnu
|
rustup update nightly
|
||||||
profile: minimal
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Build Docs
|
- name: Build Docs
|
||||||
uses: actions-rs/cargo@v1
|
run: cargo doc --workspace --all-features --no-deps
|
||||||
with:
|
|
||||||
command: doc
|
|
||||||
args: --workspace --all-features --no-deps
|
|
||||||
|
|
||||||
- name: Tweak HTML
|
- name: Tweak HTML
|
||||||
run: echo '<meta http-equiv="refresh" content="0;url=actix_cors/index.html">' > target/doc/index.html
|
run: echo '<meta http-equiv="refresh" content="0;url=actix_cors/index.html">' > target/doc/index.html
|
||||||
|
@ -42,6 +42,7 @@ These crates are provided by the community.
|
|||||||
| [tracing-actix-web] | [][tracing-actix-web] [](https://deps.rs/crate/tracing-actix-web/0.6.0) | A middleware to collect telemetry data from applications built on top of the actix-web framework. |
|
| [tracing-actix-web] | [][tracing-actix-web] [](https://deps.rs/crate/tracing-actix-web/0.6.0) | A middleware to collect telemetry data from applications built on top of the actix-web framework. |
|
||||||
| [actix-ws] | [][actix-ws] [](https://deps.rs/crate/actix-ws/0.2.5) | Actor-less WebSockets for the Actix Runtime. |
|
| [actix-ws] | [][actix-ws] [](https://deps.rs/crate/actix-ws/0.2.5) | Actor-less WebSockets for the Actix Runtime. |
|
||||||
| [actix-hash] | [][actix-hash] [](https://deps.rs/crate/actix-hash/0.4.0) | Hashing utilities for Actix Web. |
|
| [actix-hash] | [][actix-hash] [](https://deps.rs/crate/actix-hash/0.4.0) | Hashing utilities for Actix Web. |
|
||||||
|
| [actix-bincode] |  [](https://deps.rs/crate/actix-bincode/0.2.0) | Bincode payload extractor for Actix Web |
|
||||||
|
|
||||||
To add a crate to this list, submit a pull request.
|
To add a crate to this list, submit a pull request.
|
||||||
|
|
||||||
@ -72,3 +73,4 @@ To add a crate to this list, submit a pull request.
|
|||||||
[tracing-actix-web]: https://crates.io/crates/tracing-actix-web
|
[tracing-actix-web]: https://crates.io/crates/tracing-actix-web
|
||||||
[actix-ws]: https://crates.io/crates/actix-ws
|
[actix-ws]: https://crates.io/crates/actix-ws
|
||||||
[actix-hash]: https://crates.io/crates/actix-hash
|
[actix-hash]: https://crates.io/crates/actix-hash
|
||||||
|
[actix-bincode]: https://crates.io/crates/actix-bincode
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
## Unreleased - 2022-xx-xx
|
## Unreleased - 2022-xx-xx
|
||||||
|
|
||||||
|
|
||||||
|
## 0.6.4 - 2022-10-28
|
||||||
|
- Add `Cors::allow_private_network_access()` behind an unstable flag (`draft-private-network-access`). [#297]
|
||||||
|
|
||||||
|
[#297]: https://github.com/actix/actix-extras/pull/297
|
||||||
|
|
||||||
|
|
||||||
## 0.6.3 - 2022-09-21
|
## 0.6.3 - 2022-09-21
|
||||||
- Add `Cors::block_on_origin_mismatch()` option for controlling if requests are pre-emptively rejected. [#287]
|
- Add `Cors::block_on_origin_mismatch()` option for controlling if requests are pre-emptively rejected. [#287]
|
||||||
- Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency.
|
- Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-cors"
|
name = "actix-cors"
|
||||||
version = "0.6.3"
|
version = "0.6.4"
|
||||||
authors = [
|
authors = [
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
"Rob Ede <robjtede@icloud.com>",
|
||||||
@ -12,9 +12,12 @@ repository = "https://github.com/actix/actix-extras.git"
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[lib]
|
[package.metadata.docs.rs]
|
||||||
name = "actix_cors"
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
path = "src/lib.rs"
|
all-features = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
draft-private-network-access = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-utils = "3"
|
actix-utils = "3"
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
> Cross-Origin Resource Sharing (CORS) controls for Actix Web.
|
> Cross-Origin Resource Sharing (CORS) controls for Actix Web.
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-cors)
|
[](https://crates.io/crates/actix-cors)
|
||||||
[](https://docs.rs/actix-cors/0.6.3)
|
[](https://docs.rs/actix-cors/0.6.4)
|
||||||

|

|
||||||
[](https://deps.rs/crate/actix-cors/0.6.3)
|
[](https://deps.rs/crate/actix-cors/0.6.4)
|
||||||
|
|
||||||
## Documentation & Resources
|
## Documentation & Resources
|
||||||
|
|
||||||
|
@ -101,6 +101,8 @@ impl Cors {
|
|||||||
preflight: true,
|
preflight: true,
|
||||||
send_wildcard: false,
|
send_wildcard: false,
|
||||||
supports_credentials: true,
|
supports_credentials: true,
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
allow_private_network_access: false,
|
||||||
vary_header: true,
|
vary_header: true,
|
||||||
block_on_origin_mismatch: true,
|
block_on_origin_mismatch: true,
|
||||||
};
|
};
|
||||||
@ -370,7 +372,7 @@ impl Cors {
|
|||||||
/// [Fetch Standard CORS protocol]: https://fetch.spec.whatwg.org/#http-cors-protocol
|
/// [Fetch Standard CORS protocol]: https://fetch.spec.whatwg.org/#http-cors-protocol
|
||||||
pub fn max_age(mut self, max_age: impl Into<Option<usize>>) -> Cors {
|
pub fn max_age(mut self, max_age: impl Into<Option<usize>>) -> Cors {
|
||||||
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
||||||
cors.max_age = max_age.into()
|
cors.max_age = max_age.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -389,7 +391,7 @@ impl Cors {
|
|||||||
/// Defaults to `false`.
|
/// Defaults to `false`.
|
||||||
pub fn send_wildcard(mut self) -> Cors {
|
pub fn send_wildcard(mut self) -> Cors {
|
||||||
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
||||||
cors.send_wildcard = true
|
cors.send_wildcard = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -412,7 +414,27 @@ impl Cors {
|
|||||||
/// [Fetch Standard CORS protocol]: https://fetch.spec.whatwg.org/#http-cors-protocol
|
/// [Fetch Standard CORS protocol]: https://fetch.spec.whatwg.org/#http-cors-protocol
|
||||||
pub fn supports_credentials(mut self) -> Cors {
|
pub fn supports_credentials(mut self) -> Cors {
|
||||||
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
||||||
cors.supports_credentials = true
|
cors.supports_credentials = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allow private network access.
|
||||||
|
///
|
||||||
|
/// If true, injects the `Access-Control-Allow-Private-Network: true` header in responses if the
|
||||||
|
/// request contained the `Access-Control-Request-Private-Network: true` header.
|
||||||
|
///
|
||||||
|
/// For more information on this behavior, see the draft [Private Network Access] spec.
|
||||||
|
///
|
||||||
|
/// Defaults to `false`.
|
||||||
|
///
|
||||||
|
/// [Private Network Access]: https://wicg.github.io/private-network-access
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
#[cfg_attr(docsrs, doc(cfg(feature = "draft-private-network-access")))]
|
||||||
|
pub fn allow_private_network_access(mut self) -> Cors {
|
||||||
|
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
||||||
|
cors.allow_private_network_access = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -430,7 +452,7 @@ impl Cors {
|
|||||||
/// By default, `Vary` header support is enabled.
|
/// By default, `Vary` header support is enabled.
|
||||||
pub fn disable_vary_header(mut self) -> Cors {
|
pub fn disable_vary_header(mut self) -> Cors {
|
||||||
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
||||||
cors.vary_header = false
|
cors.vary_header = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -444,7 +466,7 @@ impl Cors {
|
|||||||
/// By default *preflight* support is enabled.
|
/// By default *preflight* support is enabled.
|
||||||
pub fn disable_preflight(mut self) -> Cors {
|
pub fn disable_preflight(mut self) -> Cors {
|
||||||
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
||||||
cors.preflight = false
|
cors.preflight = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -462,7 +484,7 @@ impl Cors {
|
|||||||
/// Defaults to `true`.
|
/// Defaults to `true`.
|
||||||
pub fn block_on_origin_mismatch(mut self, block: bool) -> Cors {
|
pub fn block_on_origin_mismatch(mut self, block: bool) -> Cors {
|
||||||
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
if let Some(cors) = cors(&mut self.inner, &self.error) {
|
||||||
cors.block_on_origin_mismatch = block
|
cors.block_on_origin_mismatch = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
@ -492,6 +514,8 @@ impl Default for Cors {
|
|||||||
preflight: true,
|
preflight: true,
|
||||||
send_wildcard: false,
|
send_wildcard: false,
|
||||||
supports_credentials: false,
|
supports_credentials: false,
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
allow_private_network_access: false,
|
||||||
vary_header: true,
|
vary_header: true,
|
||||||
block_on_origin_mismatch: true,
|
block_on_origin_mismatch: true,
|
||||||
};
|
};
|
||||||
|
@ -64,6 +64,8 @@ pub(crate) struct Inner {
|
|||||||
pub(crate) preflight: bool,
|
pub(crate) preflight: bool,
|
||||||
pub(crate) send_wildcard: bool,
|
pub(crate) send_wildcard: bool,
|
||||||
pub(crate) supports_credentials: bool,
|
pub(crate) supports_credentials: bool,
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
pub(crate) allow_private_network_access: bool,
|
||||||
pub(crate) vary_header: bool,
|
pub(crate) vary_header: bool,
|
||||||
pub(crate) block_on_origin_mismatch: bool,
|
pub(crate) block_on_origin_mismatch: bool,
|
||||||
}
|
}
|
||||||
@ -219,8 +221,20 @@ pub(crate) fn add_vary_header(headers: &mut HeaderMap) {
|
|||||||
let mut val: Vec<u8> = Vec::with_capacity(hdr.len() + 71);
|
let mut val: Vec<u8> = Vec::with_capacity(hdr.len() + 71);
|
||||||
val.extend(hdr.as_bytes());
|
val.extend(hdr.as_bytes());
|
||||||
val.extend(b", Origin, Access-Control-Request-Method, Access-Control-Request-Headers");
|
val.extend(b", Origin, Access-Control-Request-Method, Access-Control-Request-Headers");
|
||||||
|
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
val.extend(b", Access-Control-Allow-Private-Network");
|
||||||
|
|
||||||
val.try_into().unwrap()
|
val.try_into().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
None => HeaderValue::from_static(
|
||||||
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, \
|
||||||
|
Access-Control-Allow-Private-Network",
|
||||||
|
),
|
||||||
|
|
||||||
|
#[cfg(not(feature = "draft-private-network-access"))]
|
||||||
None => HeaderValue::from_static(
|
None => HeaderValue::from_static(
|
||||||
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
||||||
),
|
),
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
//! Cross-Origin Resource Sharing (CORS) controls for Actix Web.
|
//! Cross-Origin Resource Sharing (CORS) controls for Actix Web.
|
||||||
//!
|
//!
|
||||||
//! This middleware can be applied to both applications and resources. Once built, a
|
//! This middleware can be applied to both applications and resources. Once built, a [`Cors`]
|
||||||
//! [`Cors`] builder can be used as an argument for Actix Web's `App::wrap()`,
|
//! builder can be used as an argument for Actix Web's `App::wrap()`, `Scope::wrap()`, or
|
||||||
//! `Scope::wrap()`, or `Resource::wrap()` methods.
|
//! `Resource::wrap()` methods.
|
||||||
//!
|
//!
|
||||||
//! This CORS middleware automatically handles `OPTIONS` preflight requests.
|
//! This CORS middleware automatically handles `OPTIONS` preflight requests.
|
||||||
//!
|
//!
|
||||||
|
//! # Crate Features
|
||||||
|
//! - `draft-private-network-access`: ⚠️ Unstable. Adds opt-in support for the [Private Network
|
||||||
|
//! Access] spec extensions. This feature is unstable since it will follow any breaking changes in
|
||||||
|
//! the draft spec until it is finalized.
|
||||||
|
//!
|
||||||
//! # Example
|
//! # Example
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use actix_cors::Cors;
|
//! use actix_cors::Cors;
|
||||||
@ -40,12 +45,15 @@
|
|||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
//!
|
||||||
|
//! [Private Network Access]: https://wicg.github.io/private-network-access
|
||||||
|
|
||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||||
#![warn(future_incompatible, missing_docs, missing_debug_implementations)]
|
#![warn(future_incompatible, missing_docs, missing_debug_implementations)]
|
||||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
|
||||||
mod all_or_some;
|
mod all_or_some;
|
||||||
mod builder;
|
mod builder;
|
||||||
|
@ -93,6 +93,18 @@ impl<S> CorsMiddleware<S> {
|
|||||||
res.insert_header((header::ACCESS_CONTROL_ALLOW_HEADERS, headers.clone()));
|
res.insert_header((header::ACCESS_CONTROL_ALLOW_HEADERS, headers.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
if inner.allow_private_network_access
|
||||||
|
&& req
|
||||||
|
.headers()
|
||||||
|
.contains_key("access-control-request-private-network")
|
||||||
|
{
|
||||||
|
res.insert_header((
|
||||||
|
header::HeaderName::from_static("access-control-allow-private-network"),
|
||||||
|
HeaderValue::from_static("true"),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
if inner.supports_credentials {
|
if inner.supports_credentials {
|
||||||
res.insert_header((
|
res.insert_header((
|
||||||
header::ACCESS_CONTROL_ALLOW_CREDENTIALS,
|
header::ACCESS_CONTROL_ALLOW_CREDENTIALS,
|
||||||
@ -162,6 +174,19 @@ impl<S> CorsMiddleware<S> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
if inner.allow_private_network_access
|
||||||
|
&& res
|
||||||
|
.request()
|
||||||
|
.headers()
|
||||||
|
.contains_key("access-control-request-private-network")
|
||||||
|
{
|
||||||
|
res.headers_mut().insert(
|
||||||
|
header::HeaderName::from_static("access-control-allow-private-network"),
|
||||||
|
HeaderValue::from_static("true"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if inner.vary_header {
|
if inner.vary_header {
|
||||||
add_vary_header(res.headers_mut());
|
add_vary_header(res.headers_mut());
|
||||||
}
|
}
|
||||||
|
@ -264,10 +264,16 @@ async fn test_response() {
|
|||||||
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||||
.map(HeaderValue::as_bytes)
|
.map(HeaderValue::as_bytes)
|
||||||
);
|
);
|
||||||
|
#[cfg(not(feature = "draft-private-network-access"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(header::VARY).map(HeaderValue::as_bytes),
|
resp.headers().get(header::VARY).map(HeaderValue::as_bytes),
|
||||||
Some(&b"Origin, Access-Control-Request-Method, Access-Control-Request-Headers"[..]),
|
Some(&b"Origin, Access-Control-Request-Method, Access-Control-Request-Headers"[..]),
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers().get(header::VARY).map(HeaderValue::as_bytes),
|
||||||
|
Some(&b"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Private-Network"[..]),
|
||||||
|
);
|
||||||
|
|
||||||
#[allow(clippy::needless_collect)]
|
#[allow(clippy::needless_collect)]
|
||||||
{
|
{
|
||||||
@ -311,9 +317,18 @@ async fn test_response() {
|
|||||||
.method(Method::OPTIONS)
|
.method(Method::OPTIONS)
|
||||||
.to_srv_request();
|
.to_srv_request();
|
||||||
let resp = test::call_service(&cors, req).await;
|
let resp = test::call_service(&cors, req).await;
|
||||||
|
#[cfg(not(feature = "draft-private-network-access"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers().get(header::VARY).map(HeaderValue::as_bytes),
|
resp.headers()
|
||||||
Some(&b"Accept, Origin, Access-Control-Request-Method, Access-Control-Request-Headers"[..]),
|
.get(header::VARY)
|
||||||
|
.map(HeaderValue::as_bytes)
|
||||||
|
.unwrap(),
|
||||||
|
b"Accept, Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
||||||
|
);
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers().get(header::VARY).map(HeaderValue::as_bytes).unwrap(),
|
||||||
|
b"Accept, Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Private-Network",
|
||||||
);
|
);
|
||||||
|
|
||||||
let cors = Cors::default()
|
let cors = Cors::default()
|
||||||
@ -463,6 +478,7 @@ async fn vary_header_on_all_handled_responses() {
|
|||||||
assert!(resp
|
assert!(resp
|
||||||
.headers()
|
.headers()
|
||||||
.contains_key(header::ACCESS_CONTROL_ALLOW_METHODS));
|
.contains_key(header::ACCESS_CONTROL_ALLOW_METHODS));
|
||||||
|
#[cfg(not(feature = "draft-private-network-access"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers()
|
resp.headers()
|
||||||
.get(header::VARY)
|
.get(header::VARY)
|
||||||
@ -471,6 +487,15 @@ async fn vary_header_on_all_handled_responses() {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers()
|
||||||
|
.get(header::VARY)
|
||||||
|
.expect("response should have Vary header")
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Private-Network",
|
||||||
|
);
|
||||||
|
|
||||||
// follow-up regular request
|
// follow-up regular request
|
||||||
let req = TestRequest::default()
|
let req = TestRequest::default()
|
||||||
@ -479,6 +504,7 @@ async fn vary_header_on_all_handled_responses() {
|
|||||||
.to_srv_request();
|
.to_srv_request();
|
||||||
let resp = test::call_service(&cors, req).await;
|
let resp = test::call_service(&cors, req).await;
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
#[cfg(not(feature = "draft-private-network-access"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers()
|
resp.headers()
|
||||||
.get(header::VARY)
|
.get(header::VARY)
|
||||||
@ -487,6 +513,15 @@ async fn vary_header_on_all_handled_responses() {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers()
|
||||||
|
.get(header::VARY)
|
||||||
|
.expect("response should have Vary header")
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Private-Network",
|
||||||
|
);
|
||||||
|
|
||||||
let cors = Cors::default()
|
let cors = Cors::default()
|
||||||
.allow_any_method()
|
.allow_any_method()
|
||||||
@ -501,6 +536,7 @@ async fn vary_header_on_all_handled_responses() {
|
|||||||
.to_srv_request();
|
.to_srv_request();
|
||||||
let resp = test::call_service(&cors, req).await;
|
let resp = test::call_service(&cors, req).await;
|
||||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||||
|
#[cfg(not(feature = "draft-private-network-access"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers()
|
resp.headers()
|
||||||
.get(header::VARY)
|
.get(header::VARY)
|
||||||
@ -509,11 +545,21 @@ async fn vary_header_on_all_handled_responses() {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers()
|
||||||
|
.get(header::VARY)
|
||||||
|
.expect("response should have Vary header")
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Private-Network",
|
||||||
|
);
|
||||||
|
|
||||||
// regular request no origin
|
// regular request no origin
|
||||||
let req = TestRequest::default().method(Method::PUT).to_srv_request();
|
let req = TestRequest::default().method(Method::PUT).to_srv_request();
|
||||||
let resp = test::call_service(&cors, req).await;
|
let resp = test::call_service(&cors, req).await;
|
||||||
assert_eq!(resp.status(), StatusCode::OK);
|
assert_eq!(resp.status(), StatusCode::OK);
|
||||||
|
#[cfg(not(feature = "draft-private-network-access"))]
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resp.headers()
|
resp.headers()
|
||||||
.get(header::VARY)
|
.get(header::VARY)
|
||||||
@ -522,6 +568,15 @@ async fn vary_header_on_all_handled_responses() {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
|
||||||
);
|
);
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
assert_eq!(
|
||||||
|
resp.headers()
|
||||||
|
.get(header::VARY)
|
||||||
|
.expect("response should have Vary header")
|
||||||
|
.to_str()
|
||||||
|
.unwrap(),
|
||||||
|
"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Private-Network",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web::test]
|
#[actix_web::test]
|
||||||
@ -578,3 +633,42 @@ async fn expose_all_request_header_values() {
|
|||||||
assert!(cd_hdr.contains("content-disposition"));
|
assert!(cd_hdr.contains("content-disposition"));
|
||||||
assert!(cd_hdr.contains("access-control-allow-origin"));
|
assert!(cd_hdr.contains("access-control-allow-origin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "draft-private-network-access")]
|
||||||
|
#[actix_web::test]
|
||||||
|
async fn private_network_access() {
|
||||||
|
let cors = Cors::permissive()
|
||||||
|
.allowed_origin("https://public.site")
|
||||||
|
.allow_private_network_access()
|
||||||
|
.new_transform(fn_service(|req: ServiceRequest| async move {
|
||||||
|
let res = req.into_response(
|
||||||
|
HttpResponse::Ok()
|
||||||
|
.insert_header((header::CONTENT_DISPOSITION, "test disposition"))
|
||||||
|
.finish(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let req = TestRequest::default()
|
||||||
|
.insert_header((header::ORIGIN, "https://public.site"))
|
||||||
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "POST"))
|
||||||
|
.insert_header((header::ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"))
|
||||||
|
.to_srv_request();
|
||||||
|
let res = test::call_service(&cors, req).await;
|
||||||
|
assert!(res.headers().contains_key("access-control-allow-origin"));
|
||||||
|
|
||||||
|
let req = TestRequest::default()
|
||||||
|
.insert_header((header::ORIGIN, "https://public.site"))
|
||||||
|
.insert_header((header::ACCESS_CONTROL_REQUEST_METHOD, "POST"))
|
||||||
|
.insert_header((header::ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"))
|
||||||
|
.insert_header(("Access-Control-Request-Private-Network", "true"))
|
||||||
|
.to_srv_request();
|
||||||
|
let res = test::call_service(&cors, req).await;
|
||||||
|
assert!(res.headers().contains_key("access-control-allow-origin"));
|
||||||
|
assert!(res
|
||||||
|
.headers()
|
||||||
|
.contains_key("access-control-allow-private-network"));
|
||||||
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
- Set secure attribute when adding a session removal cookie. [#300]
|
||||||
|
|
||||||
|
[#300]: https://github.com/actix/actix-extras/pull/300
|
||||||
|
|
||||||
## 0.7.2 - 2022-09-11
|
## 0.7.2 - 2022-09-11
|
||||||
- Set SameSite attribute when adding a session removal cookie. [#284]
|
- Set SameSite attribute when adding a session removal cookie. [#284]
|
||||||
|
@ -444,6 +444,7 @@ fn delete_session_cookie(
|
|||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<(), anyhow::Error> {
|
||||||
let removal_cookie = Cookie::build(config.name.clone(), "")
|
let removal_cookie = Cookie::build(config.name.clone(), "")
|
||||||
.path(config.path.clone())
|
.path(config.path.clone())
|
||||||
|
.secure(config.secure)
|
||||||
.http_only(config.http_only)
|
.http_only(config.http_only)
|
||||||
.same_site(config.same_site);
|
.same_site(config.same_site);
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ async fn cookie_storage() -> std::io::Result<()> {
|
|||||||
let deletion_cookie = logout_response.response().cookies().next().unwrap();
|
let deletion_cookie = logout_response.response().cookies().next().unwrap();
|
||||||
assert_eq!(deletion_cookie.name(), "id");
|
assert_eq!(deletion_cookie.name(), "id");
|
||||||
assert_eq!(deletion_cookie.path().unwrap(), "/test");
|
assert_eq!(deletion_cookie.path().unwrap(), "/test");
|
||||||
assert!(deletion_cookie.secure().is_none());
|
assert!(deletion_cookie.secure().unwrap());
|
||||||
assert!(deletion_cookie.http_only().unwrap());
|
assert!(deletion_cookie.http_only().unwrap());
|
||||||
assert_eq!(deletion_cookie.max_age().unwrap(), Duration::ZERO);
|
assert_eq!(deletion_cookie.max_age().unwrap(), Duration::ZERO);
|
||||||
assert_eq!(deletion_cookie.domain().unwrap(), "localhost");
|
assert_eq!(deletion_cookie.domain().unwrap(), "localhost");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user