diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index a4b54ca7a..008c33f89 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -5,6 +5,9 @@ on: branches: - master +permissions: + contents: read # to fetch code (actions/checkout) + jobs: check_benchmark: runs-on: ubuntu-latest diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 1ee97b591..7ac6388d4 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -4,6 +4,9 @@ on: push: branches: [master] +permissions: + contents: read # to fetch code (actions/checkout) + jobs: build_and_test_nightly: strategy: @@ -92,29 +95,21 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install stable - uses: actions-rs/toolchain@v1 - with: - toolchain: stable-x86_64-unknown-linux-gnu - profile: minimal - override: true + - uses: dtolnay/rust-toolchain@stable - name: Install cargo-hack uses: taiki-e/install-action@cargo-hack - name: Generate Cargo.lock - uses: actions-rs/cargo@v1 - with: { command: generate-lockfile } + run: cargo generate-lockfile - name: Cache Dependencies uses: Swatinem/rust-cache@v1.2.0 - name: check feature combinations - uses: actions-rs/cargo@v1 - with: { command: ci-check-all-feature-powerset } - + run: cargo ci-check-all-feature-powerset + - name: check feature combinations - uses: actions-rs/cargo@v1 - with: { command: ci-check-all-feature-powerset-linux } + run: cargo ci-check-all-feature-powerset-linux nextest: name: nextest @@ -127,24 +122,15 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - override: true + - uses: dtolnay/rust-toolchain@stable - name: Install nextest uses: taiki-e/install-action@nextest - name: Generate Cargo.lock - uses: actions-rs/cargo@v1 - with: { command: generate-lockfile } + run: cargo generate-lockfile - name: Cache Dependencies uses: Swatinem/rust-cache@v1.3.0 - name: Test with cargo-nextest - uses: actions-rs/cargo@v1 - with: - command: nextest - args: run + run: cargo nextest run diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de1e1fe18..421becc63 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,9 @@ on: push: branches: [master] +permissions: + contents: read # to fetch code (actions/checkout) + jobs: build_and_test: strategy: @@ -63,6 +66,11 @@ jobs: - name: Cache Dependencies uses: Swatinem/rust-cache@v1.2.0 + - name: workaround MSRV issues + if: matrix.version != 'stable' + run: | + cargo update -p=zstd-sys --precise=2.0.1+zstd.1.5.2 + - name: check minimal uses: actions-rs/cargo@v1 with: { command: ci-check-min } @@ -96,16 +104,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable-x86_64-unknown-linux-gnu - profile: minimal - override: true + - uses: dtolnay/rust-toolchain@stable - name: Generate Cargo.lock - uses: actions-rs/cargo@v1 - with: { command: generate-lockfile } + run: cargo generate-lockfile - name: Cache Dependencies uses: Swatinem/rust-cache@v1.3.0 @@ -123,20 +125,13 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Install Rust (nightly) - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly-x86_64-unknown-linux-gnu - profile: minimal - override: true + - uses: dtolnay/rust-toolchain@nightly - name: Generate Cargo.lock - uses: actions-rs/cargo@v1 - with: { command: generate-lockfile } + run: cargo generate-lockfile - name: Cache Dependencies uses: Swatinem/rust-cache@v1.3.0 - name: doc tests - uses: actions-rs/cargo@v1 + run: cargo ci-doctest timeout-minutes: 60 - with: { command: ci-doctest } diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index bc2cec145..e94c4d1af 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -9,54 +9,37 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - components: rustfmt - - name: Check with rustfmt - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + - uses: dtolnay/rust-toolchain@nightly + with: { components: rustfmt } + - run: cargo fmt --all -- --check clippy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - components: clippy - override: true + - uses: dtolnay/rust-toolchain@stable + with: { components: clippy } - name: Generate Cargo.lock - uses: actions-rs/cargo@v1 - with: { command: generate-lockfile } + run: cargo generate-lockfile - name: Cache Dependencies uses: Swatinem/rust-cache@v1.2.0 - + - name: Check with Clippy uses: actions-rs/clippy-check@v1 with: - token: ${{ secrets.GITHUB_TOKEN }} args: --workspace --tests --examples --all-features + token: ${{ secrets.GITHUB_TOKEN }} lint-docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - profile: minimal - components: rust-docs + + - uses: dtolnay/rust-toolchain@stable + with: { components: rust-docs } + - name: Check for broken intra-doc links uses: actions-rs/cargo@v1 env: diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 07f839e34..9aadafafc 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -4,31 +4,29 @@ on: push: branches: [master] +permissions: {} jobs: build: + permissions: + contents: write # to push changes in repo (jamesives/github-pages-deploy-action) + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly-x86_64-unknown-linux-gnu - profile: minimal - override: true + - uses: dtolnay/rust-toolchain@nightly - name: Build Docs - uses: actions-rs/cargo@v1 - with: - command: doc - args: --workspace --all-features --no-deps + run: cargo +nightly doc --no-deps --workspace --all-features + env: + RUSTDOCFLAGS: --cfg=docsrs - name: Tweak HTML run: echo '' > target/doc/index.html - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.4.0 + uses: JamesIves/github-pages-deploy-action@v4.4.1 with: folder: target/doc single-commit: true diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 33de0e6d9..01dc2928a 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -3,7 +3,6 @@ name = "actix-files" version = "0.6.2" authors = [ "Nikolay Kim ", - "fakeshadow <24548779@qq.com>", "Rob Ede ", ] description = "Static file serving for Actix Web" @@ -30,7 +29,7 @@ actix-web = { version = "4", default-features = false } bitflags = "1" bytes = "1" derive_more = "0.99.5" -futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] } +futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } http-range = "0.1.4" log = "0.4" mime = "0.3" diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 40327e5e8..0fbe39a8e 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -13,6 +13,7 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible, missing_docs, missing_debug_implementations)] +#![allow(clippy::uninlined_format_args)] use actix_service::boxed::{BoxService, BoxServiceFactory}; use actix_web::{ diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 0a9ddf947..1162c0a38 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -39,7 +39,7 @@ awc = { version = "3", default-features = false } base64 = "0.13" bytes = "1" -futures-core = { version = "0.3.7", default-features = false } +futures-core = { version = "0.3.17", default-features = false } http = "0.2.5" log = "0.4" socket2 = "0.4" @@ -48,7 +48,7 @@ serde_json = "1.0" slab = "0.4" serde_urlencoded = "0.7" tls-openssl = { version = "0.10.9", package = "openssl", optional = true } -tokio = { version = "1.8.4", features = ["sync"] } +tokio = { version = "1.18.4", features = ["sync"] } [dev-dependencies] actix-web = { version = "4", default-features = false, features = ["cookies"] } diff --git a/actix-http-test/src/lib.rs b/actix-http-test/src/lib.rs index 8636ef9c4..a66f7b486 100644 --- a/actix-http-test/src/lib.rs +++ b/actix-http-test/src/lib.rs @@ -2,6 +2,7 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] +#![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] @@ -87,6 +88,7 @@ pub async fn test_server_with_addr>( // notify TestServer that server and system have shut down // all thread managed resources should be dropped at this point + #[allow(clippy::let_underscore_future)] let _ = thread_stop_tx.send(()); }); @@ -294,6 +296,7 @@ impl Drop for TestServer { // without needing to await anything // signal server to stop + #[allow(clippy::let_underscore_future)] let _ = self.server.stop(true); // signal system to stop diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index a8f65ef92..f67a7fefc 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -5,14 +5,31 @@ - Fix non-empty body of http2 HEAD response. ### Added +- Implement `MessageBody` for `Cow<'static, str>` and `Cow<'static, [u8]>`. [#2959] - Implement `MessageBody` for `&mut B` where `B: MessageBody + Unpin`. [#2868] - Implement `MessageBody` for `Pin` where `B::Target: MessageBody`. [#2868] +- Automatic h2c detection via new service finalizer `HttpService::tcp_auto_h2c()`. [#2957] +- `HeaderMap::retain()` [#2955]. +- Header name constants in `header` module. [#2956] [#2968] + - `CACHE_STATUS` + - `CDN_CACHE_CONTROL` + - `CROSS_ORIGIN_EMBEDDER_POLICY` + - `CROSS_ORIGIN_OPENER_POLICY` + - `PERMISSIONS_POLICY` + - `X_FORWARDED_FOR` + - `X_FORWARDED_HOST` + - `X_FORWARDED_PROTO` ### Performance - Improve overall performance of operations on `Extensions`. [#2890] +[#2959]: https://github.com/actix/actix-web/pull/2959 [#2868]: https://github.com/actix/actix-web/pull/2868 [#2890]: https://github.com/actix/actix-web/pull/2890 +[#2957]: https://github.com/actix/actix-web/pull/2957 +[#2955]: https://github.com/actix/actix-web/pull/2955 +[#2956]: https://github.com/actix/actix-web/pull/2956 +[#2968]: https://github.com/actix/actix-web/pull/2968 ## 3.2.2 - 2022-09-11 diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 30e436160..9939089b9 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -67,7 +67,7 @@ bytes = "1" bytestring = "1" derive_more = "0.99.5" encoding_rs = "0.8" -futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] } +futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } http = "0.2.5" httparse = "1.5.1" httpdate = "1.0.1" @@ -77,6 +77,8 @@ mime = "0.3" percent-encoding = "2.1" pin-project-lite = "0.2" smallvec = "1.6.1" +tokio = { version = "1.18.4", features = [] } +tokio-util = { version = "0.7", features = ["io", "codec"] } tracing = { version = "0.1.30", default-features = false, features = ["log"] } # http2 @@ -94,7 +96,7 @@ actix-tls = { version = "3", default-features = false, optional = true } # compress-* brotli = { version = "3.3.3", optional = true } flate2 = { version = "1.0.13", optional = true } -zstd = { version = "0.11", optional = true } +zstd = { version = "0.12", optional = true } [dev-dependencies] actix-http-test = { version = "3", features = ["openssl"] } @@ -103,9 +105,9 @@ actix-tls = { version = "3", features = ["openssl"] } actix-web = "4" async-stream = "0.3" -criterion = { version = "0.3", features = ["html_reports"] } +criterion = { version = "0.4", features = ["html_reports"] } env_logger = "0.9" -futures-util = { version = "0.3.7", default-features = false, features = ["alloc"] } +futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } memchr = "2.4" once_cell = "1.9" rcgen = "0.9" @@ -117,7 +119,7 @@ serde_json = "1.0" static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.9" } tls-rustls = { package = "rustls", version = "0.20.0" } -tokio = { version = "1.8.4", features = ["net", "rt", "macros"] } +tokio = { version = "1.18.4", features = ["net", "rt", "macros"] } [[example]] name = "ws" diff --git a/actix-http/benches/quality-value.rs b/actix-http/benches/quality-value.rs index 33ba9c4c8..0ed274ded 100644 --- a/actix-http/benches/quality-value.rs +++ b/actix-http/benches/quality-value.rs @@ -1,3 +1,5 @@ +#![allow(clippy::uninlined_format_args)] + use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; const CODES: &[u16] = &[0, 1000, 201, 800, 550]; diff --git a/actix-http/examples/h2c-detect.rs b/actix-http/examples/h2c-detect.rs new file mode 100644 index 000000000..aa3dd5d31 --- /dev/null +++ b/actix-http/examples/h2c-detect.rs @@ -0,0 +1,29 @@ +//! An example that supports automatic selection of plaintext h1/h2c connections. +//! +//! Notably, both the following commands will work. +//! ```console +//! $ curl --http1.1 'http://localhost:8080/' +//! $ curl --http2-prior-knowledge 'http://localhost:8080/' +//! ``` + +use std::{convert::Infallible, io}; + +use actix_http::{HttpService, Request, Response, StatusCode}; +use actix_server::Server; + +#[tokio::main(flavor = "current_thread")] +async fn main() -> io::Result<()> { + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + Server::build() + .bind("h2c-detect", ("127.0.0.1", 8080), || { + HttpService::build() + .finish(|_req: Request| async move { + Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!")) + }) + .tcp_auto_h2c() + })? + .workers(2) + .run() + .await +} diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs index c4f0503cd..6af6d5095 100644 --- a/actix-http/examples/ws.rs +++ b/actix-http/examples/ws.rs @@ -10,13 +10,13 @@ use std::{ time::Duration, }; -use actix_codec::Encoder; use actix_http::{body::BodyStream, error::Error, ws, HttpService, Request, Response}; use actix_rt::time::{interval, Interval}; use actix_server::Server; use bytes::{Bytes, BytesMut}; use bytestring::ByteString; use futures_core::{ready, Stream}; +use tokio_util::codec::Encoder; use tracing::{info, trace}; #[actix_rt::main] diff --git a/actix-http/src/body/message_body.rs b/actix-http/src/body/message_body.rs index 0cfaa8653..e274cf8aa 100644 --- a/actix-http/src/body/message_body.rs +++ b/actix-http/src/body/message_body.rs @@ -120,7 +120,7 @@ pub trait MessageBody { } mod foreign_impls { - use std::ops::DerefMut; + use std::{borrow::Cow, ops::DerefMut}; use super::*; @@ -324,6 +324,39 @@ mod foreign_impls { } } + impl MessageBody for Cow<'static, [u8]> { + type Error = Infallible; + + #[inline] + fn size(&self) -> BodySize { + BodySize::Sized(self.len() as u64) + } + + #[inline] + fn poll_next( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll>> { + if self.is_empty() { + Poll::Ready(None) + } else { + let bytes = match mem::take(self.get_mut()) { + Cow::Borrowed(b) => Bytes::from_static(b), + Cow::Owned(b) => Bytes::from(b), + }; + Poll::Ready(Some(Ok(bytes))) + } + } + + #[inline] + fn try_into_bytes(self) -> Result { + match self { + Cow::Borrowed(b) => Ok(Bytes::from_static(b)), + Cow::Owned(b) => Ok(Bytes::from(b)), + } + } + } + impl MessageBody for &'static str { type Error = Infallible; @@ -379,6 +412,39 @@ mod foreign_impls { } } + impl MessageBody for Cow<'static, str> { + type Error = Infallible; + + #[inline] + fn size(&self) -> BodySize { + BodySize::Sized(self.len() as u64) + } + + #[inline] + fn poll_next( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll>> { + if self.is_empty() { + Poll::Ready(None) + } else { + let bytes = match mem::take(self.get_mut()) { + Cow::Borrowed(s) => Bytes::from_static(s.as_bytes()), + Cow::Owned(s) => Bytes::from(s.into_bytes()), + }; + Poll::Ready(Some(Ok(bytes))) + } + } + + #[inline] + fn try_into_bytes(self) -> Result { + match self { + Cow::Borrowed(s) => Ok(Bytes::from_static(s.as_bytes())), + Cow::Owned(s) => Ok(Bytes::from(s.into_bytes())), + } + } + } + impl MessageBody for bytestring::ByteString { type Error = Infallible; diff --git a/actix-http/src/body/sized_stream.rs b/actix-http/src/body/sized_stream.rs index e5e27b287..08cd81a0d 100644 --- a/actix-http/src/body/sized_stream.rs +++ b/actix-http/src/body/sized_stream.rs @@ -44,7 +44,7 @@ where #[inline] fn size(&self) -> BodySize { - BodySize::Sized(self.size as u64) + BodySize::Sized(self.size) } /// Attempts to pull out the next value of the underlying [`Stream`]. diff --git a/actix-http/src/builder.rs b/actix-http/src/builder.rs index 71b933835..e2693acaf 100644 --- a/actix-http/src/builder.rs +++ b/actix-http/src/builder.rs @@ -186,7 +186,7 @@ where self } - /// Finish service configuration and create a HTTP Service for HTTP/1 protocol. + /// Finish service configuration and create a service for the HTTP/1 protocol. pub fn h1(self, service: F) -> H1Service where B: MessageBody, @@ -209,7 +209,7 @@ where .on_connect_ext(self.on_connect_ext) } - /// Finish service configuration and create a HTTP service for HTTP/2 protocol. + /// Finish service configuration and create a service for the HTTP/2 protocol. #[cfg(feature = "http2")] #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub fn h2(self, service: F) -> crate::h2::H2Service diff --git a/actix-http/src/h1/chunked.rs b/actix-http/src/h1/chunked.rs index 4005ed892..fc9081b81 100644 --- a/actix-http/src/h1/chunked.rs +++ b/actix-http/src/h1/chunked.rs @@ -71,7 +71,7 @@ impl ChunkedState { match size.checked_mul(radix) { Some(n) => { - *size = n as u64; + *size = n; *size += rem as u64; Poll::Ready(Ok(ChunkedState::Size)) diff --git a/actix-http/src/h1/client.rs b/actix-http/src/h1/client.rs index 75c88d00c..6a0d531d0 100644 --- a/actix-http/src/h1/client.rs +++ b/actix-http/src/h1/client.rs @@ -1,9 +1,9 @@ use std::{fmt, io}; -use actix_codec::{Decoder, Encoder}; use bitflags::bitflags; use bytes::{Bytes, BytesMut}; use http::{Method, Version}; +use tokio_util::codec::{Decoder, Encoder}; use super::{ decoder::{self, PayloadDecoder, PayloadItem, PayloadType}, diff --git a/actix-http/src/h1/codec.rs b/actix-http/src/h1/codec.rs index 80afd7455..e11f175c9 100644 --- a/actix-http/src/h1/codec.rs +++ b/actix-http/src/h1/codec.rs @@ -1,9 +1,9 @@ use std::{fmt, io}; -use actix_codec::{Decoder, Encoder}; use bitflags::bitflags; use bytes::BytesMut; use http::{Method, Version}; +use tokio_util::codec::{Decoder, Encoder}; use super::{ decoder::{self, PayloadDecoder, PayloadItem, PayloadType}, diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index 81090667d..60660b85b 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -8,13 +8,15 @@ use std::{ task::{Context, Poll}, }; -use actix_codec::{AsyncRead, AsyncWrite, Decoder as _, Encoder as _, Framed, FramedParts}; +use actix_codec::{Framed, FramedParts}; use actix_rt::time::sleep_until; use actix_service::Service; use bitflags::bitflags; use bytes::{Buf, BytesMut}; use futures_core::ready; use pin_project_lite::pin_project; +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio_util::codec::{Decoder as _, Encoder as _}; use tracing::{error, trace}; use crate::{ @@ -1004,7 +1006,7 @@ where this.read_buf.reserve(HW_BUFFER_SIZE - remaining); } - match actix_codec::poll_read_buf(io.as_mut(), cx, this.read_buf) { + match tokio_util::io::poll_read_buf(io.as_mut(), cx, this.read_buf) { Poll::Ready(Ok(n)) => { this.flags.remove(Flags::FINISHED); diff --git a/actix-http/src/h1/dispatcher_tests.rs b/actix-http/src/h1/dispatcher_tests.rs index 3eea859bf..d39c5bd69 100644 --- a/actix-http/src/h1/dispatcher_tests.rs +++ b/actix-http/src/h1/dispatcher_tests.rs @@ -64,7 +64,7 @@ fn drop_payload_service( fn echo_payload_service() -> impl Service, Error = Error> { fn_service(|mut req: Request| { Box::pin(async move { - use futures_util::stream::StreamExt as _; + use futures_util::StreamExt as _; let mut pl = req.take_payload(); let mut body = BytesMut::new(); diff --git a/actix-http/src/h1/encoder.rs b/actix-http/src/h1/encoder.rs index 21cfd75c4..abe396ce2 100644 --- a/actix-http/src/h1/encoder.rs +++ b/actix-http/src/h1/encoder.rs @@ -450,7 +450,7 @@ impl TransferEncoding { buf.extend_from_slice(&msg[..len as usize]); - *remaining -= len as u64; + *remaining -= len; Ok(*remaining == 0) } else { Ok(true) diff --git a/actix-http/src/header/common.rs b/actix-http/src/header/common.rs new file mode 100644 index 000000000..67b0a9069 --- /dev/null +++ b/actix-http/src/header/common.rs @@ -0,0 +1,51 @@ +//! Common header names not defined in [`http`]. +//! +//! Any headers added to this file will need to be re-exported from the list at `crate::headers`. + +use http::header::HeaderName; + +/// Response header field that indicates how caches have handled that response and its corresponding +/// request. +/// +/// See [RFC 9211](https://www.rfc-editor.org/rfc/rfc9211) for full semantics. +pub const CACHE_STATUS: HeaderName = HeaderName::from_static("cache-status"); + +/// Response header field that allows origin servers to control the behavior of CDN caches +/// interposed between them and clients separately from other caches that might handle the response. +/// +/// See [RFC 9213](https://www.rfc-editor.org/rfc/rfc9213) for full semantics. +pub const CDN_CACHE_CONTROL: HeaderName = HeaderName::from_static("cdn-cache-control"); + +/// Response header that prevents a document from loading any cross-origin resources that don't +/// explicitly grant the document permission (using [CORP] or [CORS]). +/// +/// [CORP]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP) +/// [CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS +pub const CROSS_ORIGIN_EMBEDDER_POLICY: HeaderName = + HeaderName::from_static("cross-origin-embedder-policy"); + +/// Response header that allows you to ensure a top-level document does not share a browsing context +/// group with cross-origin documents. +pub const CROSS_ORIGIN_OPENER_POLICY: HeaderName = + HeaderName::from_static("cross-origin-opener-policy"); + +/// Response header that conveys a desire that the browser blocks no-cors cross-origin/cross-site +/// requests to the given resource. +pub const CROSS_ORIGIN_RESOURCE_POLICY: HeaderName = + HeaderName::from_static("cross-origin-resource-policy"); + +/// Response header that provides a mechanism to allow and deny the use of browser features in a +/// document or within any `