mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into files/fix/percent-encoding
This commit is contained in:
commit
a444df21b5
|
@ -5,6 +5,93 @@ on:
|
||||||
branches: [master]
|
branches: [master]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
build_and_test_nightly:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
target:
|
||||||
|
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
|
||||||
|
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
||||||
|
- { name: Windows, os: windows-2022, triple: x86_64-pc-windows-msvc }
|
||||||
|
version:
|
||||||
|
- nightly
|
||||||
|
|
||||||
|
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
||||||
|
runs-on: ${{ matrix.target.os }}
|
||||||
|
|
||||||
|
env:
|
||||||
|
CI: 1
|
||||||
|
CARGO_INCREMENTAL: 0
|
||||||
|
VCPKGRS_DYNAMIC: 1
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# install OpenSSL on Windows
|
||||||
|
# TODO: GitHub actions docs state that OpenSSL is
|
||||||
|
# already installed on these Windows machines somewhere
|
||||||
|
- name: Set vcpkg root
|
||||||
|
if: matrix.target.triple == 'x86_64-pc-windows-msvc'
|
||||||
|
run: echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||||
|
- name: Install OpenSSL
|
||||||
|
if: matrix.target.triple == 'x86_64-pc-windows-msvc'
|
||||||
|
run: vcpkg install openssl:x64-windows
|
||||||
|
|
||||||
|
- name: Install ${{ matrix.version }}
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||||
|
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.2.0
|
||||||
|
|
||||||
|
- name: Install cargo-hack
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: install
|
||||||
|
args: cargo-hack
|
||||||
|
|
||||||
|
- name: check minimal
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with: { command: ci-check-min }
|
||||||
|
|
||||||
|
- name: check default
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with: { command: ci-check-default }
|
||||||
|
|
||||||
|
- name: tests
|
||||||
|
timeout-minutes: 60
|
||||||
|
run: |
|
||||||
|
cargo test --lib --tests -p=actix-router --all-features
|
||||||
|
cargo test --lib --tests -p=actix-http --all-features
|
||||||
|
cargo test --lib --tests -p=actix-web --features=rustls,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls
|
||||||
|
cargo test --lib --tests -p=actix-web-codegen --all-features
|
||||||
|
cargo test --lib --tests -p=awc --all-features
|
||||||
|
cargo test --lib --tests -p=actix-http-test --all-features
|
||||||
|
cargo test --lib --tests -p=actix-test --all-features
|
||||||
|
cargo test --lib --tests -p=actix-files
|
||||||
|
cargo test --lib --tests -p=actix-multipart --all-features
|
||||||
|
cargo test --lib --tests -p=actix-web-actors --all-features
|
||||||
|
|
||||||
|
- name: tests (io-uring)
|
||||||
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
|
timeout-minutes: 60
|
||||||
|
run: >
|
||||||
|
sudo bash -c "ulimit -Sl 512
|
||||||
|
&& ulimit -Hl 512
|
||||||
|
&& PATH=$PATH:/usr/share/rust/.cargo/bin
|
||||||
|
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo test --lib --tests -p=actix-files --all-features"
|
||||||
|
|
||||||
|
- name: Clear the cargo caches
|
||||||
|
run: |
|
||||||
|
cargo install cargo-cache --version 0.6.3 --no-default-features --features ci-autoclean
|
||||||
|
cargo-cache
|
||||||
|
|
||||||
ci_feature_powerset_check:
|
ci_feature_powerset_check:
|
||||||
name: Verify Feature Combinations
|
name: Verify Feature Combinations
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
@ -18,7 +18,6 @@ jobs:
|
||||||
version:
|
version:
|
||||||
- 1.54.0 # MSRV
|
- 1.54.0 # MSRV
|
||||||
- stable
|
- stable
|
||||||
- nightly
|
|
||||||
|
|
||||||
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
||||||
runs-on: ${{ matrix.target.os }}
|
runs-on: ${{ matrix.target.os }}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||

|

|
||||||
[](https://deps.rs/crate/actix-web/4.0.0-beta.18)
|
[](https://deps.rs/crate/actix-web/4.0.0-beta.18)
|
||||||
<br />
|
<br />
|
||||||
[](https://github.com/actix/actix-web/actions)
|
[](https://github.com/actix/actix-web/actions/workflows/ci.yml)
|
||||||
[](https://codecov.io/gh/actix/actix-web)
|
[](https://codecov.io/gh/actix/actix-web)
|
||||||

|

|
||||||
[](https://discord.gg/NWpN5mmg3x)
|
[](https://discord.gg/NWpN5mmg3x)
|
||||||
|
|
|
@ -109,6 +109,7 @@ impl<T> App<T> {
|
||||||
/// .route("/", web::get().to(handler))
|
/// .route("/", web::get().to(handler))
|
||||||
/// })
|
/// })
|
||||||
/// ```
|
/// ```
|
||||||
|
#[doc(alias = "manage")]
|
||||||
pub fn app_data<U: 'static>(mut self, ext: U) -> Self {
|
pub fn app_data<U: 'static>(mut self, ext: U) -> Self {
|
||||||
self.extensions.insert(ext);
|
self.extensions.insert(ext);
|
||||||
self
|
self
|
||||||
|
|
45
src/data.rs
45
src/data.rs
|
@ -19,23 +19,32 @@ pub(crate) trait DataFactory {
|
||||||
pub(crate) type FnDataFactory =
|
pub(crate) type FnDataFactory =
|
||||||
Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>;
|
Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>;
|
||||||
|
|
||||||
/// Application data.
|
/// Application data wrapper and extractor.
|
||||||
///
|
///
|
||||||
/// Application level data is a piece of arbitrary data attached to the app, scope, or resource.
|
/// # Setting Data
|
||||||
/// Application data is available to all routes and can be added during the application
|
/// Data is set using the `app_data` methods on `App`, `Scope`, and `Resource`. If data is wrapped
|
||||||
/// configuration process via `App::data()`.
|
/// in this `Data` type for those calls, it can be used as an extractor.
|
||||||
///
|
///
|
||||||
/// Application data can be accessed by using `Data<T>` extractor where `T` is data type.
|
/// Note that `Data` should be constructed _outside_ the `HttpServer::new` closure if shared,
|
||||||
|
/// potentially mutable state is desired. `Data` is cheap to clone; internally, it uses an `Arc`.
|
||||||
///
|
///
|
||||||
/// **Note**: HTTP server accepts an application factory rather than an application instance. HTTP
|
/// See also [`App::app_data`](crate::App::app_data), [`Scope::app_data`](crate::Scope::app_data),
|
||||||
/// server constructs an application instance for each thread, thus application data must be
|
/// and [`Resource::app_data`](crate::Resource::app_data).
|
||||||
/// constructed multiple times. If you want to share data between different threads, a shareable
|
///
|
||||||
/// object should be used, e.g. `Send + Sync`. Application data does not need to be `Send`
|
/// # Extracting `Data`
|
||||||
/// or `Sync`. Internally `Data` contains an `Arc`.
|
/// Since the Actix Web router layers application data, the returned object will reference the
|
||||||
|
/// "closest" instance of the type. For example, if an `App` stores a `u32`, a nested `Scope`
|
||||||
|
/// also stores a `u32`, and the delegated request handler falls within that `Scope`, then
|
||||||
|
/// extracting a `web::<Data<u32>>` for that handler will return the `Scope`'s instance.
|
||||||
|
/// However, using the same router set up and a request that does not get captured by the `Scope`,
|
||||||
|
/// `web::<Data<u32>>` would return the `App`'s instance.
|
||||||
///
|
///
|
||||||
/// If route data is not set for a handler, using `Data<T>` extractor would cause a `500 Internal
|
/// If route data is not set for a handler, using `Data<T>` extractor would cause a `500 Internal
|
||||||
/// Server Error` response.
|
/// Server Error` response.
|
||||||
///
|
///
|
||||||
|
/// See also [`HttpRequest::app_data`]
|
||||||
|
/// and [`ServiceRequest::app_data`](crate::dev::ServiceRequest::app_data).
|
||||||
|
///
|
||||||
/// # Unsized Data
|
/// # Unsized Data
|
||||||
/// For types that are unsized, most commonly `dyn T`, `Data` can wrap these types by first
|
/// For types that are unsized, most commonly `dyn T`, `Data` can wrap these types by first
|
||||||
/// constructing an `Arc<dyn T>` and using the `From` implementation to convert it.
|
/// constructing an `Arc<dyn T>` and using the `From` implementation to convert it.
|
||||||
|
@ -79,6 +88,7 @@ pub(crate) type FnDataFactory =
|
||||||
/// .route("/index.html", web::get().to(index))
|
/// .route("/index.html", web::get().to(index))
|
||||||
/// .route("/index-alt.html", web::get().to(index_alt));
|
/// .route("/index-alt.html", web::get().to(index_alt));
|
||||||
/// ```
|
/// ```
|
||||||
|
#[doc(alias = "state")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Data<T: ?Sized>(Arc<T>);
|
pub struct Data<T: ?Sized>(Arc<T>);
|
||||||
|
|
||||||
|
@ -90,12 +100,12 @@ impl<T> Data<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> Data<T> {
|
impl<T: ?Sized> Data<T> {
|
||||||
/// Get reference to inner app data.
|
/// Returns reference to inner `T`.
|
||||||
pub fn get_ref(&self) -> &T {
|
pub fn get_ref(&self) -> &T {
|
||||||
self.0.as_ref()
|
self.0.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to the internal Arc<T>
|
/// Unwraps to the internal `Arc<T>`
|
||||||
pub fn into_inner(self) -> Arc<T> {
|
pub fn into_inner(self) -> Arc<T> {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
@ -143,13 +153,16 @@ impl<T: ?Sized + 'static> FromRequest for Data<T> {
|
||||||
ok(st.clone())
|
ok(st.clone())
|
||||||
} else {
|
} else {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Failed to construct App-level Data extractor. \
|
"Failed to extract `Data<{}>` for `{}` handler. For the Data extractor to work \
|
||||||
Request path: {:?} (type: {})",
|
correctly, wrap the data with `Data::new()` and pass it to `App::app_data()`. \
|
||||||
req.path(),
|
Ensure that types align in both the set and retrieve calls.",
|
||||||
type_name::<T>(),
|
type_name::<T>(),
|
||||||
|
req.match_name().unwrap_or_else(|| req.path())
|
||||||
);
|
);
|
||||||
|
|
||||||
err(ErrorInternalServerError(
|
err(ErrorInternalServerError(
|
||||||
"App data is not configured, to configure construct it with web::Data::new() and pass it to App::app_data()",
|
"Requested application data is not configured correctly. \
|
||||||
|
View/enable debug logs for more details.",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,14 +266,34 @@ impl HttpRequest {
|
||||||
self.app_state().config()
|
self.app_state().config()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an application data object stored with `App::data` or `App::app_data`
|
/// Retrieves a piece of application state.
|
||||||
/// methods during application configuration.
|
|
||||||
///
|
///
|
||||||
/// If `App::data` was used to store object, use `Data<T>`:
|
/// Extracts any object stored with [`App::app_data()`](crate::App::app_data) (or the
|
||||||
|
/// counterpart methods on [`Scope`](crate::Scope::app_data) and
|
||||||
|
/// [`Resource`](crate::Resource::app_data)) during application configuration.
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// Since the Actix Web router layers application data, the returned object will reference the
|
||||||
/// let opt_t = req.app_data::<Data<T>>();
|
/// "closest" instance of the type. For example, if an `App` stores a `u32`, a nested `Scope`
|
||||||
|
/// also stores a `u32`, and the delegated request handler falls within that `Scope`, then
|
||||||
|
/// calling `.app_data::<u32>()` on an `HttpRequest` within that handler will return the
|
||||||
|
/// `Scope`'s instance. However, using the same router set up and a request that does not get
|
||||||
|
/// captured by the `Scope`, `.app_data::<u32>()` would return the `App`'s instance.
|
||||||
|
///
|
||||||
|
/// If the state was stored using the [`Data`] wrapper, then it must also be retrieved using
|
||||||
|
/// this same type.
|
||||||
|
///
|
||||||
|
/// See also the [`Data`] extractor.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```no_run
|
||||||
|
/// # use actix_web::{test::TestRequest, web::Data};
|
||||||
|
/// # let req = TestRequest::default().to_http_request();
|
||||||
|
/// # type T = u32;
|
||||||
|
/// let opt_t: Option<&Data<T>> = req.app_data::<Data<T>>();
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`Data`]: crate::web::Data
|
||||||
|
#[doc(alias = "state")]
|
||||||
pub fn app_data<T: 'static>(&self) -> Option<&T> {
|
pub fn app_data<T: 'static>(&self) -> Option<&T> {
|
||||||
for container in self.inner.app_data.iter().rev() {
|
for container in self.inner.app_data.iter().rev() {
|
||||||
if let Some(data) = container.get::<T>() {
|
if let Some(data) = container.get::<T>() {
|
||||||
|
|
|
@ -195,6 +195,7 @@ where
|
||||||
/// .route(web::get().to(handler))
|
/// .route(web::get().to(handler))
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
|
#[doc(alias = "manage")]
|
||||||
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
||||||
self.app_data
|
self.app_data
|
||||||
.get_or_insert_with(Extensions::new)
|
.get_or_insert_with(Extensions::new)
|
||||||
|
|
|
@ -154,6 +154,7 @@ where
|
||||||
/// .route("/", web::get().to(handler))
|
/// .route("/", web::get().to(handler))
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
|
#[doc(alias = "manage")]
|
||||||
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
||||||
self.app_data
|
self.app_data
|
||||||
.get_or_insert_with(Extensions::new)
|
.get_or_insert_with(Extensions::new)
|
||||||
|
|
Loading…
Reference in New Issue