mirror of
https://github.com/fafhrd91/actix-net
synced 2025-08-12 12:17:08 +02:00
Compare commits
70 Commits
server-v2.
...
utils-v3.0
Author | SHA1 | Date | |
---|---|---|---|
|
d5a9a6a1c5 | ||
|
ade71b7bd3 | ||
|
cb83922b29 | ||
|
25209f5bd8 | ||
|
c4a0f37d0c | ||
|
0e649329b9 | ||
|
66756bc448 | ||
|
126ed4c2e3 | ||
|
283974f3e6 | ||
|
bf2aa3902c | ||
|
71b4e55c92 | ||
|
eb5fa30ada | ||
|
49a034259f | ||
|
3337f63b4e | ||
|
86ce140249 | ||
|
635aebe887 | ||
|
4c1e581a54 | ||
|
dc67ba770d | ||
|
855e3f96fe | ||
|
737b438f73 | ||
|
0cd70b0536 | ||
|
4b6a581ef3 | ||
|
3e132d2bc6 | ||
|
c5d6174cec | ||
|
77d4a69b2f | ||
|
ae5377fd6e | ||
|
bd9bda0504 | ||
|
41ed48219d | ||
|
7804ed12eb | ||
|
2a54065fae | ||
|
217cbd2228 | ||
|
d229c1e886 | ||
|
6792f799a6 | ||
|
72481313cc | ||
|
59b629c74b | ||
|
7988694242 | ||
|
b8a7741524 | ||
|
5e290d76f8 | ||
|
0edb64575f | ||
|
941f67dec9 | ||
|
3e624b8376 | ||
|
26446fdbad | ||
|
b7b7bd2cbf | ||
|
637625f9b7 | ||
|
b1d5d85e72 | ||
|
ed2c07b304 | ||
|
4fe7fec5ef | ||
|
4c9ee88ec4 | ||
|
9ec3cc0fe7 | ||
|
01e0f922de | ||
|
10d3bb6d0d | ||
|
3ba4eafde5 | ||
|
5faa98f6d2 | ||
|
b552d847ed | ||
|
5058e2d14e | ||
|
ae9afd4de7 | ||
|
01d2f18f68 | ||
|
e92b5aaf31 | ||
|
459a6d1b02 | ||
|
9935883905 | ||
|
89a4c2ee27 | ||
|
a4681831a7 | ||
|
5d2da0fdc7 | ||
|
ef18a8342e | ||
|
621deba990 | ||
|
6a9f13c8b4 | ||
|
705b31230f | ||
|
eb490a9125 | ||
|
90f205a465 | ||
|
3a3d654cea |
@@ -14,13 +14,10 @@ ci-check = "hack --workspace --feature-powerset --exclude-features=io-uring chec
|
||||
ci-check-linux = "hack --workspace --feature-powerset check --tests --examples"
|
||||
|
||||
# tests avoiding io-uring feature
|
||||
ci-test = " hack --feature-powerset --exclude=actix-rt --exclude=actix-server --exclude-features=io-uring test --workspace --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test-rt = " hack --feature-powerset --exclude-features=io-uring test --package=actix-rt --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test-server = "hack --feature-powerset --exclude-features=io-uring test --package=actix-server --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test = "hack --feature-powerset --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
||||
|
||||
# tests avoiding io-uring feature on Windows
|
||||
ci-test-win = "hack --feature-powerset --depth 2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
||||
|
||||
# test with io-uring feature
|
||||
ci-test-rt-linux = " hack --feature-powerset test --package=actix-rt --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test-server-linux = "hack --feature-powerset test --package=actix-server --lib --tests --no-fail-fast -- --nocapture"
|
||||
|
||||
# test lower msrv
|
||||
ci-test-lower-msrv = "hack --workspace --exclude=actix-server --exclude=actix-tls --feature-powerset test --lib --tests --no-fail-fast -- --nocapture"
|
||||
ci-test-linux = " hack --feature-powerset test --lib --tests --no-fail-fast -- --nocapture"
|
||||
|
210
.github/workflows/ci-master.yml
vendored
Normal file
210
.github/workflows/ci-master.yml
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
name: CI (master only)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
|
||||
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-latest, triple: x86_64-pc-windows-msvc }
|
||||
- { name: Windows (MinGW), os: windows-latest, triple: x86_64-pc-windows-gnu }
|
||||
- { name: Windows (32-bit), os: windows-latest, triple: i686-pc-windows-msvc }
|
||||
version:
|
||||
- nightly
|
||||
|
||||
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
||||
runs-on: ${{ matrix.target.os }}
|
||||
|
||||
env:
|
||||
VCPKGRS_DYNAMIC: 1
|
||||
|
||||
steps:
|
||||
- name: Setup Routing
|
||||
if: matrix.target.os == 'macos-latest'
|
||||
run: sudo ifconfig lo0 alias 127.0.0.3
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# install OpenSSL on Windows
|
||||
- name: Set vcpkg root
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-msvc' || matrix.target.triple == 'i686-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 OpenSSL
|
||||
if: matrix.target.triple == 'i686-pc-windows-msvc'
|
||||
run: vcpkg install openssl:x86-windows
|
||||
|
||||
- name: Install ${{ matrix.version }}
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.version }}-${{ matrix.target.triple }}
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
# - name: Install MSYS2
|
||||
# if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
# uses: msys2/setup-msys2@v2
|
||||
# - name: Install MinGW Packages
|
||||
# if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
# run: |
|
||||
# msys2 -c 'pacman -Sy --noconfirm pacman'
|
||||
# msys2 -c 'pacman --noconfirm -S base-devel pkg-config'
|
||||
|
||||
# - 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 lib
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-lib }
|
||||
- name: check lib
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-lib-linux }
|
||||
- name: check lib
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-min }
|
||||
|
||||
- name: check full
|
||||
# TODO: compile OpenSSL and run tests on MinGW
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check }
|
||||
- name: check all
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-linux }
|
||||
|
||||
- name: tests
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
run: cargo ci-test
|
||||
- name: tests
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux"
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
||||
cargo-cache
|
||||
|
||||
coverage:
|
||||
name: coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust (nightly)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
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.3.0
|
||||
|
||||
- name: Generate coverage file
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
cargo install cargo-tarpaulin
|
||||
cargo tarpaulin --out Xml --verbose
|
||||
- name: Upload to Codecov
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: codecov/codecov-action@v1
|
||||
with: { file: cobertura.xml }
|
||||
|
||||
minimal-versions:
|
||||
name: minimal versions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust (nightly)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
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.3.0
|
||||
|
||||
- name: Install cargo-minimal-versions
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-minimal-versions
|
||||
|
||||
- name: Install cargo-hack
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-hack
|
||||
|
||||
- name: Check With Minimal Versions
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: minimal-versions
|
||||
args: check
|
||||
|
||||
nextest:
|
||||
name: nextest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
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.3.0
|
||||
|
||||
- name: Install cargo-nextest
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-nextest
|
||||
|
||||
- name: Test with cargo-nextest
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: nextest
|
||||
args: run
|
78
.github/workflows/ci.yml
vendored
78
.github/workflows/ci.yml
vendored
@@ -18,9 +18,8 @@ jobs:
|
||||
- { name: Windows (MinGW), os: windows-latest, triple: x86_64-pc-windows-gnu }
|
||||
- { name: Windows (32-bit), os: windows-latest, triple: i686-pc-windows-msvc }
|
||||
version:
|
||||
- 1.52.0 # MSRV for -server and -tls
|
||||
- 1.57.0
|
||||
- stable
|
||||
- nightly
|
||||
|
||||
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
||||
runs-on: ${{ matrix.target.os }}
|
||||
@@ -74,6 +73,10 @@ jobs:
|
||||
command: install
|
||||
args: cargo-hack
|
||||
|
||||
- name: Generate Cargo.lock
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: generate-lockfile }
|
||||
|
||||
- name: check lib
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
@@ -88,7 +91,7 @@ jobs:
|
||||
if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-min }
|
||||
|
||||
|
||||
- name: check full
|
||||
# TODO: compile OpenSSL and run tests on MinGW
|
||||
if: >
|
||||
@@ -101,80 +104,23 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with: { command: ci-check-linux }
|
||||
|
||||
- name: tests
|
||||
if: matrix.target.os == 'macos-latest'
|
||||
run: cargo ci-test
|
||||
- name: tests
|
||||
if: >
|
||||
matrix.target.os != 'ubuntu-latest'
|
||||
matrix.target.os == 'windows-latest'
|
||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||
run: |
|
||||
cargo ci-test
|
||||
cargo ci-test-rt
|
||||
cargo ci-test-server
|
||||
run: cargo ci-test-win
|
||||
- name: tests
|
||||
if: matrix.target.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rt-linux && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-server-linux"
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux"
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
||||
cargo-cache
|
||||
|
||||
build_and_test_lower_msrv:
|
||||
name: Linux / 1.46 (lower MSRV)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install 1.46.0 # MSRV for all but -server and -tls
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.46.0-x86_64-unknown-linux-gnu
|
||||
profile: minimal
|
||||
override: true
|
||||
|
||||
- name: Install cargo-hack
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: install
|
||||
args: cargo-hack
|
||||
|
||||
- name: tests
|
||||
run: |
|
||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=1.46 cargo ci-test-lower-msrv"
|
||||
|
||||
- name: Clear the cargo caches
|
||||
run: |
|
||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
||||
cargo-cache
|
||||
|
||||
coverage:
|
||||
name: coverage
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install Rust (nightly)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable-x86_64-unknown-linux-gnu
|
||||
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.3.0
|
||||
|
||||
- name: Generate coverage file
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: |
|
||||
cargo install cargo-tarpaulin
|
||||
cargo tarpaulin --out Xml --verbose
|
||||
- name: Upload to Codecov
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: codecov/codecov-action@v1
|
||||
with: { file: cobertura.xml }
|
||||
|
||||
rustdoc:
|
||||
name: rustdoc
|
||||
|
26
README.md
26
README.md
@@ -2,29 +2,25 @@
|
||||
|
||||
> A collection of lower-level libraries for composable network services.
|
||||
|
||||

|
||||
[](https://github.com/actix/actix-net/actions/workflows/ci.yml)
|
||||
[](https://codecov.io/gh/actix/actix-net)
|
||||
[](https://discord.gg/NWpN5mmg3x)
|
||||
[](https://deps.rs/repo/github/actix/actix-net)
|
||||
|
||||
## Build statuses
|
||||
| Platform | Build Status |
|
||||
| ---------------- | ------------ |
|
||||
| Linux | [](https://github.com/actix/actix-net/actions?query=workflow%3A"CI+(Linux)") |
|
||||
| macOS | [](https://github.com/actix/actix-net/actions?query=workflow%3A"CI+(macOS)") |
|
||||
| Windows | [](https://github.com/actix/actix-net/actions?query=workflow%3A"CI+(Windows)") |
|
||||
| Windows (MinGW) | [](https://github.com/actix/actix-net/actions?query=workflow%3A"CI+(Windows-mingw)") |
|
||||
## Examples
|
||||
|
||||
## Example
|
||||
See `actix-server/examples` and `actix-tls/examples` for some basic examples.
|
||||
See example folders for [`actix-server`](./actix-server/examples) and [`actix-tls`](./actix-tls/examples).
|
||||
|
||||
### MSRV
|
||||
This repo's Minimum Supported Rust Version (MSRV) is 1.46.0.
|
||||
## MSRV
|
||||
|
||||
Most crates in this repo's have a Minimum Supported Rust Version (MSRV) of 1.49.0. Only `actix-tls` and `actix-server` have MSRV of 1.54.0. As a policy, we permit MSRV increases in non-breaking releases.
|
||||
|
||||
## License
|
||||
This project is licensed under either of
|
||||
|
||||
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
|
||||
* MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
|
||||
The crates in repo are licensed under either of:
|
||||
|
||||
- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
|
||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
|
||||
|
||||
at your option.
|
||||
|
||||
|
@@ -1,71 +1,89 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.5.1 - 2022-03-15
|
||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
[#451]: https://github.com/actix/actix-net/pull/451
|
||||
|
||||
|
||||
## 0.5.0 - 2022-02-15
|
||||
- Updated `tokio-util` dependency to `0.7.0`. [#446]
|
||||
|
||||
[#446]: https://github.com/actix/actix-net/pull/446
|
||||
|
||||
|
||||
## 0.4.2 - 2021-12-31
|
||||
- No significant changes since `0.4.1`.
|
||||
|
||||
|
||||
## 0.4.1 - 2021-11-05
|
||||
* Added `LinesCodec.` [#338]
|
||||
* `Framed::poll_ready` flushes when the buffer is full. [#409]
|
||||
- Added `LinesCodec.` [#338]
|
||||
- `Framed::poll_ready` flushes when the buffer is full. [#409]
|
||||
|
||||
[#338]: https://github.com/actix/actix-net/pull/338
|
||||
[#409]: https://github.com/actix/actix-net/pull/409
|
||||
|
||||
|
||||
## 0.4.0 - 2021-04-20
|
||||
* No significant changes since v0.4.0-beta.1.
|
||||
- No significant changes since v0.4.0-beta.1.
|
||||
|
||||
|
||||
## 0.4.0-beta.1 - 2020-12-28
|
||||
* Replace `pin-project` with `pin-project-lite`. [#237]
|
||||
* Upgrade `tokio` dependency to `1`. [#237]
|
||||
* Upgrade `tokio-util` dependency to `0.6`. [#237]
|
||||
* Upgrade `bytes` dependency to `1`. [#237]
|
||||
- Replace `pin-project` with `pin-project-lite`. [#237]
|
||||
- Upgrade `tokio` dependency to `1`. [#237]
|
||||
- Upgrade `tokio-util` dependency to `0.6`. [#237]
|
||||
- Upgrade `bytes` dependency to `1`. [#237]
|
||||
|
||||
[#237]: https://github.com/actix/actix-net/pull/237
|
||||
|
||||
|
||||
## 0.3.0 - 2020-08-23
|
||||
* No changes from beta 2.
|
||||
- No changes from beta 2.
|
||||
|
||||
|
||||
## 0.3.0-beta.2 - 2020-08-19
|
||||
* Remove unused type parameter from `Framed::replace_codec`.
|
||||
- Remove unused type parameter from `Framed::replace_codec`.
|
||||
|
||||
|
||||
## 0.3.0-beta.1 - 2020-08-19
|
||||
* Use `.advance()` instead of `.split_to()`.
|
||||
* Upgrade `tokio-util` to `0.3`.
|
||||
* Improve `BytesCodec::encode()` performance.
|
||||
* Simplify `BytesCodec::decode()`.
|
||||
* Rename methods on `Framed` to better describe their use.
|
||||
* Add method on `Framed` to get a pinned reference to the underlying I/O.
|
||||
* Add method on `Framed` check emptiness of read buffer.
|
||||
- Use `.advance()` instead of `.split_to()`.
|
||||
- Upgrade `tokio-util` to `0.3`.
|
||||
- Improve `BytesCodec::encode()` performance.
|
||||
- Simplify `BytesCodec::decode()`.
|
||||
- Rename methods on `Framed` to better describe their use.
|
||||
- Add method on `Framed` to get a pinned reference to the underlying I/O.
|
||||
- Add method on `Framed` check emptiness of read buffer.
|
||||
|
||||
|
||||
## 0.2.0 - 2019-12-10
|
||||
* Use specific futures dependencies.
|
||||
- Use specific futures dependencies.
|
||||
|
||||
|
||||
## 0.2.0-alpha.4
|
||||
* Fix buffer remaining capacity calculation.
|
||||
- Fix buffer remaining capacity calculation.
|
||||
|
||||
|
||||
## 0.2.0-alpha.3
|
||||
* Use tokio 0.2.
|
||||
* Fix low/high watermark for write/read buffers.
|
||||
- Use tokio 0.2.
|
||||
- Fix low/high watermark for write/read buffers.
|
||||
|
||||
|
||||
## 0.2.0-alpha.2
|
||||
* Migrated to `std::future`.
|
||||
- Migrated to `std::future`.
|
||||
|
||||
|
||||
## 0.1.2 - 2019-03-27
|
||||
* Added `Framed::map_io()` method.
|
||||
- Added `Framed::map_io()` method.
|
||||
|
||||
|
||||
## 0.1.1 - 2019-03-06
|
||||
* Added `FramedParts::with_read_buffer()` method.
|
||||
- Added `FramedParts::with_read_buffer()` method.
|
||||
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
* Move codec to separate crate.
|
||||
- Move codec to separate crate.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-codec"
|
||||
version = "0.4.1"
|
||||
version = "0.5.1"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
@@ -17,15 +17,15 @@ name = "actix_codec"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.2.1"
|
||||
bitflags = "1.2"
|
||||
bytes = "1"
|
||||
futures-core = { version = "0.3.7", default-features = false }
|
||||
futures-sink = { version = "0.3.7", default-features = false }
|
||||
log = "0.4"
|
||||
memchr = "2.3"
|
||||
pin-project-lite = "0.2"
|
||||
tokio = "1.5.1"
|
||||
tokio-util = { version = "0.6", features = ["codec", "io"] }
|
||||
tokio = "1.13.1"
|
||||
tokio-util = { version = "0.7", features = ["codec", "io"] }
|
||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.3", features = ["html_reports"] }
|
||||
|
@@ -156,7 +156,7 @@ impl<T, U> Framed<T, U> {
|
||||
}
|
||||
|
||||
impl<T, U> Framed<T, U> {
|
||||
/// Serialize item and Write to the inner buffer
|
||||
/// Serialize item and write to the inner buffer
|
||||
pub fn write<I>(mut self: Pin<&mut Self>, item: I) -> Result<(), <U as Encoder<I>>::Error>
|
||||
where
|
||||
T: AsyncWrite,
|
||||
@@ -193,18 +193,18 @@ impl<T, U> Framed<T, U> {
|
||||
match this.codec.decode_eof(this.read_buf) {
|
||||
Ok(Some(frame)) => return Poll::Ready(Some(Ok(frame))),
|
||||
Ok(None) => return Poll::Ready(None),
|
||||
Err(e) => return Poll::Ready(Some(Err(e))),
|
||||
Err(err) => return Poll::Ready(Some(Err(err))),
|
||||
}
|
||||
}
|
||||
|
||||
log::trace!("attempting to decode a frame");
|
||||
tracing::trace!("attempting to decode a frame");
|
||||
|
||||
match this.codec.decode(this.read_buf) {
|
||||
Ok(Some(frame)) => {
|
||||
log::trace!("frame decoded from buffer");
|
||||
tracing::trace!("frame decoded from buffer");
|
||||
return Poll::Ready(Some(Ok(frame)));
|
||||
}
|
||||
Err(e) => return Poll::Ready(Some(Err(e))),
|
||||
Err(err) => return Poll::Ready(Some(Err(err))),
|
||||
_ => (), // Need more data
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ impl<T, U> Framed<T, U> {
|
||||
|
||||
let cnt = match tokio_util::io::poll_read_buf(this.io, cx, this.read_buf) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(Err(e)) => return Poll::Ready(Some(Err(e.into()))),
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err.into()))),
|
||||
Poll::Ready(Ok(cnt)) => cnt,
|
||||
};
|
||||
|
||||
@@ -242,10 +242,10 @@ impl<T, U> Framed<T, U> {
|
||||
U: Encoder<I>,
|
||||
{
|
||||
let mut this = self.as_mut().project();
|
||||
log::trace!("flushing framed transport");
|
||||
tracing::trace!("flushing framed transport");
|
||||
|
||||
while !this.write_buf.is_empty() {
|
||||
log::trace!("writing; remaining={}", this.write_buf.len());
|
||||
tracing::trace!("writing; remaining={}", this.write_buf.len());
|
||||
|
||||
let n = ready!(this.io.as_mut().poll_write(cx, this.write_buf))?;
|
||||
|
||||
@@ -264,7 +264,7 @@ impl<T, U> Framed<T, U> {
|
||||
// Try flushing the underlying IO
|
||||
ready!(this.io.poll_flush(cx))?;
|
||||
|
||||
log::trace!("framed transport flushed");
|
||||
tracing::trace!("framed transport flushed");
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
|
@@ -7,8 +7,8 @@
|
||||
//! [`Sink`]: futures_sink::Sink
|
||||
//! [`Stream`]: futures_core::Stream
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style, future_incompatible)]
|
||||
#![warn(missing_docs)]
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
|
||||
@@ -16,10 +16,10 @@ mod bcodec;
|
||||
mod framed;
|
||||
mod lines;
|
||||
|
||||
pub use self::bcodec::BytesCodec;
|
||||
pub use self::framed::{Framed, FramedParts};
|
||||
pub use self::lines::LinesCodec;
|
||||
|
||||
pub use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||
pub use tokio_util::codec::{Decoder, Encoder};
|
||||
pub use tokio_util::io::poll_read_buf;
|
||||
|
||||
pub use self::bcodec::BytesCodec;
|
||||
pub use self::framed::{Framed, FramedParts};
|
||||
pub use self::lines::LinesCodec;
|
||||
|
@@ -7,8 +7,8 @@ use super::{Decoder, Encoder};
|
||||
|
||||
/// Lines codec. Reads/writes line delimited strings.
|
||||
///
|
||||
/// Will split input up by LF or CRLF delimiters. I.e. carriage return characters at the end of
|
||||
/// lines are not preserved.
|
||||
/// Will split input up by LF or CRLF delimiters. Carriage return characters at the end of lines are
|
||||
/// not preserved.
|
||||
#[derive(Debug, Copy, Clone, Default)]
|
||||
#[non_exhaustive]
|
||||
pub struct LinesCodec;
|
||||
|
@@ -1,12 +1,16 @@
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
io::{self, Write},
|
||||
pin::Pin,
|
||||
task::{
|
||||
Context,
|
||||
Poll::{self, Pending, Ready},
|
||||
},
|
||||
};
|
||||
|
||||
use actix_codec::*;
|
||||
use bytes::Buf;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use bytes::{Buf as _, BufMut as _, BytesMut};
|
||||
use futures_sink::Sink;
|
||||
use std::collections::VecDeque;
|
||||
use std::io::{self, Write};
|
||||
use std::pin::Pin;
|
||||
use std::task::Poll::{Pending, Ready};
|
||||
use std::task::{Context, Poll};
|
||||
use tokio_test::{assert_ready, task};
|
||||
|
||||
macro_rules! bilateral {
|
||||
@@ -50,7 +54,7 @@ impl Write for Bilateral {
|
||||
assert_eq!(&data[..], &src[..data.len()]);
|
||||
Ok(data.len())
|
||||
}
|
||||
Some(Err(e)) => Err(e),
|
||||
Some(Err(err)) => Err(err),
|
||||
None => panic!("unexpected write; {:?}", src),
|
||||
}
|
||||
}
|
||||
@@ -67,13 +71,13 @@ impl AsyncWrite for Bilateral {
|
||||
buf: &[u8],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
match Pin::get_mut(self).write(buf) {
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Pending,
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Pending,
|
||||
other => Ready(other),
|
||||
}
|
||||
}
|
||||
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||
match Pin::get_mut(self).flush() {
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Pending,
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Pending,
|
||||
other => Ready(other),
|
||||
}
|
||||
}
|
||||
@@ -99,8 +103,8 @@ impl AsyncRead for Bilateral {
|
||||
buf.put_slice(&data);
|
||||
Ready(Ok(()))
|
||||
}
|
||||
Some(Err(ref e)) if e.kind() == WouldBlock => Pending,
|
||||
Some(Err(e)) => Ready(Err(e)),
|
||||
Some(Err(ref err)) if err.kind() == WouldBlock => Pending,
|
||||
Some(Err(err)) => Ready(Err(err)),
|
||||
None => Ready(Ok(())),
|
||||
}
|
||||
}
|
||||
|
@@ -1,46 +1,47 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.2.3 - 2021-10-19
|
||||
* Fix test macro in presence of other imports named "test". [#399]
|
||||
- Fix test macro in presence of other imports named "test". [#399]
|
||||
|
||||
[#399]: https://github.com/actix/actix-net/pull/399
|
||||
|
||||
|
||||
## 0.2.2 - 2021-10-14
|
||||
* Improve error recovery potential when macro input is invalid. [#391]
|
||||
* Allow custom `System`s on test macro. [#391]
|
||||
- Improve error recovery potential when macro input is invalid. [#391]
|
||||
- Allow custom `System`s on test macro. [#391]
|
||||
|
||||
[#391]: https://github.com/actix/actix-net/pull/391
|
||||
|
||||
|
||||
## 0.2.1 - 2021-02-02
|
||||
* Add optional argument `system` to `main` macro which can be used to specify the path to `actix_rt::System` (useful for re-exports). [#363]
|
||||
- Add optional argument `system` to `main` macro which can be used to specify the path to `actix_rt::System` (useful for re-exports). [#363]
|
||||
|
||||
[#363]: https://github.com/actix/actix-net/pull/363
|
||||
|
||||
|
||||
## 0.2.0 - 2021-02-02
|
||||
* Update to latest `actix_rt::System::new` signature. [#261]
|
||||
- Update to latest `actix_rt::System::new` signature. [#261]
|
||||
|
||||
[#261]: https://github.com/actix/actix-net/pull/261
|
||||
|
||||
|
||||
## 0.2.0-beta.1 - 2021-01-09
|
||||
* Remove `actix-reexport` feature. [#218]
|
||||
- Remove `actix-reexport` feature. [#218]
|
||||
|
||||
[#218]: https://github.com/actix/actix-net/pull/218
|
||||
|
||||
|
||||
## 0.1.3 - 2020-12-03
|
||||
* Add `actix-reexport` feature. [#218]
|
||||
- Add `actix-reexport` feature. [#218]
|
||||
|
||||
[#218]: https://github.com/actix/actix-net/pull/218
|
||||
|
||||
|
||||
## 0.1.2 - 2020-05-18
|
||||
* Forward actix_rt::test arguments to test function [#127]
|
||||
- Forward actix_rt::test arguments to test function [#127]
|
||||
|
||||
[#127]: https://github.com/actix/actix-net/pull/127
|
||||
|
@@ -9,6 +9,7 @@
|
||||
//! See docs for the [`#[test]`](macro@test) macro.
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(future_incompatible)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
|
||||
|
@@ -1,32 +1,55 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Add `#[track_caller]` attribute to `spawn` functions and methods. [#454]
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
[#454]: https://github.com/actix/actix-net/pull/454
|
||||
|
||||
|
||||
## 2.7.0 - 2022-03-08
|
||||
- Update `tokio-uring` dependency to `0.3.0`. [#448]
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
[#448]: https://github.com/actix/actix-net/pull/448
|
||||
|
||||
|
||||
## 2.6.0 - 2022-01-12
|
||||
- Update `tokio-uring` dependency to `0.2.0`. [#436]
|
||||
|
||||
[#436]: https://github.com/actix/actix-net/pull/436
|
||||
|
||||
|
||||
## 2.5.1 - 2021-12-31
|
||||
- Expose `System::with_tokio_rt` and `Arbiter::with_tokio_rt`. [#430]
|
||||
|
||||
[#430]: https://github.com/actix/actix-net/pull/430
|
||||
|
||||
|
||||
## 2.5.0 - 2021-11-22
|
||||
* Add `System::run_with_code` to allow retrieving the exit code on stop. [#411]
|
||||
- Add `System::run_with_code` to allow retrieving the exit code on stop. [#411]
|
||||
|
||||
[#411]: https://github.com/actix/actix-net/pull/411
|
||||
|
||||
|
||||
## 2.4.0 - 2021-11-05
|
||||
* Add `Arbiter::try_current` for situations where thread may or may not have Arbiter context. [#408]
|
||||
* Start io-uring with `System::new` when feature is enabled. [#395]
|
||||
- Add `Arbiter::try_current` for situations where thread may or may not have Arbiter context. [#408]
|
||||
- Start io-uring with `System::new` when feature is enabled. [#395]
|
||||
|
||||
[#395]: https://github.com/actix/actix-net/pull/395
|
||||
[#408]: https://github.com/actix/actix-net/pull/408
|
||||
|
||||
|
||||
## 2.3.0 - 2021-10-11
|
||||
* The `spawn` method can now resolve with non-unit outputs. [#369]
|
||||
* Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux. [#374]
|
||||
- The `spawn` method can now resolve with non-unit outputs. [#369]
|
||||
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux. [#374]
|
||||
|
||||
[#369]: https://github.com/actix/actix-net/pull/369
|
||||
[#374]: https://github.com/actix/actix-net/pull/374
|
||||
|
||||
|
||||
## 2.2.0 - 2021-03-29
|
||||
* **BREAKING** `ActixStream::{poll_read_ready, poll_write_ready}` methods now return
|
||||
- **BREAKING** `ActixStream::{poll_read_ready, poll_write_ready}` methods now return
|
||||
`Ready` object in ok variant. [#293]
|
||||
* Breakage is acceptable since `ActixStream` was not intended to be public.
|
||||
|
||||
@@ -34,51 +57,51 @@
|
||||
|
||||
|
||||
## 2.1.0 - 2021-02-24
|
||||
* Add `ActixStream` extension trait to include readiness methods. [#276]
|
||||
* Re-export `tokio::net::TcpSocket` in `net` module [#282]
|
||||
- Add `ActixStream` extension trait to include readiness methods. [#276]
|
||||
- Re-export `tokio::net::TcpSocket` in `net` module [#282]
|
||||
|
||||
[#276]: https://github.com/actix/actix-net/pull/276
|
||||
[#282]: https://github.com/actix/actix-net/pull/282
|
||||
|
||||
|
||||
## 2.0.2 - 2021-02-06
|
||||
* Add `Arbiter::handle` to get a handle of an owned Arbiter. [#274]
|
||||
* Add `System::try_current` for situations where actix may or may not be running a System. [#275]
|
||||
- Add `Arbiter::handle` to get a handle of an owned Arbiter. [#274]
|
||||
- Add `System::try_current` for situations where actix may or may not be running a System. [#275]
|
||||
|
||||
[#274]: https://github.com/actix/actix-net/pull/274
|
||||
[#275]: https://github.com/actix/actix-net/pull/275
|
||||
|
||||
|
||||
## 2.0.1 - 2021-02-06
|
||||
* Expose `JoinError` from Tokio. [#271]
|
||||
- Expose `JoinError` from Tokio. [#271]
|
||||
|
||||
[#271]: https://github.com/actix/actix-net/pull/271
|
||||
|
||||
|
||||
## 2.0.0 - 2021-02-02
|
||||
* Remove all Arbiter-local storage methods. [#262]
|
||||
* Re-export `tokio::pin`. [#262]
|
||||
- Remove all Arbiter-local storage methods. [#262]
|
||||
- Re-export `tokio::pin`. [#262]
|
||||
|
||||
[#262]: https://github.com/actix/actix-net/pull/262
|
||||
|
||||
|
||||
## 2.0.0-beta.3 - 2021-01-31
|
||||
* Remove `run_in_tokio`, `attach_to_tokio` and `AsyncSystemRunner`. [#253]
|
||||
* Return `JoinHandle` from `actix_rt::spawn`. [#253]
|
||||
* Remove old `Arbiter::spawn`. Implementation is now inlined into `actix_rt::spawn`. [#253]
|
||||
* Rename `Arbiter::{send => spawn}` and `Arbiter::{exec_fn => spawn_fn}`. [#253]
|
||||
* Remove `Arbiter::exec`. [#253]
|
||||
* Remove deprecated `Arbiter::local_join` and `Arbiter::is_running`. [#253]
|
||||
* `Arbiter::spawn` now accepts !Unpin futures. [#256]
|
||||
* `System::new` no longer takes arguments. [#257]
|
||||
* Remove `System::with_current`. [#257]
|
||||
* Remove `Builder`. [#257]
|
||||
* Add `System::with_init` as replacement for `Builder::run`. [#257]
|
||||
* Rename `System::{is_set => is_registered}`. [#257]
|
||||
* Add `ArbiterHandle` for sending messages to non-current-thread arbiters. [#257].
|
||||
* `System::arbiter` now returns an `&ArbiterHandle`. [#257]
|
||||
* `Arbiter::current` now returns an `ArbiterHandle` instead. [#257]
|
||||
* `Arbiter::join` now takes self by value. [#257]
|
||||
- Remove `run_in_tokio`, `attach_to_tokio` and `AsyncSystemRunner`. [#253]
|
||||
- Return `JoinHandle` from `actix_rt::spawn`. [#253]
|
||||
- Remove old `Arbiter::spawn`. Implementation is now inlined into `actix_rt::spawn`. [#253]
|
||||
- Rename `Arbiter::{send => spawn}` and `Arbiter::{exec_fn => spawn_fn}`. [#253]
|
||||
- Remove `Arbiter::exec`. [#253]
|
||||
- Remove deprecated `Arbiter::local_join` and `Arbiter::is_running`. [#253]
|
||||
- `Arbiter::spawn` now accepts !Unpin futures. [#256]
|
||||
- `System::new` no longer takes arguments. [#257]
|
||||
- Remove `System::with_current`. [#257]
|
||||
- Remove `Builder`. [#257]
|
||||
- Add `System::with_init` as replacement for `Builder::run`. [#257]
|
||||
- Rename `System::{is_set => is_registered}`. [#257]
|
||||
- Add `ArbiterHandle` for sending messages to non-current-thread arbiters. [#257].
|
||||
- `System::arbiter` now returns an `&ArbiterHandle`. [#257]
|
||||
- `Arbiter::current` now returns an `ArbiterHandle` instead. [#257]
|
||||
- `Arbiter::join` now takes self by value. [#257]
|
||||
|
||||
[#253]: https://github.com/actix/actix-net/pull/253
|
||||
[#254]: https://github.com/actix/actix-net/pull/254
|
||||
@@ -87,37 +110,37 @@
|
||||
|
||||
|
||||
## 2.0.0-beta.2 - 2021-01-09
|
||||
* Add `task` mod with re-export of `tokio::task::{spawn_blocking, yield_now, JoinHandle}` [#245]
|
||||
* Add default "macros" feature to allow faster compile times when using `default-features=false`.
|
||||
- Add `task` mod with re-export of `tokio::task::{spawn_blocking, yield_now, JoinHandle}` [#245]
|
||||
- Add default "macros" feature to allow faster compile times when using `default-features=false`.
|
||||
|
||||
[#245]: https://github.com/actix/actix-net/pull/245
|
||||
|
||||
|
||||
## 2.0.0-beta.1 - 2020-12-28
|
||||
* Add `System::attach_to_tokio` method. [#173]
|
||||
* Update `tokio` dependency to `1.0`. [#236]
|
||||
* Rename `time` module `delay_for` to `sleep`, `delay_until` to `sleep_until`, `Delay` to `Sleep`
|
||||
- Add `System::attach_to_tokio` method. [#173]
|
||||
- Update `tokio` dependency to `1.0`. [#236]
|
||||
- Rename `time` module `delay_for` to `sleep`, `delay_until` to `sleep_until`, `Delay` to `Sleep`
|
||||
to stay aligned with Tokio's naming. [#236]
|
||||
* Remove `'static` lifetime requirement for `Runtime::block_on` and `SystemRunner::block_on`.
|
||||
- Remove `'static` lifetime requirement for `Runtime::block_on` and `SystemRunner::block_on`.
|
||||
* These methods now accept `&self` when calling. [#236]
|
||||
* Remove `'static` lifetime requirement for `System::run` and `Builder::run`. [#236]
|
||||
* `Arbiter::spawn` now panics when `System` is not in scope. [#207]
|
||||
* Fix work load issue by removing `PENDING` thread local. [#207]
|
||||
- Remove `'static` lifetime requirement for `System::run` and `Builder::run`. [#236]
|
||||
- `Arbiter::spawn` now panics when `System` is not in scope. [#207]
|
||||
- Fix work load issue by removing `PENDING` thread local. [#207]
|
||||
|
||||
[#207]: https://github.com/actix/actix-net/pull/207
|
||||
[#236]: https://github.com/actix/actix-net/pull/236
|
||||
|
||||
|
||||
## 1.1.1 - 2020-04-30
|
||||
* Fix memory leak due to [#94] (see [#129] for more detail)
|
||||
- Fix memory leak due to [#94] (see [#129] for more detail)
|
||||
|
||||
[#129]: https://github.com/actix/actix-net/issues/129
|
||||
|
||||
|
||||
## 1.1.0 - 2020-04-08 _(YANKED)_
|
||||
* Expose `System::is_set` to check if current system has ben started [#99]
|
||||
* Add `Arbiter::is_running` to check if event loop is running [#124]
|
||||
* Add `Arbiter::local_join` associated function
|
||||
- Expose `System::is_set` to check if current system has ben started [#99]
|
||||
- Add `Arbiter::is_running` to check if event loop is running [#124]
|
||||
- Add `Arbiter::local_join` associated function
|
||||
to get be able to `await` for spawned futures [#94]
|
||||
|
||||
[#94]: https://github.com/actix/actix-net/pull/94
|
||||
@@ -126,55 +149,55 @@
|
||||
|
||||
|
||||
## 1.0.0 - 2019-12-11
|
||||
* Update dependencies
|
||||
- Update dependencies
|
||||
|
||||
|
||||
## 1.0.0-alpha.3 - 2019-12-07
|
||||
* Migrate to tokio 0.2
|
||||
* Fix compilation on non-unix platforms
|
||||
- Migrate to tokio 0.2
|
||||
- Fix compilation on non-unix platforms
|
||||
|
||||
|
||||
## 1.0.0-alpha.2 - 2019-12-02
|
||||
* Export `main` and `test` attribute macros
|
||||
* Export `time` module (re-export of tokio-timer)
|
||||
* Export `net` module (re-export of tokio-net)
|
||||
- Export `main` and `test` attribute macros
|
||||
- Export `time` module (re-export of tokio-timer)
|
||||
- Export `net` module (re-export of tokio-net)
|
||||
|
||||
|
||||
## 1.0.0-alpha.1 - 2019-11-22
|
||||
* Migrate to std::future and tokio 0.2
|
||||
- Migrate to std::future and tokio 0.2
|
||||
|
||||
|
||||
## 0.2.6 - 2019-11-14
|
||||
* Allow to join arbiter's thread. #60
|
||||
* Fix arbiter's thread panic message.
|
||||
- Allow to join arbiter's thread. #60
|
||||
- Fix arbiter's thread panic message.
|
||||
|
||||
|
||||
## 0.2.5 - 2019-09-02
|
||||
* Add arbiter specific storage
|
||||
- Add arbiter specific storage
|
||||
|
||||
|
||||
## 0.2.4 - 2019-07-17
|
||||
* Avoid a copy of the Future when initializing the Box. #29
|
||||
- Avoid a copy of the Future when initializing the Box. #29
|
||||
|
||||
|
||||
## 0.2.3 - 2019-06-22
|
||||
* Allow to start System using existing CurrentThread Handle #22
|
||||
- Allow to start System using existing CurrentThread Handle #22
|
||||
|
||||
|
||||
## 0.2.2 - 2019-03-28
|
||||
* Moved `blocking` module to `actix-threadpool` crate
|
||||
- Moved `blocking` module to `actix-threadpool` crate
|
||||
|
||||
|
||||
## 0.2.1 - 2019-03-11
|
||||
* Added `blocking` module
|
||||
* Added `Arbiter::exec_fn` - execute fn on the arbiter's thread
|
||||
* Added `Arbiter::exec` - execute fn on the arbiter's thread and wait result
|
||||
- Added `blocking` module
|
||||
- Added `Arbiter::exec_fn` - execute fn on the arbiter's thread
|
||||
- Added `Arbiter::exec` - execute fn on the arbiter's thread and wait result
|
||||
|
||||
|
||||
## 0.2.0 - 2019-03-06
|
||||
* `run` method returns `io::Result<()>`
|
||||
* Removed `Handle`
|
||||
- `run` method returns `io::Result<()>`
|
||||
- Removed `Handle`
|
||||
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
* Initial release
|
||||
- Initial release
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-rt"
|
||||
version = "2.5.0"
|
||||
version = "2.7.0"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
@@ -27,11 +27,12 @@ io-uring = ["tokio-uring"]
|
||||
actix-macros = { version = "0.2.3", optional = true }
|
||||
|
||||
futures-core = { version = "0.3", default-features = false }
|
||||
tokio = { version = "1.5.1", features = ["rt", "net", "parking_lot", "signal", "sync", "time"] }
|
||||
tokio = { version = "1.13.1", features = ["rt", "net", "parking_lot", "signal", "sync", "time"] }
|
||||
|
||||
# runtime for `io-uring` feature
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
tokio-uring = { version = "0.1", optional = true }
|
||||
tokio-uring = { version = "0.3", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.5.1", features = ["full"] }
|
||||
hyper = { version = "0.14", default-features = false, features = ["server", "tcp", "http1"] }
|
||||
tokio = { version = "1.13.1", features = ["full"] }
|
||||
hyper = { version = "0.14.10", default-features = false, features = ["server", "tcp", "http1"] }
|
||||
|
@@ -3,11 +3,11 @@
|
||||
> Tokio-based single-threaded async runtime for the Actix ecosystem.
|
||||
|
||||
[](https://crates.io/crates/actix-rt)
|
||||
[](https://docs.rs/actix-rt/2.5.0)
|
||||
[](https://docs.rs/actix-rt/2.7.0)
|
||||
[](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
|
||||

|
||||
<br />
|
||||
[](https://deps.rs/crate/actix-rt/2.5.0)
|
||||
[](https://deps.rs/crate/actix-rt/2.7.0)
|
||||

|
||||
[](https://discord.gg/WghFtEH6Hb)
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
use hyper::service::{make_service_fn, service_fn};
|
||||
use hyper::{Body, Request, Response, Server};
|
||||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use std::{convert::Infallible, net::SocketAddr};
|
||||
|
||||
use hyper::{
|
||||
service::{make_service_fn, service_fn},
|
||||
Body, Request, Response, Server,
|
||||
};
|
||||
|
||||
async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||
Ok(Response::new(Body::from("Hello World")))
|
||||
@@ -21,8 +23,8 @@ fn main() {
|
||||
let server =
|
||||
Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))).serve(make_service);
|
||||
|
||||
if let Err(e) = server.await {
|
||||
eprintln!("server error: {}", e);
|
||||
if let Err(err) = server.await {
|
||||
eprintln!("server error: {}", err);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@@ -108,7 +108,6 @@ impl Arbiter {
|
||||
///
|
||||
/// [tokio-runtime]: tokio::runtime::Runtime
|
||||
#[cfg(not(all(target_os = "linux", feature = "io-uring")))]
|
||||
#[doc(hidden)]
|
||||
pub fn with_tokio_rt<F>(runtime_factory: F) -> Arbiter
|
||||
where
|
||||
F: Fn() -> tokio::runtime::Runtime + Send + 'static,
|
||||
@@ -261,6 +260,7 @@ impl Arbiter {
|
||||
/// If you require a result, include a response channel in the future.
|
||||
///
|
||||
/// Returns true if future was sent successfully and false if the Arbiter has died.
|
||||
#[track_caller]
|
||||
pub fn spawn<Fut>(&self, future: Fut) -> bool
|
||||
where
|
||||
Fut: Future<Output = ()> + Send + 'static,
|
||||
@@ -276,6 +276,7 @@ impl Arbiter {
|
||||
/// channel in the function.
|
||||
///
|
||||
/// Returns true if function was sent successfully and false if the Arbiter has died.
|
||||
#[track_caller]
|
||||
pub fn spawn_fn<F>(&self, f: F) -> bool
|
||||
where
|
||||
F: FnOnce() + Send + 'static,
|
||||
|
@@ -41,7 +41,7 @@
|
||||
//! In particular, when running a `System`, only `System::block_on` is supported.
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
@@ -51,13 +51,10 @@ compile_error!("io_uring is a linux only feature.");
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
// Cannot define a main macro when compiled into test harness.
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/62127.
|
||||
#[cfg(all(feature = "macros", not(test)))]
|
||||
pub use actix_macros::main;
|
||||
|
||||
#[cfg(feature = "macros")]
|
||||
pub use actix_macros::test;
|
||||
|
||||
@@ -65,12 +62,13 @@ mod arbiter;
|
||||
mod runtime;
|
||||
mod system;
|
||||
|
||||
pub use tokio::pin;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
pub use self::arbiter::{Arbiter, ArbiterHandle};
|
||||
pub use self::runtime::Runtime;
|
||||
pub use self::system::{System, SystemRunner};
|
||||
|
||||
pub use tokio::pin;
|
||||
|
||||
pub mod signal {
|
||||
//! Asynchronous signal handling (Tokio re-exports).
|
||||
|
||||
@@ -95,7 +93,6 @@ pub mod net {
|
||||
use tokio::io::{AsyncRead, AsyncWrite, Interest};
|
||||
pub use tokio::net::UdpSocket;
|
||||
pub use tokio::net::{TcpListener, TcpSocket, TcpStream};
|
||||
|
||||
#[cfg(unix)]
|
||||
pub use tokio::net::{UnixDatagram, UnixListener, UnixStream};
|
||||
|
||||
@@ -198,6 +195,7 @@ pub mod task {
|
||||
/// assert!(handle.await.unwrap_err().is_cancelled());
|
||||
/// # });
|
||||
/// ```
|
||||
#[track_caller]
|
||||
#[inline]
|
||||
pub fn spawn<Fut>(f: Fut) -> JoinHandle<Fut::Output>
|
||||
where
|
||||
|
@@ -53,6 +53,7 @@ impl Runtime {
|
||||
/// # Panics
|
||||
/// This function panics if the spawn fails. Failure occurs if the executor is currently at
|
||||
/// capacity and is unable to spawn a new future.
|
||||
#[track_caller]
|
||||
pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
|
||||
where
|
||||
F: Future + 'static,
|
||||
@@ -73,6 +74,7 @@ impl Runtime {
|
||||
///
|
||||
/// The caller is responsible for ensuring that other spawned futures complete execution by
|
||||
/// calling `block_on` or `run`.
|
||||
#[track_caller]
|
||||
pub fn block_on<F>(&self, f: F) -> F::Output
|
||||
where
|
||||
F: Future,
|
||||
|
@@ -46,7 +46,6 @@ impl System {
|
||||
/// Create a new System using the [Tokio Runtime](tokio-runtime) returned from a closure.
|
||||
///
|
||||
/// [tokio-runtime]: tokio::runtime::Runtime
|
||||
#[doc(hidden)]
|
||||
pub fn with_tokio_rt<F>(runtime_factory: F) -> SystemRunner
|
||||
where
|
||||
F: Fn() -> tokio::runtime::Runtime,
|
||||
@@ -205,6 +204,7 @@ impl SystemRunner {
|
||||
}
|
||||
|
||||
/// Runs the provided future, blocking the current thread until the future completes.
|
||||
#[track_caller]
|
||||
#[inline]
|
||||
pub fn block_on<F: Future>(&self, fut: F) -> F::Output {
|
||||
self.rt.block_on(fut)
|
||||
|
@@ -4,7 +4,6 @@ use std::{
|
||||
};
|
||||
|
||||
use actix_rt::{task::JoinError, Arbiter, System};
|
||||
|
||||
#[cfg(not(feature = "io-uring"))]
|
||||
use {
|
||||
std::{sync::mpsc::channel, thread},
|
||||
|
@@ -1,48 +1,82 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 2.1.1 - 2022-03-09
|
||||
- No significant changes since `2.1.0`.
|
||||
|
||||
|
||||
## 2.1.0 - 2022-03-08
|
||||
- Update `tokio-uring` dependency to `0.3.0`. [#448]
|
||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#448]
|
||||
- Wait for accept thread to stop before sending completion signal. [#443]
|
||||
|
||||
[#443]: https://github.com/actix/actix-net/pull/443
|
||||
[#448]: https://github.com/actix/actix-net/pull/448
|
||||
|
||||
|
||||
## 2.0.0 - 2022-01-19
|
||||
- No significant changes since `2.0.0-rc.4`.
|
||||
|
||||
|
||||
## 2.0.0-rc.4 - 2022-01-12
|
||||
- Update `tokio-uring` dependency to `0.2.0`. [#436]
|
||||
|
||||
[#436]: https://github.com/actix/actix-net/pull/436
|
||||
|
||||
|
||||
## 2.0.0-rc.3 - 2021-12-31
|
||||
- No significant changes since `2.0.0-rc.2`.
|
||||
|
||||
|
||||
## 2.0.0-rc.2 - 2021-12-27
|
||||
- Simplify `TestServer`. [#431]
|
||||
|
||||
[#431]: https://github.com/actix/actix-net/pull/431
|
||||
|
||||
|
||||
## 2.0.0-rc.1 - 2021-12-05
|
||||
* Hide implementation details of `Server`. [#424]
|
||||
* `Server` now runs only after awaiting it. [#425]
|
||||
- Hide implementation details of `Server`. [#424]
|
||||
- `Server` now runs only after awaiting it. [#425]
|
||||
|
||||
[#424]: https://github.com/actix/actix-net/pull/424
|
||||
[#425]: https://github.com/actix/actix-net/pull/425
|
||||
|
||||
|
||||
## 2.0.0-beta.9 - 2021-11-15
|
||||
* Restore `Arbiter` support lost in `beta.8`. [#417]
|
||||
- Restore `Arbiter` support lost in `beta.8`. [#417]
|
||||
|
||||
[#417]: https://github.com/actix/actix-net/pull/417
|
||||
|
||||
|
||||
## 2.0.0-beta.8 - 2021-11-05 _(YANKED)_
|
||||
* Fix non-unix signal handler. [#410]
|
||||
- Fix non-unix signal handler. [#410]
|
||||
|
||||
[#410]: https://github.com/actix/actix-net/pull/410
|
||||
|
||||
|
||||
## 2.0.0-beta.7 - 2021-11-05 _(YANKED)_
|
||||
* Server can be started in regular Tokio runtime. [#408]
|
||||
* Expose new `Server` type whose `Future` impl resolves when server stops. [#408]
|
||||
* Rename `Server` to `ServerHandle`. [#407]
|
||||
* Add `Server::handle` to obtain handle to server. [#408]
|
||||
* Rename `ServerBuilder::{maxconn => max_concurrent_connections}`. [#407]
|
||||
* Deprecate crate-level `new` shortcut for server builder. [#408]
|
||||
* Minimum supported Rust version (MSRV) is now 1.52.
|
||||
- Server can be started in regular Tokio runtime. [#408]
|
||||
- Expose new `Server` type whose `Future` impl resolves when server stops. [#408]
|
||||
- Rename `Server` to `ServerHandle`. [#407]
|
||||
- Add `Server::handle` to obtain handle to server. [#408]
|
||||
- Rename `ServerBuilder::{maxconn => max_concurrent_connections}`. [#407]
|
||||
- Deprecate crate-level `new` shortcut for server builder. [#408]
|
||||
- Minimum supported Rust version (MSRV) is now 1.52.
|
||||
|
||||
[#407]: https://github.com/actix/actix-net/pull/407
|
||||
[#408]: https://github.com/actix/actix-net/pull/408
|
||||
|
||||
|
||||
## 2.0.0-beta.6 - 2021-10-11
|
||||
* Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux. [#374]
|
||||
* Server no long listens to `SIGHUP` signal. Previously, the received was not used but did block
|
||||
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux. [#374]
|
||||
- Server no long listens to `SIGHUP` signal. Previously, the received was not used but did block
|
||||
subsequent exit signals from working. [#389]
|
||||
* Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to
|
||||
- Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to
|
||||
this change. [#349]
|
||||
* Remove `ServerBuilder::configure` [#349]
|
||||
- Remove `ServerBuilder::configure` [#349]
|
||||
|
||||
[#374]: https://github.com/actix/actix-net/pull/374
|
||||
[#349]: https://github.com/actix/actix-net/pull/349
|
||||
@@ -50,23 +84,23 @@
|
||||
|
||||
|
||||
## 2.0.0-beta.5 - 2021-04-20
|
||||
* Server shutdown notifies all workers to exit regardless if shutdown is graceful. This causes all
|
||||
- Server shutdown notifies all workers to exit regardless if shutdown is graceful. This causes all
|
||||
workers to shutdown immediately in force shutdown case. [#333]
|
||||
|
||||
[#333]: https://github.com/actix/actix-net/pull/333
|
||||
|
||||
|
||||
## 2.0.0-beta.4 - 2021-04-01
|
||||
* Prevent panic when `shutdown_timeout` is very large. [f9262db]
|
||||
- Prevent panic when `shutdown_timeout` is very large. [f9262db]
|
||||
|
||||
[f9262db]: https://github.com/actix/actix-net/commit/f9262db
|
||||
|
||||
|
||||
## 2.0.0-beta.3 - 2021-02-06
|
||||
* Hidden `ServerBuilder::start` method has been removed. Use `ServerBuilder::run`. [#246]
|
||||
* Add retry for EINTR signal (`io::Interrupted`) in `Accept`'s poll loop. [#264]
|
||||
* Add `ServerBuilder::worker_max_blocking_threads` to customize blocking thread pool size. [#265]
|
||||
* Update `actix-rt` to `2.0.0`. [#273]
|
||||
- Hidden `ServerBuilder::start` method has been removed. Use `ServerBuilder::run`. [#246]
|
||||
- Add retry for EINTR signal (`io::Interrupted`) in `Accept`'s poll loop. [#264]
|
||||
- Add `ServerBuilder::worker_max_blocking_threads` to customize blocking thread pool size. [#265]
|
||||
- Update `actix-rt` to `2.0.0`. [#273]
|
||||
|
||||
[#246]: https://github.com/actix/actix-net/pull/246
|
||||
[#264]: https://github.com/actix/actix-net/pull/264
|
||||
@@ -75,21 +109,21 @@
|
||||
|
||||
|
||||
## 2.0.0-beta.2 - 2021-01-03
|
||||
* Merge `actix-testing` to `actix-server` as `test_server` mod. [#242]
|
||||
- Merge `actix-testing` to `actix-server` as `test_server` mod. [#242]
|
||||
|
||||
[#242]: https://github.com/actix/actix-net/pull/242
|
||||
|
||||
|
||||
## 2.0.0-beta.1 - 2020-12-28
|
||||
* Added explicit info log message on accept queue pause. [#215]
|
||||
* Prevent double registration of sockets when back-pressure is resolved. [#223]
|
||||
* Update `mio` dependency to `0.7.3`. [#239]
|
||||
* Remove `socket2` dependency. [#239]
|
||||
* `ServerBuilder::backlog` now accepts `u32` instead of `i32`. [#239]
|
||||
* Remove `AcceptNotify` type and pass `WakerQueue` to `Worker` to wake up `Accept`'s `Poll`. [#239]
|
||||
* Convert `mio::net::TcpStream` to `actix_rt::net::TcpStream`(`UnixStream` for uds) using
|
||||
- Added explicit info log message on accept queue pause. [#215]
|
||||
- Prevent double registration of sockets when back-pressure is resolved. [#223]
|
||||
- Update `mio` dependency to `0.7.3`. [#239]
|
||||
- Remove `socket2` dependency. [#239]
|
||||
- `ServerBuilder::backlog` now accepts `u32` instead of `i32`. [#239]
|
||||
- Remove `AcceptNotify` type and pass `WakerQueue` to `Worker` to wake up `Accept`'s `Poll`. [#239]
|
||||
- Convert `mio::net::TcpStream` to `actix_rt::net::TcpStream`(`UnixStream` for uds) using
|
||||
`FromRawFd` and `IntoRawFd`(`FromRawSocket` and `IntoRawSocket` on windows). [#239]
|
||||
* Remove `AsyncRead` and `AsyncWrite` trait bound for `socket::FromStream` trait. [#239]
|
||||
- Remove `AsyncRead` and `AsyncWrite` trait bound for `socket::FromStream` trait. [#239]
|
||||
|
||||
[#215]: https://github.com/actix/actix-net/pull/215
|
||||
[#223]: https://github.com/actix/actix-net/pull/223
|
||||
@@ -97,125 +131,125 @@
|
||||
|
||||
|
||||
## 1.0.4 - 2020-09-12
|
||||
* Update actix-codec to 0.3.0.
|
||||
* Workers must be greater than 0. [#167]
|
||||
- Update actix-codec to 0.3.0.
|
||||
- Workers must be greater than 0. [#167]
|
||||
|
||||
[#167]: https://github.com/actix/actix-net/pull/167
|
||||
|
||||
|
||||
## 1.0.3 - 2020-05-19
|
||||
* Replace deprecated `net2` crate with `socket2` [#140]
|
||||
- Replace deprecated `net2` crate with `socket2` [#140]
|
||||
|
||||
[#140]: https://github.com/actix/actix-net/pull/140
|
||||
|
||||
|
||||
## 1.0.2 - 2020-02-26
|
||||
* Avoid error by calling `reregister()` on Windows [#103]
|
||||
- Avoid error by calling `reregister()` on Windows [#103]
|
||||
|
||||
[#103]: https://github.com/actix/actix-net/pull/103
|
||||
|
||||
|
||||
## 1.0.1 - 2019-12-29
|
||||
* Rename `.start()` method to `.run()`
|
||||
- Rename `.start()` method to `.run()`
|
||||
|
||||
|
||||
## 1.0.0 - 2019-12-11
|
||||
* Use actix-net releases
|
||||
- Use actix-net releases
|
||||
|
||||
|
||||
## 1.0.0-alpha.4 - 2019-12-08
|
||||
* Use actix-service 1.0.0-alpha.4
|
||||
- Use actix-service 1.0.0-alpha.4
|
||||
|
||||
|
||||
## 1.0.0-alpha.3 - 2019-12-07
|
||||
* Migrate to tokio 0.2
|
||||
* Fix compilation on non-unix platforms
|
||||
* Better handling server configuration
|
||||
- Migrate to tokio 0.2
|
||||
- Fix compilation on non-unix platforms
|
||||
- Better handling server configuration
|
||||
|
||||
|
||||
## 1.0.0-alpha.2 - 2019-12-02
|
||||
* Simplify server service (remove actix-server-config)
|
||||
* Allow to wait on `Server` until server stops
|
||||
- Simplify server service (remove actix-server-config)
|
||||
- Allow to wait on `Server` until server stops
|
||||
|
||||
|
||||
## 0.8.0-alpha.1 - 2019-11-22
|
||||
* Migrate to `std::future`
|
||||
- Migrate to `std::future`
|
||||
|
||||
|
||||
## 0.7.0 - 2019-10-04
|
||||
* Update `rustls` to 0.16
|
||||
* Minimum required Rust version upped to 1.37.0
|
||||
- Update `rustls` to 0.16
|
||||
- Minimum required Rust version upped to 1.37.0
|
||||
|
||||
|
||||
## 0.6.1 - 2019-09-25
|
||||
* Add UDS listening support to `ServerBuilder`
|
||||
- Add UDS listening support to `ServerBuilder`
|
||||
|
||||
|
||||
## 0.6.0 - 2019-07-18
|
||||
* Support Unix domain sockets #3
|
||||
- Support Unix domain sockets #3
|
||||
|
||||
|
||||
## 0.5.1 - 2019-05-18
|
||||
* ServerBuilder::shutdown_timeout() accepts u64
|
||||
- ServerBuilder::shutdown_timeout() accepts u64
|
||||
|
||||
|
||||
## 0.5.0 - 2019-05-12
|
||||
* Add `Debug` impl for `SslError`
|
||||
* Derive debug for `Server` and `ServerCommand`
|
||||
* Upgrade to actix-service 0.4
|
||||
- Add `Debug` impl for `SslError`
|
||||
- Derive debug for `Server` and `ServerCommand`
|
||||
- Upgrade to actix-service 0.4
|
||||
|
||||
|
||||
## 0.4.3 - 2019-04-16
|
||||
* Re-export `IoStream` trait
|
||||
* Depend on `ssl` and `rust-tls` features from actix-server-config
|
||||
- Re-export `IoStream` trait
|
||||
- Depend on `ssl` and `rust-tls` features from actix-server-config
|
||||
|
||||
|
||||
## 0.4.2 - 2019-03-30
|
||||
* Fix SIGINT force shutdown
|
||||
- Fix SIGINT force shutdown
|
||||
|
||||
|
||||
## 0.4.1 - 2019-03-14
|
||||
* `SystemRuntime::on_start()` - allow to run future before server service initialization
|
||||
- `SystemRuntime::on_start()` - allow to run future before server service initialization
|
||||
|
||||
|
||||
## 0.4.0 - 2019-03-12
|
||||
* Use `ServerConfig` for service factory
|
||||
* Wrap tcp socket to `Io` type
|
||||
* Upgrade actix-service
|
||||
- Use `ServerConfig` for service factory
|
||||
- Wrap tcp socket to `Io` type
|
||||
- Upgrade actix-service
|
||||
|
||||
|
||||
## 0.3.1 - 2019-03-04
|
||||
* Add `ServerBuilder::maxconnrate` sets the maximum per-worker number of concurrent connections
|
||||
* Add helper ssl error `SslError`
|
||||
* Rename `StreamServiceFactory` to `ServiceFactory`
|
||||
* Deprecate `StreamServiceFactory`
|
||||
- Add `ServerBuilder::maxconnrate` sets the maximum per-worker number of concurrent connections
|
||||
- Add helper ssl error `SslError`
|
||||
- Rename `StreamServiceFactory` to `ServiceFactory`
|
||||
- Deprecate `StreamServiceFactory`
|
||||
|
||||
|
||||
## 0.3.0 - 2019-03-02
|
||||
* Use new `NewService` trait
|
||||
- Use new `NewService` trait
|
||||
|
||||
|
||||
## 0.2.1 - 2019-02-09
|
||||
* Drop service response
|
||||
- Drop service response
|
||||
|
||||
|
||||
## 0.2.0 - 2019-02-01
|
||||
* Migrate to actix-service 0.2
|
||||
* Updated rustls dependency
|
||||
- Migrate to actix-service 0.2
|
||||
- Updated rustls dependency
|
||||
|
||||
|
||||
## 0.1.3 - 2018-12-21
|
||||
* Fix max concurrent connections handling
|
||||
- Fix max concurrent connections handling
|
||||
|
||||
|
||||
## 0.1.2 - 2018-12-12
|
||||
* rename ServiceConfig::rt() to ServiceConfig::apply()
|
||||
* Fix back-pressure for concurrent ssl handshakes
|
||||
- rename ServiceConfig::rt() to ServiceConfig::apply()
|
||||
- Fix back-pressure for concurrent ssl handshakes
|
||||
|
||||
|
||||
## 0.1.1 - 2018-12-11
|
||||
* Fix signal handling on windows
|
||||
- Fix signal handling on windows
|
||||
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
* Move server to separate crate
|
||||
- Move server to separate crate
|
||||
|
@@ -1,14 +1,17 @@
|
||||
[package]
|
||||
name = "actix-server"
|
||||
version = "2.0.0-rc.1"
|
||||
version = "2.1.1"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"fakeshadow <24548779@qq.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
"Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>",
|
||||
]
|
||||
description = "General purpose TCP server built for the Actix ecosystem"
|
||||
keywords = ["network", "framework", "async", "futures"]
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
keywords = ["network", "tcp", "server", "framework", "async"]
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
@@ -21,26 +24,27 @@ default = []
|
||||
io-uring = ["tokio-uring", "actix-rt/io-uring"]
|
||||
|
||||
[dependencies]
|
||||
actix-rt = { version = "2.4.0", default-features = false }
|
||||
actix-service = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-rt = { version = "2.7", default-features = false }
|
||||
actix-service = "2"
|
||||
actix-utils = "3"
|
||||
|
||||
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||
futures-util = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||
log = "0.4"
|
||||
mio = { version = "0.8", features = ["os-poll", "net"] }
|
||||
num_cpus = "1.13"
|
||||
socket2 = "0.4.2"
|
||||
tokio = { version = "1.5.1", features = ["sync"] }
|
||||
tokio = { version = "1.13.1", features = ["sync"] }
|
||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||
|
||||
# runtime for io-uring feature
|
||||
tokio-uring = { version = "0.1", optional = true }
|
||||
# runtime for `io-uring` feature
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
tokio-uring = { version = "0.3", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-codec = "0.4.0"
|
||||
actix-rt = "2.4.0"
|
||||
actix-codec = "0.5.0"
|
||||
actix-rt = "2.6.0"
|
||||
|
||||
bytes = "1"
|
||||
env_logger = "0.9"
|
||||
futures-util = { version = "0.3.7", default-features = false, features = ["sink", "async-await-macro"] }
|
||||
tokio = { version = "1.5.1", features = ["io-util", "rt-multi-thread", "macros"] }
|
||||
tokio = { version = "1.13.1", features = ["io-util", "rt-multi-thread", "macros", "fs"] }
|
||||
|
15
actix-server/README.md
Normal file
15
actix-server/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# actix-server
|
||||
|
||||
> General purpose TCP server built for the Actix ecosystem.
|
||||
|
||||
[](https://crates.io/crates/actix-server)
|
||||
[](https://docs.rs/actix-server/2.1.1)
|
||||
[](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
||||

|
||||
[](https://deps.rs/crate/actix-server/2.1.1)
|
||||

|
||||
[](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
## Resources
|
||||
- [Library Documentation](https://docs.rs/actix-server)
|
||||
- [Examples](/actix-server/examples)
|
95
actix-server/examples/file-reader.rs
Normal file
95
actix-server/examples/file-reader.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
//! Simple file-reader TCP server with framed stream.
|
||||
//!
|
||||
//! Using the following command:
|
||||
//!
|
||||
//! ```sh
|
||||
//! nc 127.0.0.1 8080
|
||||
//! ```
|
||||
//!
|
||||
//! Follow the prompt and enter a file path, relative or absolute.
|
||||
|
||||
use std::io;
|
||||
|
||||
use actix_codec::{Framed, LinesCodec};
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_server::Server;
|
||||
use actix_service::{fn_service, ServiceFactoryExt as _};
|
||||
use futures_util::{SinkExt as _, StreamExt as _};
|
||||
use tokio::{fs::File, io::AsyncReadExt as _};
|
||||
|
||||
async fn run() -> io::Result<()> {
|
||||
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
|
||||
|
||||
let addr = ("127.0.0.1", 8080);
|
||||
tracing::info!("starting server on port: {}", &addr.0);
|
||||
|
||||
// Bind socket address and start worker(s). By default, the server uses the number of physical
|
||||
// CPU cores as the worker count. For this reason, the closure passed to bind needs to return
|
||||
// a service *factory*; so it can be created once per worker.
|
||||
Server::build()
|
||||
.bind("file-reader", addr, move || {
|
||||
fn_service(move |stream: TcpStream| async move {
|
||||
// set up codec to use with I/O resource
|
||||
let mut framed = Framed::new(stream, LinesCodec::default());
|
||||
|
||||
loop {
|
||||
// prompt for file name
|
||||
framed.send("Type file name to return:").await?;
|
||||
|
||||
// wait for next line
|
||||
match framed.next().await {
|
||||
Some(Ok(line)) => {
|
||||
match File::open(&line).await {
|
||||
Ok(mut file) => {
|
||||
tracing::info!("reading file: {}", &line);
|
||||
|
||||
// read file into String buffer
|
||||
let mut buf = String::new();
|
||||
file.read_to_string(&mut buf).await?;
|
||||
|
||||
// send String into framed object
|
||||
framed.send(buf).await?;
|
||||
|
||||
// break out of loop and
|
||||
break;
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!("{}", err);
|
||||
framed
|
||||
.send("File not found or not readable. Try again.")
|
||||
.await?;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// not being able to read a line from the stream is unrecoverable
|
||||
Some(Err(err)) => return Err(err),
|
||||
|
||||
// This EOF won't be hit.
|
||||
None => continue,
|
||||
}
|
||||
}
|
||||
|
||||
// close connection after file has been copied to TCP stream
|
||||
Ok(())
|
||||
})
|
||||
.map_err(|err| tracing::error!("service error: {:?}", err))
|
||||
})?
|
||||
.workers(2)
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
run().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// alternatively:
|
||||
// #[actix_rt::main]
|
||||
// async fn main() -> io::Result<()> {
|
||||
// run().await?;
|
||||
// Ok(())
|
||||
// }
|
@@ -22,20 +22,19 @@ use actix_server::Server;
|
||||
use actix_service::{fn_service, ServiceFactoryExt as _};
|
||||
use bytes::BytesMut;
|
||||
use futures_util::future::ok;
|
||||
use log::{error, info};
|
||||
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
|
||||
|
||||
async fn run() -> io::Result<()> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
||||
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
|
||||
|
||||
let count = Arc::new(AtomicUsize::new(0));
|
||||
|
||||
let addr = ("127.0.0.1", 8080);
|
||||
info!("starting server on port: {}", &addr.0);
|
||||
tracing::info!("starting server on port: {}", &addr.0);
|
||||
|
||||
// Bind socket address and start worker(s). By default, the server uses the number of available
|
||||
// logical CPU cores as the worker count. For this reason, the closure passed to bind needs
|
||||
// to return a service *factory*; so it can be created once per worker.
|
||||
// Bind socket address and start worker(s). By default, the server uses the number of physical
|
||||
// CPU cores as the worker count. For this reason, the closure passed to bind needs to return
|
||||
// a service *factory*; so it can be created once per worker.
|
||||
Server::build()
|
||||
.bind("echo", addr, move || {
|
||||
let count = Arc::clone(&count);
|
||||
@@ -58,14 +57,14 @@ async fn run() -> io::Result<()> {
|
||||
|
||||
// more bytes to process
|
||||
Ok(bytes_read) => {
|
||||
info!("[{}] read {} bytes", num, bytes_read);
|
||||
tracing::info!("[{}] read {} bytes", num, bytes_read);
|
||||
stream.write_all(&buf[size..]).await.unwrap();
|
||||
size += bytes_read;
|
||||
}
|
||||
|
||||
// stream error; bail from loop with error
|
||||
Err(err) => {
|
||||
error!("Stream Error: {:?}", err);
|
||||
tracing::error!("stream error: {:?}", err);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
@@ -75,10 +74,10 @@ async fn run() -> io::Result<()> {
|
||||
Ok((buf.freeze(), size))
|
||||
}
|
||||
})
|
||||
.map_err(|err| error!("Service Error: {:?}", err))
|
||||
.map_err(|err| tracing::error!("service error: {:?}", err))
|
||||
.and_then(move |(_, size)| {
|
||||
let num = num2.load(Ordering::SeqCst);
|
||||
info!("[{}] total bytes read: {}", num, size);
|
||||
tracing::info!("[{}] total bytes read: {}", num, size);
|
||||
ok(size)
|
||||
})
|
||||
})?
|
||||
|
@@ -1,8 +1,8 @@
|
||||
use std::{io, thread, time::Duration};
|
||||
|
||||
use actix_rt::time::Instant;
|
||||
use log::{debug, error, info};
|
||||
use mio::{Interest, Poll, Token as MioToken};
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::{
|
||||
availability::Availability,
|
||||
@@ -24,7 +24,7 @@ struct ServerSocketInfo {
|
||||
timeout: Option<actix_rt::time::Instant>,
|
||||
}
|
||||
|
||||
/// poll instance of the server.
|
||||
/// Poll instance of the server.
|
||||
pub(crate) struct Accept {
|
||||
poll: Poll,
|
||||
waker_queue: WakerQueue,
|
||||
@@ -41,7 +41,7 @@ impl Accept {
|
||||
pub(crate) fn start(
|
||||
sockets: Vec<(usize, MioListener)>,
|
||||
builder: &ServerBuilder,
|
||||
) -> io::Result<(WakerQueue, Vec<WorkerHandleServer>)> {
|
||||
) -> io::Result<(WakerQueue, Vec<WorkerHandleServer>, thread::JoinHandle<()>)> {
|
||||
let handle_server = ServerHandle::new(builder.cmd_tx.clone());
|
||||
|
||||
// construct poll instance and its waker
|
||||
@@ -73,12 +73,12 @@ impl Accept {
|
||||
handle_server,
|
||||
)?;
|
||||
|
||||
thread::Builder::new()
|
||||
let accept_handle = thread::Builder::new()
|
||||
.name("actix-server acceptor".to_owned())
|
||||
.spawn(move || accept.poll_with(&mut sockets))
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
|
||||
|
||||
Ok((waker_queue, handles_server))
|
||||
Ok((waker_queue, handles_server, accept_handle))
|
||||
}
|
||||
|
||||
fn new_with_sockets(
|
||||
@@ -127,10 +127,10 @@ impl Accept {
|
||||
let mut events = mio::Events::with_capacity(256);
|
||||
|
||||
loop {
|
||||
if let Err(e) = self.poll.poll(&mut events, self.timeout) {
|
||||
match e.kind() {
|
||||
if let Err(err) = self.poll.poll(&mut events, self.timeout) {
|
||||
match err.kind() {
|
||||
io::ErrorKind::Interrupted => {}
|
||||
_ => panic!("Poll error: {}", e),
|
||||
_ => panic!("Poll error: {}", err),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ impl Accept {
|
||||
WAKER_TOKEN => {
|
||||
let exit = self.handle_waker(sockets);
|
||||
if exit {
|
||||
info!("Accept thread stopped");
|
||||
info!("accept thread stopped");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -161,11 +161,13 @@ impl Accept {
|
||||
// a loop that would try to drain the command channel. It's yet unknown
|
||||
// if it's necessary/good practice to actively drain the waker queue.
|
||||
loop {
|
||||
// take guard with every iteration so no new interest can be added
|
||||
// until the current task is done.
|
||||
// Take guard with every iteration so no new interests can be added until the current
|
||||
// task is done. Take care not to take the guard again inside this loop.
|
||||
let mut guard = self.waker_queue.guard();
|
||||
|
||||
#[allow(clippy::significant_drop_in_scrutinee)]
|
||||
match guard.pop_front() {
|
||||
// worker notify it becomes available.
|
||||
// Worker notified it became available.
|
||||
Some(WakerInterest::WorkerAvailable(idx)) => {
|
||||
drop(guard);
|
||||
|
||||
@@ -176,7 +178,7 @@ impl Accept {
|
||||
}
|
||||
}
|
||||
|
||||
// a new worker thread is made and it's handle would be added to Accept
|
||||
// A new worker thread has been created so store its handle.
|
||||
Some(WakerInterest::Worker(handle)) => {
|
||||
drop(guard);
|
||||
|
||||
@@ -297,16 +299,16 @@ impl Accept {
|
||||
|
||||
fn register_logged(&self, info: &mut ServerSocketInfo) {
|
||||
match self.register(info) {
|
||||
Ok(_) => debug!("Resume accepting connections on {}", info.lst.local_addr()),
|
||||
Err(e) => error!("Can not register server socket {}", e),
|
||||
Ok(_) => debug!("resume accepting connections on {}", info.lst.local_addr()),
|
||||
Err(err) => error!("can not register server socket {}", err),
|
||||
}
|
||||
}
|
||||
|
||||
fn deregister_logged(&self, info: &mut ServerSocketInfo) {
|
||||
match self.poll.registry().deregister(&mut info.lst) {
|
||||
Ok(_) => debug!("Paused accepting connections on {}", info.lst.local_addr()),
|
||||
Err(e) => {
|
||||
error!("Can not deregister server socket {}", e)
|
||||
Ok(_) => debug!("paused accepting connections on {}", info.lst.local_addr()),
|
||||
Err(err) => {
|
||||
error!("can not deregister server socket {}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,7 +352,7 @@ impl Accept {
|
||||
self.remove_next();
|
||||
|
||||
if self.handles.is_empty() {
|
||||
error!("No workers");
|
||||
error!("no workers");
|
||||
// All workers are gone and Conn is nowhere to be sent.
|
||||
// Treat this situation as Ok and drop Conn.
|
||||
return Ok(());
|
||||
@@ -396,10 +398,10 @@ impl Accept {
|
||||
let conn = Conn { io, token };
|
||||
self.accept_one(conn);
|
||||
}
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => return,
|
||||
Err(ref e) if connection_error(e) => continue,
|
||||
Err(e) => {
|
||||
error!("Error accepting connection: {}", e);
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => return,
|
||||
Err(ref err) if connection_error(err) => continue,
|
||||
Err(err) => {
|
||||
error!("error accepting connection: {}", err);
|
||||
|
||||
// deregister listener temporary
|
||||
self.deregister_logged(info);
|
||||
|
@@ -1,12 +1,12 @@
|
||||
use std::{io, time::Duration};
|
||||
|
||||
use actix_rt::net::TcpStream;
|
||||
use log::{info, trace};
|
||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
||||
use tracing::{info, trace};
|
||||
|
||||
use crate::{
|
||||
server::ServerCommand,
|
||||
service::{InternalServiceFactory, ServiceFactory, StreamNewService},
|
||||
service::{InternalServiceFactory, ServerServiceFactory, StreamNewService},
|
||||
socket::{
|
||||
create_mio_tcp_listener, MioListener, MioTcpListener, StdTcpListener, ToSocketAddrs,
|
||||
},
|
||||
@@ -40,7 +40,7 @@ impl ServerBuilder {
|
||||
let (cmd_tx, cmd_rx) = unbounded_channel();
|
||||
|
||||
ServerBuilder {
|
||||
threads: num_cpus::get(),
|
||||
threads: num_cpus::get_physical(),
|
||||
token: 0,
|
||||
factories: Vec::new(),
|
||||
sockets: Vec::new(),
|
||||
@@ -55,8 +55,11 @@ impl ServerBuilder {
|
||||
|
||||
/// Set number of workers to start.
|
||||
///
|
||||
/// By default server uses number of available logical CPU as workers count. Workers must be
|
||||
/// greater than 0.
|
||||
/// `num` must be greater than 0.
|
||||
///
|
||||
/// The default worker count is the number of physical CPU cores available. If your benchmark
|
||||
/// testing indicates that simultaneous multi-threading is beneficial to your app, you can use
|
||||
/// the [`num_cpus`] crate to acquire the _logical_ core count instead.
|
||||
pub fn workers(mut self, num: usize) -> Self {
|
||||
assert_ne!(num, 0, "workers must be greater than 0");
|
||||
self.threads = num;
|
||||
@@ -137,10 +140,11 @@ impl ServerBuilder {
|
||||
}
|
||||
|
||||
/// Add new service to the server.
|
||||
pub fn bind<F, U, N: AsRef<str>>(mut self, name: N, addr: U, factory: F) -> io::Result<Self>
|
||||
pub fn bind<F, U, N>(mut self, name: N, addr: U, factory: F) -> io::Result<Self>
|
||||
where
|
||||
F: ServiceFactory<TcpStream>,
|
||||
F: ServerServiceFactory<TcpStream>,
|
||||
U: ToSocketAddrs,
|
||||
N: AsRef<str>,
|
||||
{
|
||||
let sockets = bind_addr(addr, self.backlog)?;
|
||||
|
||||
@@ -169,7 +173,7 @@ impl ServerBuilder {
|
||||
factory: F,
|
||||
) -> io::Result<Self>
|
||||
where
|
||||
F: ServiceFactory<TcpStream>,
|
||||
F: ServerServiceFactory<TcpStream>,
|
||||
{
|
||||
lst.set_nonblocking(true)?;
|
||||
let addr = lst.local_addr()?;
|
||||
@@ -193,7 +197,7 @@ impl ServerBuilder {
|
||||
if self.sockets.is_empty() {
|
||||
panic!("Server should have at least one bound socket");
|
||||
} else {
|
||||
info!("Starting {} workers", self.threads);
|
||||
info!("starting {} workers", self.threads);
|
||||
Server::new(self)
|
||||
}
|
||||
}
|
||||
@@ -210,16 +214,16 @@ impl ServerBuilder {
|
||||
/// Add new unix domain service to the server.
|
||||
pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> io::Result<Self>
|
||||
where
|
||||
F: ServiceFactory<actix_rt::net::UnixStream>,
|
||||
F: ServerServiceFactory<actix_rt::net::UnixStream>,
|
||||
N: AsRef<str>,
|
||||
U: AsRef<std::path::Path>,
|
||||
{
|
||||
// The path must not exist when we try to bind.
|
||||
// Try to remove it to avoid bind error.
|
||||
if let Err(e) = std::fs::remove_file(addr.as_ref()) {
|
||||
if let Err(err) = std::fs::remove_file(addr.as_ref()) {
|
||||
// NotFound is expected and not an issue. Anything else is.
|
||||
if e.kind() != std::io::ErrorKind::NotFound {
|
||||
return Err(e);
|
||||
if err.kind() != std::io::ErrorKind::NotFound {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +241,7 @@ impl ServerBuilder {
|
||||
factory: F,
|
||||
) -> io::Result<Self>
|
||||
where
|
||||
F: ServiceFactory<actix_rt::net::UnixStream>,
|
||||
F: ServerServiceFactory<actix_rt::net::UnixStream>,
|
||||
{
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
lst.set_nonblocking(true)?;
|
||||
@@ -260,22 +264,23 @@ pub(super) fn bind_addr<S: ToSocketAddrs>(
|
||||
addr: S,
|
||||
backlog: u32,
|
||||
) -> io::Result<Vec<MioTcpListener>> {
|
||||
let mut err = None;
|
||||
let mut opt_err = None;
|
||||
let mut success = false;
|
||||
let mut sockets = Vec::new();
|
||||
|
||||
for addr in addr.to_socket_addrs()? {
|
||||
match create_mio_tcp_listener(addr, backlog) {
|
||||
Ok(lst) => {
|
||||
success = true;
|
||||
sockets.push(lst);
|
||||
}
|
||||
Err(e) => err = Some(e),
|
||||
Err(err) => opt_err = Some(err),
|
||||
}
|
||||
}
|
||||
|
||||
if success {
|
||||
Ok(sockets)
|
||||
} else if let Some(err) = err.take() {
|
||||
} else if let Some(err) = opt_err.take() {
|
||||
Err(err)
|
||||
} else {
|
||||
Err(io::Error::new(
|
||||
|
@@ -63,10 +63,10 @@ impl<T> Future for JoinAll<T> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
use actix_utils::future::ready;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_join_all() {
|
||||
let futs = vec![ready(Ok(1)), ready(Err(3)), ready(Ok(9))];
|
||||
|
@@ -1,6 +1,7 @@
|
||||
//! General purpose TCP server.
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(future_incompatible)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
|
||||
@@ -20,11 +21,10 @@ mod worker;
|
||||
pub use self::builder::ServerBuilder;
|
||||
pub use self::handle::ServerHandle;
|
||||
pub use self::server::Server;
|
||||
pub use self::service::ServiceFactory;
|
||||
pub use self::test_server::TestServer;
|
||||
|
||||
pub use self::service::ServerServiceFactory;
|
||||
#[doc(hidden)]
|
||||
pub use self::socket::FromStream;
|
||||
pub use self::test_server::TestServer;
|
||||
|
||||
/// Start server building process
|
||||
#[doc(hidden)]
|
||||
|
@@ -3,14 +3,15 @@ use std::{
|
||||
io, mem,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use actix_rt::{time::sleep, System};
|
||||
use futures_core::{future::BoxFuture, Stream};
|
||||
use futures_util::stream::StreamExt as _;
|
||||
use log::{error, info};
|
||||
use tokio::sync::{mpsc::UnboundedReceiver, oneshot};
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::{
|
||||
accept::Accept,
|
||||
@@ -65,7 +66,7 @@ pub(crate) enum ServerCommand {
|
||||
/// server has fully shut down.
|
||||
///
|
||||
/// # Shutdown Signals
|
||||
/// On UNIX systems, `SIGQUIT` will start a graceful shutdown and `SIGTERM` or `SIGINT` will start a
|
||||
/// On UNIX systems, `SIGTERM` will start a graceful shutdown and `SIGQUIT` or `SIGINT` will start a
|
||||
/// forced shutdown. On Windows, a Ctrl-C signal will start a forced shutdown.
|
||||
///
|
||||
/// A graceful shutdown will wait for all workers to stop first.
|
||||
@@ -158,6 +159,7 @@ impl Future for Server {
|
||||
|
||||
pub struct ServerInner {
|
||||
worker_handles: Vec<WorkerHandleServer>,
|
||||
accept_handle: Option<thread::JoinHandle<()>>,
|
||||
worker_config: ServerWorkerConfig,
|
||||
services: Vec<Box<dyn InternalServiceFactory>>,
|
||||
waker_queue: WakerQueue,
|
||||
@@ -198,14 +200,14 @@ impl ServerInner {
|
||||
|
||||
for (_, name, lst) in &builder.sockets {
|
||||
info!(
|
||||
r#"Starting service: "{}", workers: {}, listening on: {}"#,
|
||||
r#"starting service: "{}", workers: {}, listening on: {}"#,
|
||||
name,
|
||||
builder.threads,
|
||||
lst.local_addr()
|
||||
);
|
||||
}
|
||||
|
||||
let (waker_queue, worker_handles) = Accept::start(sockets, &builder)?;
|
||||
let (waker_queue, worker_handles, accept_handle) = Accept::start(sockets, &builder)?;
|
||||
|
||||
let mux = ServerEventMultiplexer {
|
||||
signal_fut: (builder.listen_os_signals).then(Signals::new),
|
||||
@@ -214,6 +216,7 @@ impl ServerInner {
|
||||
|
||||
let server = ServerInner {
|
||||
waker_queue,
|
||||
accept_handle: Some(accept_handle),
|
||||
worker_handles,
|
||||
worker_config: builder.worker_config,
|
||||
services: builder.factories,
|
||||
@@ -243,7 +246,8 @@ impl ServerInner {
|
||||
} => {
|
||||
self.stopping = true;
|
||||
|
||||
// stop accept thread
|
||||
// Signal accept thread to stop.
|
||||
// Signal is non-blocking; we wait for thread to stop later.
|
||||
self.waker_queue.wake(WakerInterest::Stop);
|
||||
|
||||
// send stop signal to workers
|
||||
@@ -258,6 +262,13 @@ impl ServerInner {
|
||||
let _ = join_all(workers_stop).await;
|
||||
}
|
||||
|
||||
// wait for accept thread stop
|
||||
self.accept_handle
|
||||
.take()
|
||||
.unwrap()
|
||||
.join()
|
||||
.expect("Accept thread must not panic in any case");
|
||||
|
||||
if let Some(tx) = completion {
|
||||
let _ = tx.send(());
|
||||
}
|
||||
@@ -272,7 +283,7 @@ impl ServerInner {
|
||||
// TODO: maybe just return with warning log if not found ?
|
||||
assert!(self.worker_handles.iter().any(|wrk| wrk.idx == idx));
|
||||
|
||||
error!("Worker {} has died; restarting", idx);
|
||||
error!("worker {} has died; restarting", idx);
|
||||
|
||||
let factories = self
|
||||
.services
|
||||
|
@@ -1,16 +1,21 @@
|
||||
use std::marker::PhantomData;
|
||||
use std::net::SocketAddr;
|
||||
use std::task::{Context, Poll};
|
||||
use std::{
|
||||
marker::PhantomData,
|
||||
net::SocketAddr,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use actix_service::{Service, ServiceFactory as BaseServiceFactory};
|
||||
use actix_utils::future::{ready, Ready};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use log::error;
|
||||
use tracing::error;
|
||||
|
||||
use crate::socket::{FromStream, MioStream};
|
||||
use crate::worker::WorkerCounterGuard;
|
||||
use crate::{
|
||||
socket::{FromStream, MioStream},
|
||||
worker::WorkerCounterGuard,
|
||||
};
|
||||
|
||||
pub trait ServiceFactory<Stream: FromStream>: Send + Clone + 'static {
|
||||
#[doc(hidden)]
|
||||
pub trait ServerServiceFactory<Stream: FromStream>: Send + Clone + 'static {
|
||||
type Factory: BaseServiceFactory<Stream, Config = ()>;
|
||||
|
||||
fn create(&self) -> Self::Factory;
|
||||
@@ -72,15 +77,15 @@ where
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Can not convert to an async tcp stream: {}", e);
|
||||
Err(err) => {
|
||||
error!("can not convert to an async TCP stream: {}", err);
|
||||
Err(())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct StreamNewService<F: ServiceFactory<Io>, Io: FromStream> {
|
||||
pub(crate) struct StreamNewService<F: ServerServiceFactory<Io>, Io: FromStream> {
|
||||
name: String,
|
||||
inner: F,
|
||||
token: usize,
|
||||
@@ -90,7 +95,7 @@ pub(crate) struct StreamNewService<F: ServiceFactory<Io>, Io: FromStream> {
|
||||
|
||||
impl<F, Io> StreamNewService<F, Io>
|
||||
where
|
||||
F: ServiceFactory<Io>,
|
||||
F: ServerServiceFactory<Io>,
|
||||
Io: FromStream + Send + 'static,
|
||||
{
|
||||
pub(crate) fn create(
|
||||
@@ -111,7 +116,7 @@ where
|
||||
|
||||
impl<F, Io> InternalServiceFactory for StreamNewService<F, Io>
|
||||
where
|
||||
F: ServiceFactory<Io>,
|
||||
F: ServerServiceFactory<Io>,
|
||||
Io: FromStream + Send + 'static,
|
||||
{
|
||||
fn name(&self, _: usize) -> &str {
|
||||
@@ -143,7 +148,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T, I> ServiceFactory<I> for F
|
||||
impl<F, T, I> ServerServiceFactory<I> for F
|
||||
where
|
||||
F: Fn() -> T + Send + Clone + 'static,
|
||||
T: BaseServiceFactory<I, Config = ()>,
|
||||
|
@@ -5,7 +5,7 @@ use std::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use log::trace;
|
||||
use tracing::trace;
|
||||
|
||||
/// Types of process signals.
|
||||
// #[allow(dead_code)]
|
||||
@@ -69,8 +69,8 @@ impl Signals {
|
||||
unix::signal(*kind)
|
||||
.map(|tokio_sig| (*sig, tokio_sig))
|
||||
.map_err(|e| {
|
||||
log::error!(
|
||||
"Can not initialize stream handler for {:?} err: {}",
|
||||
tracing::error!(
|
||||
"can not initialize stream handler for {:?} err: {}",
|
||||
sig,
|
||||
e
|
||||
)
|
||||
|
@@ -1,19 +1,17 @@
|
||||
pub(crate) use std::net::{
|
||||
SocketAddr as StdSocketAddr, TcpListener as StdTcpListener, ToSocketAddrs,
|
||||
};
|
||||
use std::{fmt, io};
|
||||
|
||||
use actix_rt::net::TcpStream;
|
||||
pub(crate) use mio::net::TcpListener as MioTcpListener;
|
||||
use mio::{event::Source, Interest, Registry, Token};
|
||||
#[cfg(unix)]
|
||||
pub(crate) use {
|
||||
mio::net::UnixListener as MioUnixListener,
|
||||
std::os::unix::net::UnixListener as StdUnixListener,
|
||||
};
|
||||
|
||||
use std::{fmt, io};
|
||||
|
||||
use actix_rt::net::TcpStream;
|
||||
use mio::{event::Source, Interest, Registry, Token};
|
||||
|
||||
pub(crate) enum MioListener {
|
||||
Tcp(MioTcpListener),
|
||||
#[cfg(unix)]
|
||||
|
@@ -2,7 +2,7 @@ use std::{io, net, sync::mpsc, thread};
|
||||
|
||||
use actix_rt::{net::TcpStream, System};
|
||||
|
||||
use crate::{Server, ServerBuilder, ServerHandle, ServiceFactory};
|
||||
use crate::{Server, ServerBuilder, ServerHandle, ServerServiceFactory};
|
||||
|
||||
/// A testing server.
|
||||
///
|
||||
@@ -16,7 +16,7 @@ use crate::{Server, ServerBuilder, ServerHandle, ServiceFactory};
|
||||
///
|
||||
/// #[actix_rt::main]
|
||||
/// async fn main() {
|
||||
/// let srv = TestServer::with(|| fn_service(
|
||||
/// let srv = TestServer::start(|| fn_service(
|
||||
/// |sock| async move {
|
||||
/// println!("New connection: {:?}", sock);
|
||||
/// Ok::<_, ()>(())
|
||||
@@ -28,8 +28,8 @@ use crate::{Server, ServerBuilder, ServerHandle, ServiceFactory};
|
||||
/// ```
|
||||
pub struct TestServer;
|
||||
|
||||
/// Test server runtime
|
||||
pub struct TestServerRuntime {
|
||||
/// Test server handle.
|
||||
pub struct TestServerHandle {
|
||||
addr: net::SocketAddr,
|
||||
host: String,
|
||||
port: u16,
|
||||
@@ -38,46 +38,26 @@ pub struct TestServerRuntime {
|
||||
}
|
||||
|
||||
impl TestServer {
|
||||
/// Start new server with server builder.
|
||||
pub fn start<F>(mut factory: F) -> TestServerRuntime
|
||||
where
|
||||
F: FnMut(ServerBuilder) -> ServerBuilder + Send + 'static,
|
||||
{
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
// run server in separate thread
|
||||
let thread_handle = thread::spawn(move || {
|
||||
System::new().block_on(async {
|
||||
let server = factory(Server::build()).workers(1).disable_signals().run();
|
||||
tx.send(server.handle()).unwrap();
|
||||
server.await
|
||||
})
|
||||
});
|
||||
|
||||
let server_handle = rx.recv().unwrap();
|
||||
|
||||
TestServerRuntime {
|
||||
addr: "127.0.0.1:0".parse().unwrap(),
|
||||
host: "127.0.0.1".to_string(),
|
||||
port: 0,
|
||||
server_handle,
|
||||
thread_handle: Some(thread_handle),
|
||||
}
|
||||
/// Start new `TestServer` using application factory and default server config.
|
||||
pub fn start(factory: impl ServerServiceFactory<TcpStream>) -> TestServerHandle {
|
||||
Self::start_with_builder(Server::build(), factory)
|
||||
}
|
||||
|
||||
/// Start new test server with application factory.
|
||||
pub fn with<F: ServiceFactory<TcpStream>>(factory: F) -> TestServerRuntime {
|
||||
/// Start new `TestServer` using application factory and server builder.
|
||||
pub fn start_with_builder(
|
||||
server_builder: ServerBuilder,
|
||||
factory: impl ServerServiceFactory<TcpStream>,
|
||||
) -> TestServerHandle {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
// run server in separate thread
|
||||
let thread_handle = thread::spawn(move || {
|
||||
let sys = System::new();
|
||||
let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let local_addr = tcp.local_addr().unwrap();
|
||||
let lst = net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let local_addr = lst.local_addr().unwrap();
|
||||
|
||||
sys.block_on(async {
|
||||
let server = Server::build()
|
||||
.listen("test", tcp, factory)
|
||||
System::new().block_on(async {
|
||||
let server = server_builder
|
||||
.listen("test", lst, factory)
|
||||
.unwrap()
|
||||
.workers(1)
|
||||
.disable_signals()
|
||||
@@ -93,7 +73,7 @@ impl TestServer {
|
||||
let host = format!("{}", addr.ip());
|
||||
let port = addr.port();
|
||||
|
||||
TestServerRuntime {
|
||||
TestServerHandle {
|
||||
addr,
|
||||
host,
|
||||
port,
|
||||
@@ -107,17 +87,19 @@ impl TestServer {
|
||||
use socket2::{Domain, Protocol, Socket, Type};
|
||||
|
||||
let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
|
||||
let socket =
|
||||
Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP)).unwrap();
|
||||
let domain = Domain::for_address(addr);
|
||||
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP)).unwrap();
|
||||
|
||||
socket.set_reuse_address(true).unwrap();
|
||||
socket.set_nonblocking(true).unwrap();
|
||||
socket.bind(&addr.into()).unwrap();
|
||||
socket.listen(1024).unwrap();
|
||||
|
||||
net::TcpListener::from(socket).local_addr().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl TestServerRuntime {
|
||||
impl TestServerHandle {
|
||||
/// Test server host.
|
||||
pub fn host(&self) -> &str {
|
||||
&self.host
|
||||
@@ -140,12 +122,12 @@ impl TestServerRuntime {
|
||||
}
|
||||
|
||||
/// Connect to server, returning a Tokio `TcpStream`.
|
||||
pub fn connect(&self) -> std::io::Result<TcpStream> {
|
||||
pub fn connect(&self) -> io::Result<TcpStream> {
|
||||
TcpStream::from_std(net::TcpStream::connect(self.addr)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TestServerRuntime {
|
||||
impl Drop for TestServerHandle {
|
||||
fn drop(&mut self) {
|
||||
self.stop()
|
||||
}
|
||||
@@ -158,8 +140,14 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn plain_tokio_runtime() {
|
||||
let srv = TestServer::with(|| fn_service(|_sock| async move { Ok::<_, ()>(()) }));
|
||||
async fn connect_in_tokio_runtime() {
|
||||
let srv = TestServer::start(|| fn_service(|_sock| async move { Ok::<_, ()>(()) }));
|
||||
assert!(srv.connect().is_ok());
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn connect_in_actix_runtime() {
|
||||
let srv = TestServer::start(|| fn_service(|_sock| async move { Ok::<_, ()>(()) }));
|
||||
assert!(srv.connect().is_ok());
|
||||
}
|
||||
}
|
||||
|
@@ -17,11 +17,11 @@ use actix_rt::{
|
||||
Arbiter, ArbiterHandle, System,
|
||||
};
|
||||
use futures_core::{future::LocalBoxFuture, ready};
|
||||
use log::{error, info, trace};
|
||||
use tokio::sync::{
|
||||
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
||||
oneshot,
|
||||
};
|
||||
use tracing::{error, info, trace};
|
||||
|
||||
use crate::{
|
||||
service::{BoxedServerService, InternalServiceFactory},
|
||||
@@ -250,7 +250,7 @@ pub(crate) struct ServerWorkerConfig {
|
||||
impl Default for ServerWorkerConfig {
|
||||
fn default() -> Self {
|
||||
// 512 is the default max blocking thread count of tokio runtime.
|
||||
let max_blocking_threads = std::cmp::max(512 / num_cpus::get(), 1);
|
||||
let max_blocking_threads = std::cmp::max(512 / num_cpus::get_physical(), 1);
|
||||
Self {
|
||||
shutdown_timeout: Duration::from_secs(30),
|
||||
max_blocking_threads,
|
||||
@@ -337,7 +337,7 @@ impl ServerWorker {
|
||||
Ok((token, svc)) => services.push((idx, token, svc)),
|
||||
|
||||
Err(err) => {
|
||||
error!("Can not start worker: {:?}", err);
|
||||
error!("can not start worker: {:?}", err);
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("can not start server service {}", idx),
|
||||
@@ -436,7 +436,7 @@ impl ServerWorker {
|
||||
Ok((token, svc)) => services.push((idx, token, svc)),
|
||||
|
||||
Err(err) => {
|
||||
error!("Can not start worker: {:?}", err);
|
||||
error!("can not start worker: {:?}", err);
|
||||
Arbiter::current().stop();
|
||||
factory_tx
|
||||
.send(Err(io::Error::new(
|
||||
@@ -476,7 +476,7 @@ impl ServerWorker {
|
||||
|
||||
fn restart_service(&mut self, idx: usize, factory_id: usize) {
|
||||
let factory = &self.factories[factory_id];
|
||||
trace!("Service {:?} failed, restarting", factory.name(idx));
|
||||
trace!("service {:?} failed, restarting", factory.name(idx));
|
||||
self.services[idx].status = WorkerServiceStatus::Restarting;
|
||||
self.state = WorkerState::Restarting(Restart {
|
||||
factory_id,
|
||||
@@ -508,7 +508,7 @@ impl ServerWorker {
|
||||
Poll::Ready(Ok(_)) => {
|
||||
if srv.status == WorkerServiceStatus::Unavailable {
|
||||
trace!(
|
||||
"Service {:?} is available",
|
||||
"service {:?} is available",
|
||||
self.factories[srv.factory_idx].name(idx)
|
||||
);
|
||||
srv.status = WorkerServiceStatus::Available;
|
||||
@@ -519,7 +519,7 @@ impl ServerWorker {
|
||||
|
||||
if srv.status == WorkerServiceStatus::Available {
|
||||
trace!(
|
||||
"Service {:?} is unavailable",
|
||||
"service {:?} is unavailable",
|
||||
self.factories[srv.factory_idx].name(idx)
|
||||
);
|
||||
srv.status = WorkerServiceStatus::Unavailable;
|
||||
@@ -527,7 +527,7 @@ impl ServerWorker {
|
||||
}
|
||||
Poll::Ready(Err(_)) => {
|
||||
error!(
|
||||
"Service {:?} readiness check returned error, restarting",
|
||||
"service {:?} readiness check returned error, restarting",
|
||||
self.factories[srv.factory_idx].name(idx)
|
||||
);
|
||||
srv.status = WorkerServiceStatus::Failed;
|
||||
@@ -590,11 +590,11 @@ impl Future for ServerWorker {
|
||||
{
|
||||
let num = this.counter.total();
|
||||
if num == 0 {
|
||||
info!("Shutting down idle worker");
|
||||
info!("shutting down idle worker");
|
||||
let _ = tx.send(true);
|
||||
return Poll::Ready(());
|
||||
} else if graceful {
|
||||
info!("Graceful worker shutdown; finishing {} connections", num);
|
||||
info!("graceful worker shutdown; finishing {} connections", num);
|
||||
this.shutdown(false);
|
||||
|
||||
this.state = WorkerState::Shutdown(Shutdown {
|
||||
@@ -603,7 +603,7 @@ impl Future for ServerWorker {
|
||||
tx,
|
||||
});
|
||||
} else {
|
||||
info!("Force shutdown worker, closing {} connections", num);
|
||||
info!("force shutdown worker, closing {} connections", num);
|
||||
this.shutdown(true);
|
||||
|
||||
let _ = tx.send(false);
|
||||
@@ -638,7 +638,7 @@ impl Future for ServerWorker {
|
||||
assert_eq!(token, token_new);
|
||||
|
||||
trace!(
|
||||
"Service {:?} has been restarted",
|
||||
"service {:?} has been restarted",
|
||||
this.factories[factory_id].name(token)
|
||||
);
|
||||
|
||||
@@ -685,7 +685,7 @@ impl Future for ServerWorker {
|
||||
match this.check_readiness(cx) {
|
||||
Ok(true) => {}
|
||||
Ok(false) => {
|
||||
trace!("Worker is unavailable");
|
||||
trace!("worker is unavailable");
|
||||
this.state = WorkerState::Unavailable;
|
||||
return self.poll(cx);
|
||||
}
|
||||
|
@@ -26,20 +26,54 @@ fn test_bind() {
|
||||
let srv = Server::build()
|
||||
.workers(1)
|
||||
.disable_signals()
|
||||
.shutdown_timeout(3600)
|
||||
.bind("test", addr, move || {
|
||||
fn_service(|_| async { Ok::<_, ()>(()) })
|
||||
})?
|
||||
.run();
|
||||
|
||||
let _ = tx.send(srv.handle());
|
||||
|
||||
tx.send(srv.handle()).unwrap();
|
||||
srv.await
|
||||
})
|
||||
});
|
||||
|
||||
let srv = rx.recv().unwrap();
|
||||
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
assert!(net::TcpStream::connect(addr).is_ok());
|
||||
|
||||
net::TcpStream::connect(addr).unwrap();
|
||||
|
||||
let _ = srv.stop(true);
|
||||
h.join().unwrap().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_listen() {
|
||||
let addr = unused_addr();
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let lst = net::TcpListener::bind(addr).unwrap();
|
||||
|
||||
let h = thread::spawn(move || {
|
||||
actix_rt::System::new().block_on(async {
|
||||
let srv = Server::build()
|
||||
.workers(1)
|
||||
.disable_signals()
|
||||
.shutdown_timeout(3600)
|
||||
.listen("test", lst, move || {
|
||||
fn_service(|_| async { Ok::<_, ()>(()) })
|
||||
})?
|
||||
.run();
|
||||
|
||||
tx.send(srv.handle()).unwrap();
|
||||
srv.await
|
||||
})
|
||||
});
|
||||
|
||||
let srv = rx.recv().unwrap();
|
||||
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
|
||||
net::TcpStream::connect(addr).unwrap();
|
||||
|
||||
let _ = srv.stop(true);
|
||||
h.join().unwrap().unwrap();
|
||||
@@ -80,38 +114,6 @@ fn plain_tokio_runtime() {
|
||||
h.join().unwrap().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_listen() {
|
||||
let addr = unused_addr();
|
||||
let lst = net::TcpListener::bind(addr).unwrap();
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
let h = thread::spawn(move || {
|
||||
actix_rt::System::new().block_on(async {
|
||||
let srv = Server::build()
|
||||
.disable_signals()
|
||||
.workers(1)
|
||||
.listen("test", lst, move || {
|
||||
fn_service(|_| async { Ok::<_, ()>(()) })
|
||||
})?
|
||||
.run();
|
||||
|
||||
let _ = tx.send(srv.handle());
|
||||
|
||||
srv.await
|
||||
})
|
||||
});
|
||||
|
||||
let srv = rx.recv().unwrap();
|
||||
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
assert!(net::TcpStream::connect(addr).is_ok());
|
||||
|
||||
let _ = srv.stop(true);
|
||||
h.join().unwrap().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_start() {
|
||||
@@ -184,9 +186,9 @@ fn test_start() {
|
||||
#[actix_rt::test]
|
||||
async fn test_max_concurrent_connections() {
|
||||
// Note:
|
||||
// A tcp listener would accept connects based on it's backlog setting.
|
||||
// A TCP listener would accept connects based on it's backlog setting.
|
||||
//
|
||||
// The limit test on the other hand is only for concurrent tcp stream limiting a work
|
||||
// The limit test on the other hand is only for concurrent TCP stream limiting a work
|
||||
// thread accept.
|
||||
|
||||
use tokio::io::AsyncWriteExt;
|
||||
@@ -252,6 +254,7 @@ async fn test_max_concurrent_connections() {
|
||||
h.join().unwrap().unwrap();
|
||||
}
|
||||
|
||||
// TODO: race-y failures detected due to integer underflow when calling Counter::total
|
||||
#[actix_rt::test]
|
||||
async fn test_service_restart() {
|
||||
use std::task::{Context, Poll};
|
73
actix-server/tests/testing_server.rs
Normal file
73
actix-server/tests/testing_server.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use std::net;
|
||||
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_server::{Server, TestServer};
|
||||
use actix_service::fn_service;
|
||||
use bytes::BytesMut;
|
||||
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
|
||||
|
||||
macro_rules! await_timeout_ms {
|
||||
($fut:expr, $limit:expr) => {
|
||||
::actix_rt::time::timeout(::std::time::Duration::from_millis($limit), $fut)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
};
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn testing_server_echo() {
|
||||
let srv = TestServer::start(|| {
|
||||
fn_service(move |mut stream: TcpStream| async move {
|
||||
let mut size = 0;
|
||||
let mut buf = BytesMut::new();
|
||||
|
||||
match stream.read_buf(&mut buf).await {
|
||||
Ok(0) => return Err(()),
|
||||
|
||||
Ok(bytes_read) => {
|
||||
stream.write_all(&buf[size..]).await.unwrap();
|
||||
size += bytes_read;
|
||||
}
|
||||
|
||||
Err(_) => return Err(()),
|
||||
}
|
||||
|
||||
Ok((buf.freeze(), size))
|
||||
})
|
||||
});
|
||||
|
||||
let mut conn = srv.connect().unwrap();
|
||||
|
||||
await_timeout_ms!(conn.write_all(b"test"), 200);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
await_timeout_ms!(conn.read_to_end(&mut buf), 200);
|
||||
|
||||
assert_eq!(&buf, b"test".as_ref());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn new_with_builder() {
|
||||
let alt_addr = TestServer::unused_addr();
|
||||
|
||||
let srv = TestServer::start_with_builder(
|
||||
Server::build()
|
||||
.bind("alt", alt_addr, || {
|
||||
fn_service(|_| async { Ok::<_, ()>(()) })
|
||||
})
|
||||
.unwrap(),
|
||||
|| {
|
||||
fn_service(|mut sock: TcpStream| async move {
|
||||
let mut buf = [0u8; 16];
|
||||
sock.read_exact(&mut buf).await
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
// connect to test server
|
||||
srv.connect().unwrap();
|
||||
|
||||
// connect to alt service defined in custom ServerBuilder
|
||||
TcpStream::from_std(net::TcpStream::connect(alt_addr).unwrap()).unwrap();
|
||||
}
|
@@ -1,57 +1,63 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
* Service types can now be `Send` and `'static` regardless of request, response, and config types, etc.. [#397]
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 2.0.2 - 2021-12-18
|
||||
- Service types can now be `Send` and `'static` regardless of request, response, and config types, etc. [#397]
|
||||
|
||||
[#397]: https://github.com/actix/actix-net/pull/397
|
||||
|
||||
|
||||
## 2.0.1 - 2021-10-11
|
||||
* Documentation fix.
|
||||
- Documentation fix. [#388]
|
||||
|
||||
[#388]: https://github.com/actix/actix-net/pull/388
|
||||
|
||||
|
||||
## 2.0.0 - 2021-04-16
|
||||
* Removed pipeline and related structs/functions. [#335]
|
||||
- Removed pipeline and related structs/functions. [#335]
|
||||
|
||||
[#335]: https://github.com/actix/actix-net/pull/335
|
||||
|
||||
|
||||
## 2.0.0-beta.5 - 2021-03-15
|
||||
* Add default `Service` trait impl for `Rc<S: Service>` and `&S: Service`. [#288]
|
||||
* Add `boxed::rc_service` function for constructing `boxed::RcService` type [#290]
|
||||
- Add default `Service` trait impl for `Rc<S: Service>` and `&S: Service`. [#288]
|
||||
- Add `boxed::rc_service` function for constructing `boxed::RcService` type [#290]
|
||||
|
||||
[#288]: https://github.com/actix/actix-net/pull/288
|
||||
[#290]: https://github.com/actix/actix-net/pull/290
|
||||
|
||||
|
||||
## 2.0.0-beta.4 - 2021-02-04
|
||||
* `Service::poll_ready` and `Service::call` receive `&self`. [#247]
|
||||
* `apply_fn` and `apply_fn_factory` now receive `Fn(Req, &Service)` function type. [#247]
|
||||
* `apply_cfg` and `apply_cfg_factory` now receive `Fn(Req, &Service)` function type. [#247]
|
||||
* `fn_service` and friends now receive `Fn(Req)` function type. [#247]
|
||||
- `Service::poll_ready` and `Service::call` receive `&self`. [#247]
|
||||
- `apply_fn` and `apply_fn_factory` now receive `Fn(Req, &Service)` function type. [#247]
|
||||
- `apply_cfg` and `apply_cfg_factory` now receive `Fn(Req, &Service)` function type. [#247]
|
||||
- `fn_service` and friends now receive `Fn(Req)` function type. [#247]
|
||||
|
||||
[#247]: https://github.com/actix/actix-net/pull/247
|
||||
|
||||
|
||||
## 2.0.0-beta.3 - 2021-01-09
|
||||
* The `forward_ready!` macro converts errors. [#246]
|
||||
- The `forward_ready!` macro converts errors. [#246]
|
||||
|
||||
[#246]: https://github.com/actix/actix-net/pull/246
|
||||
|
||||
|
||||
## 2.0.0-beta.2 - 2021-01-03
|
||||
* Remove redundant type parameter from `map_config`.
|
||||
- Remove redundant type parameter from `map_config`.
|
||||
|
||||
|
||||
## 2.0.0-beta.1 - 2020-12-28
|
||||
* `Service`, other traits, and many type signatures now take the the request type as a type
|
||||
- `Service`, other traits, and many type signatures now take the the request type as a type
|
||||
parameter instead of an associated type. [#232]
|
||||
* Add `always_ready!` and `forward_ready!` macros. [#233]
|
||||
* Crate is now `no_std`. [#233]
|
||||
* Migrate pin projections to `pin-project-lite`. [#233]
|
||||
* Remove `AndThenApplyFn` and Pipeline `and_then_apply_fn`. Use the
|
||||
- Add `always_ready!` and `forward_ready!` macros. [#233]
|
||||
- Crate is now `no_std`. [#233]
|
||||
- Migrate pin projections to `pin-project-lite`. [#233]
|
||||
- Remove `AndThenApplyFn` and Pipeline `and_then_apply_fn`. Use the
|
||||
`.and_then(apply_fn(...))` construction. [#233]
|
||||
* Move non-vital methods to `ServiceExt` and `ServiceFactoryExt` extension traits. [#235]
|
||||
- Move non-vital methods to `ServiceExt` and `ServiceFactoryExt` extension traits. [#235]
|
||||
|
||||
[#232]: https://github.com/actix/actix-net/pull/232
|
||||
[#233]: https://github.com/actix/actix-net/pull/233
|
||||
@@ -59,123 +65,123 @@
|
||||
|
||||
|
||||
## 1.0.6 - 2020-08-09
|
||||
* Removed unsound custom Cell implementation that allowed obtaining several mutable references to
|
||||
- Removed unsound custom Cell implementation that allowed obtaining several mutable references to
|
||||
the same data, which is undefined behavior in Rust and could lead to violations of memory safety. External code could obtain several mutable references to the same data through
|
||||
service combinators. Attempts to acquire several mutable references to the same data will instead
|
||||
result in a panic.
|
||||
|
||||
|
||||
## 1.0.5 - 2020-01-16
|
||||
* Fixed unsoundness in .and_then()/.then() service combinators.
|
||||
- Fixed unsoundness in .and_then()/.then() service combinators.
|
||||
|
||||
|
||||
## 1.0.4 - 2020-01-15
|
||||
* Revert 1.0.3 change
|
||||
- Revert 1.0.3 change
|
||||
|
||||
|
||||
## 1.0.3 - 2020-01-15
|
||||
* Fixed unsoundness in `AndThenService` impl.
|
||||
- Fixed unsoundness in `AndThenService` impl.
|
||||
|
||||
|
||||
## 1.0.2 - 2020-01-08
|
||||
* Add `into_service` helper function.
|
||||
- Add `into_service` helper function.
|
||||
|
||||
|
||||
## 1.0.1 - 2019-12-22
|
||||
* `map_config()` and `unit_config()` now accept `IntoServiceFactory` type.
|
||||
- `map_config()` and `unit_config()` now accept `IntoServiceFactory` type.
|
||||
|
||||
|
||||
## 1.0.0 - 2019-12-11
|
||||
* Add Clone impl for Apply service
|
||||
- Add Clone impl for Apply service
|
||||
|
||||
|
||||
## 1.0.0-alpha.4 - 2019-12-08
|
||||
* Renamed `service_fn` to `fn_service`
|
||||
* Renamed `factory_fn` to `fn_factory`
|
||||
* Renamed `factory_fn_cfg` to `fn_factory_with_config`
|
||||
- Renamed `service_fn` to `fn_service`
|
||||
- Renamed `factory_fn` to `fn_factory`
|
||||
- Renamed `factory_fn_cfg` to `fn_factory_with_config`
|
||||
|
||||
|
||||
## 1.0.0-alpha.3 - 2019-12-06
|
||||
* Add missing Clone impls
|
||||
* Restore `Transform::map_init_err()` combinator
|
||||
* Restore `Service/Factory::apply_fn()` in form of `Pipeline/Factory::and_then_apply_fn()`
|
||||
* Optimize service combinators and futures memory layout
|
||||
- Add missing Clone impls
|
||||
- Restore `Transform::map_init_err()` combinator
|
||||
- Restore `Service/Factory::apply_fn()` in form of `Pipeline/Factory::and_then_apply_fn()`
|
||||
- Optimize service combinators and futures memory layout
|
||||
|
||||
|
||||
## 1.0.0-alpha.2 - 2019-12-02
|
||||
* Use owned config value for service factory
|
||||
* Renamed BoxedNewService/BoxedService to BoxServiceFactory/BoxService
|
||||
- Use owned config value for service factory
|
||||
- Renamed BoxedNewService/BoxedService to BoxServiceFactory/BoxService
|
||||
|
||||
|
||||
## 1.0.0-alpha.1 - 2019-11-25
|
||||
* Migrated to `std::future`
|
||||
* `NewService` renamed to `ServiceFactory`
|
||||
* Added `pipeline` and `pipeline_factory` function
|
||||
- Migrated to `std::future`
|
||||
- `NewService` renamed to `ServiceFactory`
|
||||
- Added `pipeline` and `pipeline_factory` function
|
||||
|
||||
|
||||
## 0.4.2 - 2019-08-27
|
||||
* Check service readiness for `new_apply_cfg` combinator
|
||||
- Check service readiness for `new_apply_cfg` combinator
|
||||
|
||||
|
||||
## 0.4.1 - 2019-06-06
|
||||
* Add `new_apply_cfg` function
|
||||
- Add `new_apply_cfg` function
|
||||
|
||||
|
||||
## 0.4.0 - 2019-05-12
|
||||
* Add `NewService::map_config` and `NewService::unit_config` combinators.
|
||||
* Use associated type for `NewService` config.
|
||||
* Change `apply_cfg` function.
|
||||
* Renamed helper functions.
|
||||
- Add `NewService::map_config` and `NewService::unit_config` combinators.
|
||||
- Use associated type for `NewService` config.
|
||||
- Change `apply_cfg` function.
|
||||
- Renamed helper functions.
|
||||
|
||||
|
||||
## 0.3.6 - 2019-04-07
|
||||
* Poll boxed service call result immediately
|
||||
- Poll boxed service call result immediately
|
||||
|
||||
|
||||
## 0.3.5 - 2019-03-29
|
||||
* Add `impl<S: Service> Service for Rc<RefCell<S>>`.
|
||||
- Add `impl<S: Service> Service for Rc<RefCell<S>>`.
|
||||
|
||||
|
||||
## 0.3.4 - 2019-03-12
|
||||
* Add `Transform::from_err()` combinator
|
||||
* Add `apply_fn` helper
|
||||
* Add `apply_fn_factory` helper
|
||||
* Add `apply_transform` helper
|
||||
* Add `apply_cfg` helper
|
||||
- Add `Transform::from_err()` combinator
|
||||
- Add `apply_fn` helper
|
||||
- Add `apply_fn_factory` helper
|
||||
- Add `apply_transform` helper
|
||||
- Add `apply_cfg` helper
|
||||
|
||||
|
||||
## 0.3.3 - 2019-03-09
|
||||
* Add `ApplyTransform` new service for transform and new service.
|
||||
* Add `NewService::apply_cfg()` combinator, allows to use nested `NewService` with different config parameter.
|
||||
* Revert IntoFuture change
|
||||
- Add `ApplyTransform` new service for transform and new service.
|
||||
- Add `NewService::apply_cfg()` combinator, allows to use nested `NewService` with different config parameter.
|
||||
- Revert IntoFuture change
|
||||
|
||||
|
||||
## 0.3.2 - 2019-03-04
|
||||
* Change `NewService::Future` and `Transform::Future` to the `IntoFuture` trait.
|
||||
* Export `AndThenTransform` type
|
||||
- Change `NewService::Future` and `Transform::Future` to the `IntoFuture` trait.
|
||||
- Export `AndThenTransform` type
|
||||
|
||||
|
||||
## 0.3.1 - 2019-03-04
|
||||
* Simplify Transform trait
|
||||
- Simplify Transform trait
|
||||
|
||||
|
||||
## 0.3.0 - 2019-03-02
|
||||
* Added boxed NewService and Service.
|
||||
* Added `Config` parameter to `NewService` trait.
|
||||
* Added `Config` parameter to `NewTransform` trait.
|
||||
- Added boxed NewService and Service.
|
||||
- Added `Config` parameter to `NewService` trait.
|
||||
- Added `Config` parameter to `NewTransform` trait.
|
||||
|
||||
|
||||
## 0.2.2 - 2019-02-19
|
||||
* Added `NewService` impl for `Rc<S> where S: NewService`
|
||||
* Added `NewService` impl for `Arc<S> where S: NewService`
|
||||
- Added `NewService` impl for `Rc<S> where S: NewService`
|
||||
- Added `NewService` impl for `Arc<S> where S: NewService`
|
||||
|
||||
|
||||
## 0.2.1 - 2019-02-03
|
||||
* Generalize `.apply` combinator with Transform trait
|
||||
- Generalize `.apply` combinator with Transform trait
|
||||
|
||||
|
||||
## 0.2.0 - 2019-02-01
|
||||
* Use associated type instead of generic for Service definition.
|
||||
- Use associated type instead of generic for Service definition.
|
||||
* Before:
|
||||
```rust
|
||||
impl Service<Request> for Client {
|
||||
@@ -194,29 +200,29 @@
|
||||
|
||||
|
||||
## 0.1.6 - 2019-01-24
|
||||
* Use `FnMut` instead of `Fn` for .apply() and .map() combinators and `FnService` type
|
||||
* Change `.apply()` error semantic, new service's error is `From<Self::Error>`
|
||||
- Use `FnMut` instead of `Fn` for .apply() and .map() combinators and `FnService` type
|
||||
- Change `.apply()` error semantic, new service's error is `From<Self::Error>`
|
||||
|
||||
|
||||
## 0.1.5 - 2019-01-13
|
||||
* Make `Out::Error` convertible from `T::Error` for apply combinator
|
||||
- Make `Out::Error` convertible from `T::Error` for apply combinator
|
||||
|
||||
|
||||
## 0.1.4 - 2019-01-11
|
||||
* Use `FnMut` instead of `Fn` for `FnService`
|
||||
- Use `FnMut` instead of `Fn` for `FnService`
|
||||
|
||||
|
||||
## 0.1.3 - 2018-12-12
|
||||
* Split service combinators to separate trait
|
||||
- Split service combinators to separate trait
|
||||
|
||||
|
||||
## 0.1.2 - 2018-12-12
|
||||
* Release future early for `.and_then()` and `.then()` combinators
|
||||
- Release future early for `.and_then()` and `.then()` combinators
|
||||
|
||||
|
||||
## 0.1.1 - 2018-12-09
|
||||
* Added Service impl for `Box<S: Service>`
|
||||
- Added Service impl for `Box<S: Service>`
|
||||
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
* Initial import
|
||||
- Initial import
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-service"
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
@@ -23,6 +23,6 @@ paste = "1"
|
||||
pin-project-lite = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-rt = "2"
|
||||
actix-utils = "3"
|
||||
futures-util = { version = "0.3.7", default-features = false }
|
||||
|
@@ -3,10 +3,10 @@
|
||||
> Service trait and combinators for representing asynchronous request/response operations.
|
||||
|
||||
[](https://crates.io/crates/actix-service)
|
||||
[](https://docs.rs/actix-service/2.0.1)
|
||||
[](https://docs.rs/actix-service/2.0.2)
|
||||
[](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
|
||||

|
||||
[](https://deps.rs/crate/actix-service/2.0.1)
|
||||
[](https://deps.rs/crate/actix-service/2.0.2)
|
||||

|
||||
[](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
|
@@ -394,9 +394,10 @@ mod tests {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_auto_impl_send() {
|
||||
use crate::{map_config, ServiceExt, ServiceFactoryExt};
|
||||
use alloc::rc::Rc;
|
||||
|
||||
use crate::{map_config, ServiceExt, ServiceFactoryExt};
|
||||
|
||||
let srv_1 = fn_service(|_: Rc<u8>| ok::<_, Rc<u8>>(Rc::new(0u8)));
|
||||
|
||||
let fac_1 = fn_factory_with_config(|_: Rc<u8>| {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
//! See [`Service`] docs for information on this crate's foundational trait.
|
||||
|
||||
#![no_std]
|
||||
#![deny(rust_2018_idioms, nonstandard_style, future_incompatible)]
|
||||
#![warn(missing_docs)]
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
#![allow(clippy::type_complexity)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
@@ -38,10 +38,9 @@ pub use self::apply_cfg::{apply_cfg, apply_cfg_factory};
|
||||
pub use self::ext::{ServiceExt, ServiceFactoryExt, TransformExt};
|
||||
pub use self::fn_service::{fn_factory, fn_factory_with_config, fn_service};
|
||||
pub use self::map_config::{map_config, unit_config};
|
||||
pub use self::transform::{apply, ApplyTransform, Transform};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use self::ready::{err, ok, ready, Ready};
|
||||
pub use self::transform::{apply, ApplyTransform, Transform};
|
||||
|
||||
/// An asynchronous operation from `Request` to a `Response`.
|
||||
///
|
||||
|
@@ -25,6 +25,8 @@
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`forward_ready!`]: crate::forward_ready
|
||||
#[macro_export]
|
||||
macro_rules! always_ready {
|
||||
() => {
|
||||
|
@@ -97,7 +97,7 @@ where
|
||||
|
||||
match this.fut.poll(cx) {
|
||||
Poll::Ready(Ok(resp)) => Poll::Ready(Ok((this.f)(resp))),
|
||||
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
|
||||
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
|
@@ -1,82 +1,113 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 3.0.4 - 2022-03-15
|
||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
|
||||
|
||||
[#451]: https://github.com/actix/actix-net/pull/451
|
||||
|
||||
|
||||
## 3.0.3 - 2022-02-15
|
||||
- No significant changes since `3.0.2`.
|
||||
|
||||
|
||||
## 3.0.2 - 2022-01-28
|
||||
- Expose `connect::Connection::new`. [#439]
|
||||
|
||||
[#439]: https://github.com/actix/actix-net/pull/439
|
||||
|
||||
|
||||
## 3.0.1 - 2022-01-11
|
||||
- No significant changes since `3.0.0`.
|
||||
|
||||
|
||||
## 3.0.0 - 2021-12-26
|
||||
- No significant changes since `3.0.0-rc.2`.
|
||||
|
||||
|
||||
## 3.0.0-rc.2 - 2021-12-10
|
||||
- Re-export `openssl::SslConnectorBuilder` in `connect::openssl::reexports`. [#429]
|
||||
|
||||
[#429]: https://github.com/actix/actix-net/pull/429
|
||||
|
||||
|
||||
## 3.0.0-rc.1 - 2021-11-29
|
||||
### Added
|
||||
* Derive `Debug` for `connect::Connection`. [#422]
|
||||
* Implement `Display` for `accept::TlsError`. [#422]
|
||||
* Implement `Error` for `accept::TlsError` where both types also implement `Error`. [#422]
|
||||
* Implement `Default` for `connect::Resolver`. [#422]
|
||||
* Implement `Error` for `connect::ConnectError`. [#422]
|
||||
* Implement `Default` for `connect::tcp::{TcpConnector, TcpConnectorService}`. [#423]
|
||||
* Implement `Default` for `connect::ConnectorService`. [#423]
|
||||
- Derive `Debug` for `connect::Connection`. [#422]
|
||||
- Implement `Display` for `accept::TlsError`. [#422]
|
||||
- Implement `Error` for `accept::TlsError` where both types also implement `Error`. [#422]
|
||||
- Implement `Default` for `connect::Resolver`. [#422]
|
||||
- Implement `Error` for `connect::ConnectError`. [#422]
|
||||
- Implement `Default` for `connect::tcp::{TcpConnector, TcpConnectorService}`. [#423]
|
||||
- Implement `Default` for `connect::ConnectorService`. [#423]
|
||||
|
||||
### Changed
|
||||
* The crate's default features flags no longer include `uri`. [#422]
|
||||
* Useful re-exports from underlying TLS crates are exposed in a `reexports` modules in all acceptors and connectors.
|
||||
* Convert `connect::ResolverService` from enum to struct. [#422]
|
||||
* Make `ConnectAddrsIter` private. [#422]
|
||||
* Mark `tcp::{TcpConnector, TcpConnectorService}` structs `#[non_exhaustive]`. [#423]
|
||||
* Rename `accept::native_tls::{NativeTlsAcceptorService => AcceptorService}`. [#422]
|
||||
* Rename `connect::{Address => Host}` trait. [#422]
|
||||
* Rename method `connect::Connection::{host => hostname}`. [#422]
|
||||
* Rename struct `connect::{Connect => ConnectInfo}`. [#422]
|
||||
* Rename struct `connect::{ConnectService => ConnectorService}`. [#422]
|
||||
* Rename struct `connect::{ConnectServiceFactory => Connector}`. [#422]
|
||||
* Rename TLS acceptor service future types and hide from docs. [#422]
|
||||
* Unbox some service futures types. [#422]
|
||||
* Inline modules in `connect::tls` to `connect` module. [#422]
|
||||
- The crate's default features flags no longer include `uri`. [#422]
|
||||
- Useful re-exports from underlying TLS crates are exposed in a `reexports` modules in all acceptors and connectors.
|
||||
- Convert `connect::ResolverService` from enum to struct. [#422]
|
||||
- Make `ConnectAddrsIter` private. [#422]
|
||||
- Mark `tcp::{TcpConnector, TcpConnectorService}` structs `#[non_exhaustive]`. [#423]
|
||||
- Rename `accept::native_tls::{NativeTlsAcceptorService => AcceptorService}`. [#422]
|
||||
- Rename `connect::{Address => Host}` trait. [#422]
|
||||
- Rename method `connect::Connection::{host => hostname}`. [#422]
|
||||
- Rename struct `connect::{Connect => ConnectInfo}`. [#422]
|
||||
- Rename struct `connect::{ConnectService => ConnectorService}`. [#422]
|
||||
- Rename struct `connect::{ConnectServiceFactory => Connector}`. [#422]
|
||||
- Rename TLS acceptor service future types and hide from docs. [#422]
|
||||
- Unbox some service futures types. [#422]
|
||||
- Inline modules in `connect::tls` to `connect` module. [#422]
|
||||
|
||||
### Removed
|
||||
* Remove `connect::{new_connector, new_connector_factory, default_connector, default_connector_factory}` methods. [#422]
|
||||
* Remove `connect::native_tls::Connector::service` method. [#422]
|
||||
* Remove redundant `connect::Connection::from_parts` method. [#422]
|
||||
- Remove `connect::{new_connector, new_connector_factory, default_connector, default_connector_factory}` methods. [#422]
|
||||
- Remove `connect::native_tls::Connector::service` method. [#422]
|
||||
- Remove redundant `connect::Connection::from_parts` method. [#422]
|
||||
|
||||
[#422]: https://github.com/actix/actix-net/pull/422
|
||||
[#423]: https://github.com/actix/actix-net/pull/423
|
||||
|
||||
|
||||
## 3.0.0-beta.9 - 2021-11-22
|
||||
* Add configurable timeout for accepting TLS connection. [#393]
|
||||
* Added `TlsError::Timeout` variant. [#393]
|
||||
* All TLS acceptor services now use `TlsError` for their error types. [#393]
|
||||
* Added `TlsError::into_service_error`. [#420]
|
||||
- Add configurable timeout for accepting TLS connection. [#393]
|
||||
- Added `TlsError::Timeout` variant. [#393]
|
||||
- All TLS acceptor services now use `TlsError` for their error types. [#393]
|
||||
- Added `TlsError::into_service_error`. [#420]
|
||||
|
||||
[#393]: https://github.com/actix/actix-net/pull/393
|
||||
[#420]: https://github.com/actix/actix-net/pull/420
|
||||
|
||||
|
||||
## 3.0.0-beta.8 - 2021-11-15
|
||||
* Add `Connect::request` for getting a reference to the connection request. [#415]
|
||||
- Add `Connect::request` for getting a reference to the connection request. [#415]
|
||||
|
||||
[#415]: https://github.com/actix/actix-net/pull/415
|
||||
|
||||
|
||||
## 3.0.0-beta.7 - 2021-10-20
|
||||
* Add `webpki_roots_cert_store()` to get rustls compatible webpki roots cert store. [#401]
|
||||
* Alias `connect::ssl` to `connect::tls`. [#401]
|
||||
- Add `webpki_roots_cert_store()` to get rustls compatible webpki roots cert store. [#401]
|
||||
- Alias `connect::ssl` to `connect::tls`. [#401]
|
||||
|
||||
[#401]: https://github.com/actix/actix-net/pull/401
|
||||
|
||||
|
||||
## 3.0.0-beta.6 - 2021-10-19
|
||||
* Update `tokio-rustls` to `0.23` which uses `rustls` `0.20`. [#396]
|
||||
* Removed a re-export of `Session` from `rustls` as it no longer exist. [#396]
|
||||
* Minimum supported Rust version (MSRV) is now 1.52.
|
||||
- Update `tokio-rustls` to `0.23` which uses `rustls` `0.20`. [#396]
|
||||
- Removed a re-export of `Session` from `rustls` as it no longer exist. [#396]
|
||||
- Minimum supported Rust version (MSRV) is now 1.52.
|
||||
|
||||
[#396]: https://github.com/actix/actix-net/pull/396
|
||||
|
||||
|
||||
## 3.0.0-beta.5 - 2021-03-29
|
||||
* Changed `connect::ssl::rustls::RustlsConnectorService` to return error when `DNSNameRef`
|
||||
- Changed `connect::ssl::rustls::RustlsConnectorService` to return error when `DNSNameRef`
|
||||
generation failed instead of panic. [#296]
|
||||
* Remove `connect::ssl::openssl::OpensslConnectServiceFactory`. [#297]
|
||||
* Remove `connect::ssl::openssl::OpensslConnectService`. [#297]
|
||||
* Add `connect::ssl::native_tls` module for native tls support. [#295]
|
||||
* Rename `accept::{nativetls => native_tls}`. [#295]
|
||||
* Remove `connect::TcpConnectService` type. Service caller expecting a `TcpStream` should use `connect::ConnectService` instead and call `Connection<T, TcpStream>::into_parts`. [#299]
|
||||
- Remove `connect::ssl::openssl::OpensslConnectServiceFactory`. [#297]
|
||||
- Remove `connect::ssl::openssl::OpensslConnectService`. [#297]
|
||||
- Add `connect::ssl::native_tls` module for native tls support. [#295]
|
||||
- Rename `accept::{nativetls => native_tls}`. [#295]
|
||||
- Remove `connect::TcpConnectService` type. Service caller expecting a `TcpStream` should use `connect::ConnectService` instead and call `Connection<T, TcpStream>::into_parts`. [#299]
|
||||
|
||||
[#295]: https://github.com/actix/actix-net/pull/295
|
||||
[#296]: https://github.com/actix/actix-net/pull/296
|
||||
@@ -85,72 +116,72 @@
|
||||
|
||||
|
||||
## 3.0.0-beta.4 - 2021-02-24
|
||||
* Rename `accept::openssl::{SslStream => TlsStream}`.
|
||||
* Add `connect::Connect::set_local_addr` to attach local `IpAddr`. [#282]
|
||||
* `connector::TcpConnector` service will try to bind to local_addr of `IpAddr` when given. [#282]
|
||||
- Rename `accept::openssl::{SslStream => TlsStream}`.
|
||||
- Add `connect::Connect::set_local_addr` to attach local `IpAddr`. [#282]
|
||||
- `connector::TcpConnector` service will try to bind to local_addr of `IpAddr` when given. [#282]
|
||||
|
||||
[#282]: https://github.com/actix/actix-net/pull/282
|
||||
|
||||
|
||||
## 3.0.0-beta.3 - 2021-02-06
|
||||
* Remove `trust-dns-proto` and `trust-dns-resolver`. [#248]
|
||||
* Use `std::net::ToSocketAddrs` as simple and basic default resolver. [#248]
|
||||
* Add `Resolve` trait for custom DNS resolvers. [#248]
|
||||
* Add `Resolver::new_custom` function to construct custom resolvers. [#248]
|
||||
* Export `webpki_roots::TLS_SERVER_ROOTS` in `actix_tls::connect` mod and remove
|
||||
- Remove `trust-dns-proto` and `trust-dns-resolver`. [#248]
|
||||
- Use `std::net::ToSocketAddrs` as simple and basic default resolver. [#248]
|
||||
- Add `Resolve` trait for custom DNS resolvers. [#248]
|
||||
- Add `Resolver::new_custom` function to construct custom resolvers. [#248]
|
||||
- Export `webpki_roots::TLS_SERVER_ROOTS` in `actix_tls::connect` mod and remove
|
||||
the export from `actix_tls::accept` [#248]
|
||||
* Remove `ConnectTakeAddrsIter`. `Connect::take_addrs` now returns `ConnectAddrsIter<'static>`
|
||||
- Remove `ConnectTakeAddrsIter`. `Connect::take_addrs` now returns `ConnectAddrsIter<'static>`
|
||||
as owned iterator. [#248]
|
||||
* Rename `Address::{host => hostname}` to more accurately describe which URL segment is returned.
|
||||
* Update `actix-rt` to `2.0.0`. [#273]
|
||||
- Rename `Address::{host => hostname}` to more accurately describe which URL segment is returned.
|
||||
- Update `actix-rt` to `2.0.0`. [#273]
|
||||
|
||||
[#248]: https://github.com/actix/actix-net/pull/248
|
||||
[#273]: https://github.com/actix/actix-net/pull/273
|
||||
|
||||
|
||||
## 3.0.0-beta.2 - 2021-xx-xx
|
||||
* Depend on stable trust-dns packages. [#204]
|
||||
## 3.0.0-beta.2 - 2022-xx-xx
|
||||
- Depend on stable trust-dns packages. [#204]
|
||||
|
||||
[#204]: https://github.com/actix/actix-net/pull/204
|
||||
|
||||
|
||||
## 3.0.0-beta.1 - 2020-12-29
|
||||
* Move acceptors under `accept` module. [#238]
|
||||
* Merge `actix-connect` crate under `connect` module. [#238]
|
||||
* Add feature flags to enable acceptors and/or connectors individually. [#238]
|
||||
- Move acceptors under `accept` module. [#238]
|
||||
- Merge `actix-connect` crate under `connect` module. [#238]
|
||||
- Add feature flags to enable acceptors and/or connectors individually. [#238]
|
||||
|
||||
[#238]: https://github.com/actix/actix-net/pull/238
|
||||
|
||||
|
||||
## 2.0.0 - 2020-09-03
|
||||
* `nativetls::NativeTlsAcceptor` is renamed to `nativetls::Acceptor`.
|
||||
* Where possible, "SSL" terminology is replaced with "TLS".
|
||||
- `nativetls::NativeTlsAcceptor` is renamed to `nativetls::Acceptor`.
|
||||
- Where possible, "SSL" terminology is replaced with "TLS".
|
||||
* `SslError` is renamed to `TlsError`.
|
||||
* `TlsError::Ssl` enum variant is renamed to `TlsError::Tls`.
|
||||
* `max_concurrent_ssl_connect` is renamed to `max_concurrent_tls_connect`.
|
||||
|
||||
|
||||
## 2.0.0-alpha.2 - 2020-08-17
|
||||
* Update `rustls` dependency to 0.18
|
||||
* Update `tokio-rustls` dependency to 0.14
|
||||
* Update `webpki-roots` dependency to 0.20
|
||||
- Update `rustls` dependency to 0.18
|
||||
- Update `tokio-rustls` dependency to 0.14
|
||||
- Update `webpki-roots` dependency to 0.20
|
||||
|
||||
|
||||
## [2.0.0-alpha.1] - 2020-03-03
|
||||
* Update `rustls` dependency to 0.17
|
||||
* Update `tokio-rustls` dependency to 0.13
|
||||
* Update `webpki-roots` dependency to 0.19
|
||||
- Update `rustls` dependency to 0.17
|
||||
- Update `tokio-rustls` dependency to 0.13
|
||||
- Update `webpki-roots` dependency to 0.19
|
||||
|
||||
|
||||
## [1.0.0] - 2019-12-11
|
||||
* 1.0.0 release
|
||||
- 1.0.0 release
|
||||
|
||||
|
||||
## [1.0.0-alpha.3] - 2019-12-07
|
||||
* Migrate to tokio 0.2
|
||||
* Enable rustls acceptor service
|
||||
* Enable native-tls acceptor service
|
||||
- Migrate to tokio 0.2
|
||||
- Enable rustls acceptor service
|
||||
- Enable native-tls acceptor service
|
||||
|
||||
|
||||
## [1.0.0-alpha.1] - 2019-12-02
|
||||
* Split openssl acceptor from actix-server package
|
||||
- Split openssl acceptor from actix-server package
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-tls"
|
||||
version = "3.0.0-rc.1"
|
||||
version = "3.0.4"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
@@ -8,7 +8,7 @@ authors = [
|
||||
description = "TLS acceptor and connector services for Actix ecosystem"
|
||||
keywords = ["network", "tls", "ssl", "async", "transport"]
|
||||
repository = "https://github.com/actix/actix-net.git"
|
||||
categories = ["network-programming", "asynchronous"]
|
||||
categories = ["network-programming", "asynchronous", "cryptography"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
@@ -30,28 +30,28 @@ accept = []
|
||||
connect = []
|
||||
|
||||
# use openssl impls
|
||||
openssl = ["tls-openssl", "tokio-openssl"]
|
||||
openssl = ["tls-openssl", "tokio-openssl", "actix-codec"]
|
||||
|
||||
# use rustls impls
|
||||
rustls = ["tokio-rustls", "webpki-roots"]
|
||||
rustls = ["tokio-rustls", "webpki-roots", "actix-codec"]
|
||||
|
||||
# use native-tls impls
|
||||
native-tls = ["tokio-native-tls"]
|
||||
native-tls = ["tokio-native-tls", "actix-codec"]
|
||||
|
||||
# support http::Uri as connect address
|
||||
uri = ["http"]
|
||||
|
||||
[dependencies]
|
||||
actix-codec = "0.4.0"
|
||||
actix-codec = { version = "0.5.0", optional = true }
|
||||
actix-rt = { version = "2.2.0", default-features = false }
|
||||
actix-service = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-service = "2"
|
||||
actix-utils = "3"
|
||||
|
||||
derive_more = "0.99.5"
|
||||
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||
log = "0.4"
|
||||
impl-more = "0.1"
|
||||
pin-project-lite = "0.2.7"
|
||||
tokio-util = { version = "0.6.3", default-features = false }
|
||||
tokio-util = "0.7"
|
||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||
|
||||
# uri
|
||||
http = { version = "0.2.3", optional = true }
|
||||
@@ -68,8 +68,9 @@ webpki-roots = { version = "0.22", optional = true }
|
||||
tokio-native-tls = { version = "0.3", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-codec = "0.5.0"
|
||||
actix-rt = "2.2.0"
|
||||
actix-server = "2.0.0-rc.1"
|
||||
actix-server = "2"
|
||||
bytes = "1"
|
||||
env_logger = "0.9"
|
||||
futures-util = { version = "0.3.7", default-features = false, features = ["sink"] }
|
||||
@@ -77,7 +78,7 @@ log = "0.4"
|
||||
rcgen = "0.8"
|
||||
rustls-pemfile = "0.2.1"
|
||||
tokio-rustls = { version = "0.23", features = ["dangerous_configuration"] }
|
||||
trust-dns-resolver = "0.20.0"
|
||||
trust-dns-resolver = "0.20"
|
||||
|
||||
[[example]]
|
||||
name = "accept-rustls"
|
||||
|
@@ -15,8 +15,9 @@
|
||||
//! http --verify=false https://127.0.0.1:8443
|
||||
//! ```
|
||||
|
||||
// this use only exists because of how we have organised the crate
|
||||
// it is not necessary for your actual code
|
||||
#[rustfmt::skip]
|
||||
// this `use` is only exists because of how we have organised the crate
|
||||
// it is not necessary for your actual code; you should import from `rustls` directly
|
||||
use tokio_rustls::rustls;
|
||||
|
||||
use std::{
|
||||
@@ -34,9 +35,9 @@ use actix_server::Server;
|
||||
use actix_service::ServiceFactoryExt as _;
|
||||
use actix_tls::accept::rustls::{Acceptor as RustlsAcceptor, TlsStream};
|
||||
use futures_util::future::ok;
|
||||
use log::info;
|
||||
use rustls::{server::ServerConfig, Certificate, PrivateKey};
|
||||
use rustls_pemfile::{certs, rsa_private_keys};
|
||||
use tracing::info;
|
||||
|
||||
#[actix_rt::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
|
@@ -2,11 +2,12 @@
|
||||
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
error::Error,
|
||||
fmt,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
use actix_utils::counter::Counter;
|
||||
use derive_more::{Display, Error};
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "openssl")))]
|
||||
@@ -43,23 +44,45 @@ pub fn max_concurrent_tls_connect(num: usize) {
|
||||
/// TLS handshake error, TLS timeout, or inner service error.
|
||||
///
|
||||
/// All TLS acceptors from this crate will return the `SvcErr` type parameter as [`Infallible`],
|
||||
/// which can be cast to your own service type, inferred or otherwise,
|
||||
/// using [`into_service_error`](Self::into_service_error).
|
||||
#[derive(Debug, Display, Error)]
|
||||
/// which can be cast to your own service type, inferred or otherwise, using [`into_service_error`].
|
||||
///
|
||||
/// [`into_service_error`]: Self::into_service_error
|
||||
#[derive(Debug)]
|
||||
pub enum TlsError<TlsErr, SvcErr> {
|
||||
/// TLS handshake has timed-out.
|
||||
#[display(fmt = "TLS handshake has timed-out")]
|
||||
Timeout,
|
||||
|
||||
/// Wraps TLS service errors.
|
||||
#[display(fmt = "TLS handshake error")]
|
||||
Tls(TlsErr),
|
||||
|
||||
/// Wraps service errors.
|
||||
#[display(fmt = "Service error")]
|
||||
Service(SvcErr),
|
||||
}
|
||||
|
||||
impl<TlsErr, SvcErr> fmt::Display for TlsError<TlsErr, SvcErr> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Timeout => f.write_str("TLS handshake has timed-out"),
|
||||
Self::Tls(_) => f.write_str("TLS handshake error"),
|
||||
Self::Service(_) => f.write_str("Service error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TlsErr, SvcErr> Error for TlsError<TlsErr, SvcErr>
|
||||
where
|
||||
TlsErr: Error + 'static,
|
||||
SvcErr: Error + 'static,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
TlsError::Tls(err) => Some(err),
|
||||
TlsError::Service(err) => Some(err),
|
||||
TlsError::Timeout => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<TlsErr> TlsError<TlsErr, Infallible> {
|
||||
/// Casts the infallible service error type returned from acceptors into caller's type.
|
||||
///
|
||||
|
@@ -20,7 +20,6 @@ use actix_utils::{
|
||||
counter::Counter,
|
||||
future::{ready, Ready as FutReady},
|
||||
};
|
||||
use derive_more::{Deref, DerefMut, From};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use tokio_native_tls::{native_tls::Error, TlsAcceptor};
|
||||
|
||||
@@ -33,9 +32,11 @@ pub mod reexports {
|
||||
}
|
||||
|
||||
/// Wraps a `native-tls` based async TLS stream in order to implement [`ActixStream`].
|
||||
#[derive(Deref, DerefMut, From)]
|
||||
pub struct TlsStream<IO>(tokio_native_tls::TlsStream<IO>);
|
||||
|
||||
impl_more::impl_from!(<IO> in tokio_native_tls::TlsStream<IO> => TlsStream<IO>);
|
||||
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_native_tls::TlsStream<IO>);
|
||||
|
||||
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
|
@@ -21,7 +21,6 @@ use actix_utils::{
|
||||
counter::{Counter, CounterGuard},
|
||||
future::{ready, Ready as FutReady},
|
||||
};
|
||||
use derive_more::{Deref, DerefMut, From};
|
||||
use openssl::ssl::{Error, Ssl, SslAcceptor};
|
||||
use pin_project_lite::pin_project;
|
||||
|
||||
@@ -36,9 +35,11 @@ pub mod reexports {
|
||||
}
|
||||
|
||||
/// Wraps an `openssl` based async TLS stream in order to implement [`ActixStream`].
|
||||
#[derive(Deref, DerefMut, From)]
|
||||
pub struct TlsStream<IO>(tokio_openssl::SslStream<IO>);
|
||||
|
||||
impl_more::impl_from!(<IO> in tokio_openssl::SslStream<IO> => TlsStream<IO>);
|
||||
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_openssl::SslStream<IO>);
|
||||
|
||||
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
|
@@ -22,7 +22,6 @@ use actix_utils::{
|
||||
counter::{Counter, CounterGuard},
|
||||
future::{ready, Ready as FutReady},
|
||||
};
|
||||
use derive_more::{Deref, DerefMut, From};
|
||||
use pin_project_lite::pin_project;
|
||||
use tokio_rustls::rustls::ServerConfig;
|
||||
use tokio_rustls::{Accept, TlsAcceptor};
|
||||
@@ -36,9 +35,11 @@ pub mod reexports {
|
||||
}
|
||||
|
||||
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
|
||||
#[derive(Deref, DerefMut, From)]
|
||||
pub struct TlsStream<IO>(tokio_rustls::server::TlsStream<IO>);
|
||||
|
||||
impl_more::impl_from!(<IO> in tokio_rustls::server::TlsStream<IO> => TlsStream<IO>);
|
||||
impl_more::impl_deref_and_mut!(<IO> in TlsStream<IO> => tokio_rustls::server::TlsStream<IO>);
|
||||
|
||||
impl<IO: ActixStream> AsyncRead for TlsStream<IO> {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
|
@@ -1,20 +1,17 @@
|
||||
use derive_more::{Deref, DerefMut};
|
||||
|
||||
use super::Host;
|
||||
|
||||
/// Wraps underlying I/O and the connection request that initiated it.
|
||||
#[derive(Debug, Deref, DerefMut)]
|
||||
#[derive(Debug)]
|
||||
pub struct Connection<R, IO> {
|
||||
pub(crate) req: R,
|
||||
|
||||
#[deref]
|
||||
#[deref_mut]
|
||||
pub(crate) io: IO,
|
||||
}
|
||||
|
||||
impl_more::impl_deref_and_mut!(<R, IO> in Connection<R, IO> => io: IO);
|
||||
|
||||
impl<R, IO> Connection<R, IO> {
|
||||
/// Construct new `Connection` from request and IO parts.
|
||||
pub(crate) fn new(req: R, io: IO) -> Self {
|
||||
pub fn new(req: R, io: IO) -> Self {
|
||||
Self { req, io }
|
||||
}
|
||||
}
|
||||
|
@@ -1,30 +1,38 @@
|
||||
use std::{error::Error, io};
|
||||
|
||||
use derive_more::Display;
|
||||
use std::{error::Error, fmt, io};
|
||||
|
||||
/// Errors that can result from using a connector service.
|
||||
#[derive(Debug, Display)]
|
||||
#[derive(Debug)]
|
||||
pub enum ConnectError {
|
||||
/// Failed to resolve the hostname
|
||||
#[display(fmt = "Failed resolving hostname")]
|
||||
/// Failed to resolve the hostname.
|
||||
Resolver(Box<dyn std::error::Error>),
|
||||
|
||||
/// No DNS records
|
||||
#[display(fmt = "No DNS records found for the input")]
|
||||
/// No DNS records.
|
||||
NoRecords,
|
||||
|
||||
/// Invalid input
|
||||
/// Invalid input.
|
||||
InvalidInput,
|
||||
|
||||
/// Unresolved host name
|
||||
#[display(fmt = "Connector received `Connect` method with unresolved host")]
|
||||
/// Unresolved host name.
|
||||
Unresolved,
|
||||
|
||||
/// Connection IO error
|
||||
#[display(fmt = "{}", _0)]
|
||||
/// Connection IO error.
|
||||
Io(io::Error),
|
||||
}
|
||||
|
||||
impl fmt::Display for ConnectError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::NoRecords => f.write_str("No DNS records found for the input"),
|
||||
Self::InvalidInput => f.write_str("Invalid input"),
|
||||
Self::Unresolved => {
|
||||
f.write_str("Connector received `Connect` method with unresolved host")
|
||||
}
|
||||
Self::Resolver(_) => f.write_str("Failed to resolve hostname"),
|
||||
Self::Io(_) => f.write_str("I/O error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ConnectError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
|
@@ -8,11 +8,11 @@ use actix_rt::net::ActixStream;
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_utils::future::{ok, Ready};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
use log::trace;
|
||||
use tokio_native_tls::{
|
||||
native_tls::TlsConnector as NativeTlsConnector, TlsConnector as AsyncNativeTlsConnector,
|
||||
TlsStream as AsyncTlsStream,
|
||||
};
|
||||
use tracing::trace;
|
||||
|
||||
use crate::connect::{Connection, Host};
|
||||
|
||||
@@ -20,7 +20,6 @@ pub mod reexports {
|
||||
//! Re-exports from `native-tls` and `tokio-native-tls` that are useful for connectors.
|
||||
|
||||
pub use tokio_native_tls::native_tls::TlsConnector;
|
||||
|
||||
pub use tokio_native_tls::TlsStream as AsyncTlsStream;
|
||||
}
|
||||
|
||||
@@ -75,16 +74,16 @@ where
|
||||
let connector = self.connector.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
trace!("SSL Handshake start for: {:?}", stream.hostname());
|
||||
trace!("TLS handshake start for: {:?}", stream.hostname());
|
||||
connector
|
||||
.connect(stream.hostname(), io)
|
||||
.await
|
||||
.map(|res| {
|
||||
trace!("SSL Handshake success: {:?}", stream.hostname());
|
||||
trace!("TLS handshake success: {:?}", stream.hostname());
|
||||
stream.replace_io(res).1
|
||||
})
|
||||
.map_err(|e| {
|
||||
trace!("SSL Handshake error: {:?}", e);
|
||||
trace!("TLS handshake error: {:?}", e);
|
||||
io::Error::new(io::ErrorKind::Other, format!("{}", e))
|
||||
})
|
||||
})
|
||||
|
@@ -13,17 +13,18 @@ use actix_rt::net::ActixStream;
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_utils::future::{ok, Ready};
|
||||
use futures_core::ready;
|
||||
use log::trace;
|
||||
use openssl::ssl::SslConnector;
|
||||
use tokio_openssl::SslStream as AsyncSslStream;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::connect::{Connection, Host};
|
||||
|
||||
pub mod reexports {
|
||||
//! Re-exports from `openssl` and `tokio-openssl` that are useful for connectors.
|
||||
|
||||
pub use openssl::ssl::{Error, HandshakeError, SslConnector, SslMethod};
|
||||
|
||||
pub use openssl::ssl::{
|
||||
Error, HandshakeError, SslConnector, SslConnectorBuilder, SslMethod,
|
||||
};
|
||||
pub use tokio_openssl::SslStream as AsyncSslStream;
|
||||
}
|
||||
|
||||
@@ -96,7 +97,8 @@ where
|
||||
actix_service::always_ready!();
|
||||
|
||||
fn call(&self, stream: Connection<R, IO>) -> Self::Future {
|
||||
trace!("SSL Handshake start for: {:?}", stream.hostname());
|
||||
trace!("TLS handshake start for: {:?}", stream.hostname());
|
||||
|
||||
let (io, stream) = stream.replace_io(());
|
||||
let host = stream.hostname();
|
||||
|
||||
@@ -136,12 +138,15 @@ where
|
||||
match ready!(Pin::new(this.io.as_mut().unwrap()).poll_connect(cx)) {
|
||||
Ok(_) => {
|
||||
let stream = this.stream.take().unwrap();
|
||||
trace!("SSL Handshake success: {:?}", stream.hostname());
|
||||
trace!("TLS handshake success: {:?}", stream.hostname());
|
||||
Poll::Ready(Ok(stream.replace_io(this.io.take().unwrap()).1))
|
||||
}
|
||||
Err(e) => {
|
||||
trace!("SSL Handshake error: {:?}", e);
|
||||
Poll::Ready(Err(io::Error::new(io::ErrorKind::Other, format!("{}", e))))
|
||||
Err(err) => {
|
||||
trace!("TLS handshake error: {:?}", err);
|
||||
Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{}", err),
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ use actix_rt::task::{spawn_blocking, JoinHandle};
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_utils::future::{ok, Ready};
|
||||
use futures_core::{future::LocalBoxFuture, ready};
|
||||
use log::trace;
|
||||
use tracing::trace;
|
||||
|
||||
use super::{ConnectError, ConnectInfo, Host, Resolve};
|
||||
|
||||
@@ -164,8 +164,8 @@ impl<R: Host> Future for ResolverFut<R> {
|
||||
Self::LookUp(fut, req) => {
|
||||
let res = match ready!(Pin::new(fut).poll(cx)) {
|
||||
Ok(Ok(res)) => Ok(res),
|
||||
Ok(Err(e)) => Err(ConnectError::Resolver(Box::new(e))),
|
||||
Err(e) => Err(ConnectError::Io(e.into())),
|
||||
Ok(Err(err)) => Err(ConnectError::Resolver(Box::new(err))),
|
||||
Err(err) => Err(ConnectError::Io(err.into())),
|
||||
};
|
||||
|
||||
let req = req.take().unwrap();
|
||||
|
@@ -15,10 +15,10 @@ use actix_rt::net::ActixStream;
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_utils::future::{ok, Ready};
|
||||
use futures_core::ready;
|
||||
use log::trace;
|
||||
use tokio_rustls::rustls::{client::ServerName, OwnedTrustAnchor, RootCertStore};
|
||||
use tokio_rustls::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||
use tokio_rustls::{Connect as RustlsConnect, TlsConnector as RustlsTlsConnector};
|
||||
use tracing::trace;
|
||||
use webpki_roots::TLS_SERVER_ROOTS;
|
||||
|
||||
use crate::connect::{Connection, Host};
|
||||
@@ -26,10 +26,8 @@ use crate::connect::{Connection, Host};
|
||||
pub mod reexports {
|
||||
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
|
||||
|
||||
pub use tokio_rustls::rustls::ClientConfig;
|
||||
|
||||
pub use tokio_rustls::client::TlsStream as AsyncTlsStream;
|
||||
|
||||
pub use tokio_rustls::rustls::ClientConfig;
|
||||
pub use webpki_roots::TLS_SERVER_ROOTS;
|
||||
}
|
||||
|
||||
@@ -103,7 +101,7 @@ where
|
||||
actix_service::always_ready!();
|
||||
|
||||
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
||||
trace!("SSL Handshake start for: {:?}", connection.hostname());
|
||||
trace!("TLS handshake start for: {:?}", connection.hostname());
|
||||
let (stream, connection) = connection.replace_io(());
|
||||
|
||||
match ServerName::try_from(connection.hostname()) {
|
||||
@@ -142,7 +140,7 @@ where
|
||||
Self::Future { connect, connection } => {
|
||||
let stream = ready!(Pin::new(connect).poll(cx))?;
|
||||
let connection = connection.take().unwrap();
|
||||
trace!("SSL Handshake success: {:?}", connection.hostname());
|
||||
trace!("TLS handshake success: {:?}", connection.hostname());
|
||||
Poll::Ready(Ok(connection.replace_io(stream).1))
|
||||
}
|
||||
}
|
||||
|
@@ -15,8 +15,8 @@ use actix_rt::net::{TcpSocket, TcpStream};
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_utils::future::{ok, Ready};
|
||||
use futures_core::ready;
|
||||
use log::{error, trace};
|
||||
use tokio_util::sync::ReusableBoxFuture;
|
||||
use tracing::{error, trace};
|
||||
|
||||
use super::{connect_addrs::ConnectAddrs, error::ConnectError, ConnectInfo, Connection, Host};
|
||||
|
||||
@@ -79,7 +79,7 @@ pub enum TcpConnectorFut<R> {
|
||||
port: u16,
|
||||
local_addr: Option<IpAddr>,
|
||||
addrs: Option<VecDeque<SocketAddr>>,
|
||||
stream: ReusableBoxFuture<Result<TcpStream, io::Error>>,
|
||||
stream: ReusableBoxFuture<'static, Result<TcpStream, io::Error>>,
|
||||
},
|
||||
|
||||
Error(Option<ConnectError>),
|
||||
@@ -114,8 +114,8 @@ impl<R: Host> TcpConnectorFut<R> {
|
||||
stream: ReusableBoxFuture::new(connect(addr, local_addr)),
|
||||
},
|
||||
|
||||
// when resolver returns multiple socket addr for request they would be popped from
|
||||
// front end of queue and returns with the first successful tcp connection.
|
||||
// When resolver returns multiple socket addr for request they would be popped from
|
||||
// front end of queue and returns with the first successful TCP connection.
|
||||
ConnectAddrs::Multi(mut addrs) => {
|
||||
let addr = addrs.pop_front().unwrap();
|
||||
|
||||
|
@@ -1,9 +1,10 @@
|
||||
//! TLS acceptor and connector services for the Actix ecosystem.
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
// enable unstable doc_cfg feature only on on docs.rs where nightly compiler is used
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
|
@@ -51,13 +51,13 @@ fn openssl_acceptor(cert: String, key: String) -> tls_openssl::ssl::SslAcceptor
|
||||
mod danger {
|
||||
use std::time::SystemTime;
|
||||
|
||||
use super::*;
|
||||
|
||||
use tokio_rustls::rustls::{
|
||||
self,
|
||||
client::{ServerCertVerified, ServerCertVerifier},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct NoCertificateVerification;
|
||||
|
||||
impl ServerCertVerifier for NoCertificateVerification {
|
||||
@@ -94,7 +94,7 @@ fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
|
||||
async fn accepts_connections() {
|
||||
let (cert, key) = new_cert_and_key();
|
||||
|
||||
let srv = TestServer::with({
|
||||
let srv = TestServer::start({
|
||||
let cert = cert.clone();
|
||||
let key = key.clone();
|
||||
|
||||
|
@@ -74,7 +74,7 @@ fn openssl_connector(cert: String, key: String) -> SslConnector {
|
||||
async fn accepts_connections() {
|
||||
let (cert, key) = new_cert_and_key();
|
||||
|
||||
let srv = TestServer::with({
|
||||
let srv = TestServer::start({
|
||||
let cert = cert.clone();
|
||||
let key = key.clone();
|
||||
|
||||
|
@@ -9,15 +9,14 @@ use actix_codec::{BytesCodec, Framed};
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_server::TestServer;
|
||||
use actix_service::{fn_service, Service, ServiceFactory};
|
||||
use actix_tls::connect::{ConnectError, ConnectInfo, Connection, Connector, Host};
|
||||
use bytes::Bytes;
|
||||
use futures_util::sink::SinkExt;
|
||||
|
||||
use actix_tls::connect::{ConnectError, ConnectInfo, Connection, Connector, Host};
|
||||
|
||||
#[cfg(feature = "openssl")]
|
||||
#[actix_rt::test]
|
||||
async fn test_string() {
|
||||
let srv = TestServer::with(|| {
|
||||
let srv = TestServer::start(|| {
|
||||
fn_service(|io: TcpStream| async {
|
||||
let mut framed = Framed::new(io, BytesCodec);
|
||||
framed.send(Bytes::from_static(b"test")).await?;
|
||||
@@ -34,7 +33,7 @@ async fn test_string() {
|
||||
#[cfg(feature = "rustls")]
|
||||
#[actix_rt::test]
|
||||
async fn test_rustls_string() {
|
||||
let srv = TestServer::with(|| {
|
||||
let srv = TestServer::start(|| {
|
||||
fn_service(|io: TcpStream| async {
|
||||
let mut framed = Framed::new(io, BytesCodec);
|
||||
framed.send(Bytes::from_static(b"test")).await?;
|
||||
@@ -50,7 +49,7 @@ async fn test_rustls_string() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_static_str() {
|
||||
let srv = TestServer::with(|| {
|
||||
let srv = TestServer::start(|| {
|
||||
fn_service(|io: TcpStream| async {
|
||||
let mut framed = Framed::new(io, BytesCodec);
|
||||
framed.send(Bytes::from_static(b"test")).await?;
|
||||
@@ -81,7 +80,7 @@ async fn service_factory() {
|
||||
Connector::default()
|
||||
}
|
||||
|
||||
let srv = TestServer::with(|| {
|
||||
let srv = TestServer::start(|| {
|
||||
fn_service(|io: TcpStream| async {
|
||||
let mut framed = Framed::new(io, BytesCodec);
|
||||
framed.send(Bytes::from_static(b"test")).await?;
|
||||
@@ -101,7 +100,7 @@ async fn service_factory() {
|
||||
async fn test_openssl_uri() {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
let srv = TestServer::with(|| {
|
||||
let srv = TestServer::start(|| {
|
||||
fn_service(|io: TcpStream| async {
|
||||
let mut framed = Framed::new(io, BytesCodec);
|
||||
framed.send(Bytes::from_static(b"test")).await?;
|
||||
@@ -120,7 +119,7 @@ async fn test_openssl_uri() {
|
||||
async fn test_rustls_uri() {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
let srv = TestServer::with(|| {
|
||||
let srv = TestServer::start(|| {
|
||||
fn_service(|io: TcpStream| async {
|
||||
let mut framed = Framed::new(io, BytesCodec);
|
||||
framed.send(Bytes::from_static(b"test")).await?;
|
||||
@@ -136,7 +135,7 @@ async fn test_rustls_uri() {
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_local_addr() {
|
||||
let srv = TestServer::with(|| {
|
||||
let srv = TestServer::start(|| {
|
||||
fn_service(|io: TcpStream| async {
|
||||
let mut framed = Framed::new(io, BytesCodec);
|
||||
framed.send(Bytes::from_static(b"test")).await?;
|
||||
@@ -144,6 +143,9 @@ async fn test_local_addr() {
|
||||
})
|
||||
});
|
||||
|
||||
// if you've arrived here because of a failing test on macOS run this in your terminal:
|
||||
// sudo ifconfig lo0 alias 127.0.0.3
|
||||
|
||||
let conn = Connector::default().service();
|
||||
let local = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 3));
|
||||
|
||||
|
@@ -8,11 +8,10 @@ use std::{
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_server::TestServer;
|
||||
use actix_service::{fn_service, Service, ServiceFactory};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
|
||||
use actix_tls::connect::{
|
||||
ConnectError, ConnectInfo, Connection, Connector, Host, Resolve, Resolver,
|
||||
};
|
||||
use futures_core::future::LocalBoxFuture;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn custom_resolver() {
|
||||
@@ -53,7 +52,7 @@ async fn custom_resolver_connect() {
|
||||
use trust_dns_resolver::TokioAsyncResolver;
|
||||
|
||||
let srv =
|
||||
TestServer::with(|| fn_service(|_io: TcpStream| async { Ok::<_, io::Error>(()) }));
|
||||
TestServer::start(|| fn_service(|_io: TcpStream| async { Ok::<_, io::Error>(()) }));
|
||||
|
||||
struct MyResolver {
|
||||
trust_dns: TokioAsyncResolver,
|
||||
|
@@ -1,5 +1,8 @@
|
||||
# Changes
|
||||
|
||||
## [0.1.0] - 2020-01-15
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
* Initial release
|
||||
|
||||
## 0.1.0 - 2020-01-15
|
||||
- Initial release
|
||||
|
@@ -16,12 +16,12 @@ name = "actix_tracing"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-service = "2.0.0"
|
||||
actix-utils = "3.0.0"
|
||||
actix-service = "2"
|
||||
actix-utils = "3"
|
||||
|
||||
tracing = "0.1"
|
||||
tracing = "0.1.35"
|
||||
tracing-futures = "0.2"
|
||||
|
||||
[dev_dependencies]
|
||||
actix-rt = "2.0.0"
|
||||
actix-rt = "2"
|
||||
slab = "0.4"
|
||||
|
@@ -1,6 +1,7 @@
|
||||
//! Actix tracing - support for tokio tracing with Actix services.
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(future_incompatible)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
|
||||
@@ -117,8 +118,6 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::sync::{Arc, RwLock};
|
||||
@@ -127,6 +126,8 @@ mod test {
|
||||
use slab::Slab;
|
||||
use tracing::{span, Event, Level, Metadata, Subscriber};
|
||||
|
||||
use super::*;
|
||||
|
||||
thread_local! {
|
||||
static SPAN: RefCell<Vec<span::Id>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
@@ -1,182 +1,186 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
|
||||
|
||||
## 3.0.1 - 2022-10-21
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 3.0.0 - 2021-04-16
|
||||
* No significant changes from `3.0.0-beta.4`.
|
||||
- No significant changes from `3.0.0-beta.4`.
|
||||
|
||||
|
||||
## 3.0.0-beta.4 - 2021-04-01
|
||||
* Add `future::Either` type. [#305]
|
||||
- Add `future::Either` type. [#305]
|
||||
|
||||
[#305]: https://github.com/actix/actix-net/pull/305
|
||||
|
||||
|
||||
## 3.0.0-beta.3 - 2021-04-01
|
||||
* Moved `mpsc` to own crate `local-channel`. [#301]
|
||||
* Moved `task::LocalWaker` to own crate `local-waker`. [#301]
|
||||
* Remove `timeout` module. [#301]
|
||||
* Remove `dispatcher` module. [#301]
|
||||
* Expose `future` mod with `ready` and `poll_fn` helpers. [#301]
|
||||
- Moved `mpsc` to own crate `local-channel`. [#301]
|
||||
- Moved `task::LocalWaker` to own crate `local-waker`. [#301]
|
||||
- Remove `timeout` module. [#301]
|
||||
- Remove `dispatcher` module. [#301]
|
||||
- Expose `future` mod with `ready` and `poll_fn` helpers. [#301]
|
||||
|
||||
[#301]: https://github.com/actix/actix-net/pull/301
|
||||
|
||||
|
||||
## 3.0.0-beta.2 - 2021-02-06
|
||||
* Update `actix-rt` to `2.0.0`. [#273]
|
||||
- Update `actix-rt` to `2.0.0`. [#273]
|
||||
|
||||
[#273]: https://github.com/actix/actix-net/pull/273
|
||||
|
||||
|
||||
## 3.0.0-beta.1 - 2020-12-28
|
||||
* Update `bytes` dependency to `1`. [#237]
|
||||
* Use `pin-project-lite` to replace `pin-project`. [#229]
|
||||
* Remove `condition`,`either`,`inflight`,`keepalive`,`oneshot`,`order`,`stream` and `time` mods. [#229]
|
||||
- Update `bytes` dependency to `1`. [#237]
|
||||
- Use `pin-project-lite` to replace `pin-project`. [#229]
|
||||
- Remove `condition`,`either`,`inflight`,`keepalive`,`oneshot`,`order`,`stream` and `time` mods. [#229]
|
||||
|
||||
[#229]: https://github.com/actix/actix-net/pull/229
|
||||
[#237]: https://github.com/actix/actix-net/pull/237
|
||||
|
||||
|
||||
## 2.0.0 - 2020-08-23
|
||||
* No changes from beta 1.
|
||||
- No changes from beta 1.
|
||||
|
||||
|
||||
## 2.0.0-beta.1 - 2020-08-19
|
||||
* Upgrade `tokio-util` to `0.3`.
|
||||
* Remove unsound custom Cell and use `std::cell::RefCell` instead, as well as `actix-service`.
|
||||
* Rename method to correctly spelled `LocalWaker::is_registered`.
|
||||
- Upgrade `tokio-util` to `0.3`.
|
||||
- Remove unsound custom Cell and use `std::cell::RefCell` instead, as well as `actix-service`.
|
||||
- Rename method to correctly spelled `LocalWaker::is_registered`.
|
||||
|
||||
|
||||
## 1.0.6 - 2020-01-08
|
||||
* Add `Clone` impl for `condition::Waiter`.
|
||||
- Add `Clone` impl for `condition::Waiter`.
|
||||
|
||||
|
||||
## 1.0.5 - 2020-01-08
|
||||
* Add `Condition` type.
|
||||
* Add `Pool` of one-shot's.
|
||||
- Add `Condition` type.
|
||||
- Add `Pool` of one-shot's.
|
||||
|
||||
|
||||
## 1.0.4 - 2019-12-20
|
||||
* Add methods to check `LocalWaker` registration state.
|
||||
- Add methods to check `LocalWaker` registration state.
|
||||
|
||||
|
||||
## 1.0.3 - 2019-12-11
|
||||
* Revert InOrder service changes
|
||||
- Revert InOrder service changes
|
||||
|
||||
|
||||
## 1.0.2 - 2019-12-11
|
||||
* Allow to create `framed::Dispatcher` with custom `mpsc::Receiver`.
|
||||
* Add `oneshot::Sender::is_canceled()` method.
|
||||
- Allow to create `framed::Dispatcher` with custom `mpsc::Receiver`.
|
||||
- Add `oneshot::Sender::is_canceled()` method.
|
||||
|
||||
|
||||
## 1.0.1 - 2019-12-11
|
||||
* Optimize InOrder service.
|
||||
- Optimize InOrder service.
|
||||
|
||||
|
||||
## 1.0.0 - 2019-12-11
|
||||
* Simplify oneshot and mpsc implementations.
|
||||
- Simplify oneshot and mpsc implementations.
|
||||
|
||||
|
||||
## 1.0.0-alpha.3 - 2019-12-07
|
||||
* Migrate to tokio 0.2.
|
||||
* Fix oneshot.
|
||||
- Migrate to tokio 0.2.
|
||||
- Fix oneshot.
|
||||
|
||||
|
||||
## 1.0.0-alpha.2 - 2019-12-02
|
||||
* Migrate to `std::future`.
|
||||
- Migrate to `std::future`.
|
||||
|
||||
|
||||
## 0.4.7 - 2019-10-14
|
||||
* Re-register task on every framed transport poll.
|
||||
- Re-register task on every framed transport poll.
|
||||
|
||||
|
||||
## 0.4.6 - 2019-10-08
|
||||
* Refactor `Counter` type. register current task in available method.
|
||||
- Refactor `Counter` type. register current task in available method.
|
||||
|
||||
|
||||
## 0.4.5 - 2019-07-19
|
||||
* Deprecated `CloneableService` as it is not safe.
|
||||
- Deprecated `CloneableService` as it is not safe.
|
||||
|
||||
|
||||
## 0.4.4 - 2019-07-17
|
||||
* Undeprecate `FramedTransport` as it is actually useful.
|
||||
- Undeprecate `FramedTransport` as it is actually useful.
|
||||
|
||||
|
||||
## 0.4.3 - 2019-07-17
|
||||
* Deprecate `CloneableService` as it is not safe and in general not very useful.
|
||||
* Deprecate `FramedTransport` in favor of `actix-ioframe`.
|
||||
- Deprecate `CloneableService` as it is not safe and in general not very useful.
|
||||
- Deprecate `FramedTransport` in favor of `actix-ioframe`.
|
||||
|
||||
|
||||
## 0.4.2 - 2019-06-26
|
||||
* Do not block on sink drop for FramedTransport.
|
||||
- Do not block on sink drop for FramedTransport.
|
||||
|
||||
|
||||
## 0.4.1 - 2019-05-15
|
||||
* Change `Either` constructor.
|
||||
- Change `Either` constructor.
|
||||
|
||||
|
||||
## 0.4.0 - 2019-05-11
|
||||
* Change `Either` to handle two nexted services.
|
||||
* Upgrade actix-service 0.4.
|
||||
* Removed framed related services.
|
||||
* Removed stream related services.
|
||||
- Change `Either` to handle two nexted services.
|
||||
- Upgrade actix-service 0.4.
|
||||
- Removed framed related services.
|
||||
- Removed stream related services.
|
||||
|
||||
|
||||
## 0.3.5 - 2019-04-04
|
||||
* Allow to send messages to `FramedTransport` via mpsc channel.
|
||||
* Remove `'static` constraint from Clonable service.
|
||||
- Allow to send messages to `FramedTransport` via mpsc channel.
|
||||
- Remove `'static` constraint from Clonable service.
|
||||
|
||||
|
||||
## 0.3.4 - 2019-03-12
|
||||
* `TimeoutService`, `InOrderService`, `InFlightService` accepts generic IntoService services.
|
||||
* Fix `InFlightService::poll_ready()` nested service readiness check.
|
||||
* Fix `InOrderService::poll_ready()` nested service readiness check.
|
||||
- `TimeoutService`, `InOrderService`, `InFlightService` accepts generic IntoService services.
|
||||
- Fix `InFlightService::poll_ready()` nested service readiness check.
|
||||
- Fix `InOrderService::poll_ready()` nested service readiness check.
|
||||
|
||||
|
||||
## 0.3.3 - 2019-03-09
|
||||
* Revert IntoFuture change.
|
||||
* Add generic config param for IntoFramed and TakeOne new services.
|
||||
- Revert IntoFuture change.
|
||||
- Add generic config param for IntoFramed and TakeOne new services.
|
||||
|
||||
|
||||
## 0.3.2 - 2019-03-04
|
||||
* Use IntoFuture for new services.
|
||||
- Use IntoFuture for new services.
|
||||
|
||||
## 0.3.1 - 2019-03-04
|
||||
* Use new type of transform trait.
|
||||
- Use new type of transform trait.
|
||||
|
||||
|
||||
## 0.3.0 - 2019-03-02
|
||||
* Use new `NewService` trait
|
||||
* BoxedNewService` and `BoxedService` types moved to actix-service crate.
|
||||
- Use new `NewService` trait
|
||||
- BoxedNewService` and `BoxedService` types moved to actix-service crate.
|
||||
|
||||
|
||||
## 0.2.4 - 2019-02-21
|
||||
* Custom `BoxedNewService` implementation.
|
||||
- Custom `BoxedNewService` implementation.
|
||||
|
||||
|
||||
## 0.2.3 - 2019-02-21
|
||||
* Add `BoxedNewService` and `BoxedService`.
|
||||
- Add `BoxedNewService` and `BoxedService`.
|
||||
|
||||
|
||||
## 0.2.2 - 2019-02-11
|
||||
* Add `Display` impl for `TimeoutError`.
|
||||
* Add `Display` impl for `InOrderError`.
|
||||
- Add `Display` impl for `TimeoutError`.
|
||||
- Add `Display` impl for `InOrderError`.
|
||||
|
||||
|
||||
## 0.2.1 - 2019-02-06
|
||||
* Add `InOrder` service. the service yields responses as they become available,
|
||||
- Add `InOrder` service. the service yields responses as they become available,
|
||||
in the order that their originating requests were submitted to the service.
|
||||
* Convert `Timeout` and `InFlight` services to a transforms.
|
||||
- Convert `Timeout` and `InFlight` services to a transforms.
|
||||
|
||||
|
||||
## 0.2.0 - 2019-02-01
|
||||
* Fix framed transport error handling.
|
||||
* Added Clone impl for Either service.
|
||||
* Added Clone impl for Timeout service factory.
|
||||
* Added Service and NewService for Stream dispatcher.
|
||||
* Switch to actix-service 0.2.
|
||||
- Fix framed transport error handling.
|
||||
- Added Clone impl for Either service.
|
||||
- Added Clone impl for Timeout service factory.
|
||||
- Added Service and NewService for Stream dispatcher.
|
||||
- Switch to actix-service 0.2.
|
||||
|
||||
|
||||
## 0.1.0 - 2018-12-09
|
||||
* Move utils services to separate crate.
|
||||
- Move utils services to separate crate.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "actix-utils"
|
||||
version = "3.0.0"
|
||||
version = "3.0.1"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
|
@@ -22,16 +22,19 @@ impl Counter {
|
||||
}
|
||||
|
||||
/// Create new counter guard, incrementing the counter.
|
||||
#[inline]
|
||||
pub fn get(&self) -> CounterGuard {
|
||||
CounterGuard::new(self.0.clone())
|
||||
}
|
||||
|
||||
/// Returns true if counter is below capacity. Otherwise, register to wake task when it is.
|
||||
#[inline]
|
||||
pub fn available(&self, cx: &mut task::Context<'_>) -> bool {
|
||||
self.0.available(cx)
|
||||
}
|
||||
|
||||
/// Get total number of acquired guards.
|
||||
#[inline]
|
||||
pub fn total(&self) -> usize {
|
||||
self.0.count.get()
|
||||
}
|
||||
|
@@ -40,11 +40,13 @@ pin_project! {
|
||||
|
||||
impl<L, R> Either<L, R> {
|
||||
/// Creates new `Either` using left variant.
|
||||
#[inline]
|
||||
pub fn left(value: L) -> Either<L, R> {
|
||||
Either::Left { value }
|
||||
}
|
||||
|
||||
/// Creates new `Either` using right variant.
|
||||
#[inline]
|
||||
pub fn right(value: R) -> Either<L, R> {
|
||||
Either::Right { value }
|
||||
}
|
||||
@@ -52,6 +54,7 @@ impl<L, R> Either<L, R> {
|
||||
|
||||
impl<T> Either<T, T> {
|
||||
/// Unwraps into inner value when left and right have a common type.
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> T {
|
||||
match self {
|
||||
Either::Left { value } => value,
|
||||
@@ -67,6 +70,7 @@ where
|
||||
{
|
||||
type Output = L::Output;
|
||||
|
||||
#[inline]
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.project() {
|
||||
EitherProj::Left { value } => value.poll(cx),
|
||||
|
@@ -1,4 +1,4 @@
|
||||
//! Asynchronous values.
|
||||
//! Helpers for constructing futures.
|
||||
|
||||
mod either;
|
||||
mod poll_fn;
|
||||
|
@@ -8,6 +8,32 @@ use core::{
|
||||
};
|
||||
|
||||
/// Creates a future driven by the provided function that receives a task context.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use std::task::Poll;
|
||||
/// # use actix_utils::future::poll_fn;
|
||||
/// # async fn test_poll_fn() {
|
||||
/// let res = poll_fn(|_| Poll::Ready(42)).await;
|
||||
/// assert_eq!(res, 42);
|
||||
///
|
||||
/// let mut i = 5;
|
||||
/// let res = poll_fn(|cx| {
|
||||
/// i -= 1;
|
||||
///
|
||||
/// if i > 0 {
|
||||
/// cx.waker().wake_by_ref();
|
||||
/// Poll::Pending
|
||||
/// } else {
|
||||
/// Poll::Ready(42)
|
||||
/// }
|
||||
/// })
|
||||
/// .await;
|
||||
/// assert_eq!(res, 42);
|
||||
/// # }
|
||||
/// # actix_rt::Runtime::new().unwrap().block_on(test_poll_fn());
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn poll_fn<F, T>(f: F) -> PollFn<F>
|
||||
where
|
||||
F: FnMut(&mut Context<'_>) -> Poll<T>,
|
||||
@@ -15,13 +41,11 @@ where
|
||||
PollFn { f }
|
||||
}
|
||||
|
||||
/// A Future driven by the inner function.
|
||||
/// Future for the [`poll_fn`] function.
|
||||
pub struct PollFn<F> {
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<F> Unpin for PollFn<F> {}
|
||||
|
||||
impl<F> fmt::Debug for PollFn<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PollFn").finish()
|
||||
@@ -34,15 +58,23 @@ where
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
(self.f)(cx)
|
||||
#[inline]
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// SAFETY: we are not moving out of the pinned field
|
||||
// see https://github.com/rust-lang/rust/pull/102737
|
||||
(unsafe { &mut self.get_unchecked_mut().f })(cx)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::marker::PhantomPinned;
|
||||
|
||||
use super::*;
|
||||
|
||||
static_assertions::assert_impl_all!(PollFn<()>: Unpin);
|
||||
static_assertions::assert_not_impl_all!(PollFn<PhantomPinned>: Unpin);
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_poll_fn() {
|
||||
let res = poll_fn(|_| Poll::Ready(42)).await;
|
||||
@@ -62,4 +94,29 @@ mod tests {
|
||||
.await;
|
||||
assert_eq!(res, 42);
|
||||
}
|
||||
|
||||
// following soundness tests taken from https://github.com/tokio-rs/tokio/pull/5087
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn require_send<T: Send>(_t: &T) {}
|
||||
#[allow(dead_code)]
|
||||
fn require_sync<T: Sync>(_t: &T) {}
|
||||
|
||||
trait AmbiguousIfUnpin<A> {
|
||||
fn some_item(&self) {}
|
||||
}
|
||||
impl<T: ?Sized> AmbiguousIfUnpin<()> for T {}
|
||||
impl<T: ?Sized + Unpin> AmbiguousIfUnpin<[u8; 0]> for T {}
|
||||
|
||||
const _: fn() = || {
|
||||
let pinned = std::marker::PhantomPinned;
|
||||
let f = poll_fn(move |_| {
|
||||
// Use `pinned` to take ownership of it.
|
||||
let _ = &pinned;
|
||||
std::task::Poll::Pending::<()>
|
||||
});
|
||||
require_send(&f);
|
||||
require_sync(&f);
|
||||
AmbiguousIfUnpin::some_item(&f);
|
||||
};
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
//! When MSRV is 1.48, replace with `core::future::Ready` and `core::future::ready()`.
|
||||
//! When `core::future::Ready` has a `into_inner()` method, this can be deprecated.
|
||||
|
||||
use core::{
|
||||
future::Future,
|
||||
@@ -6,7 +6,7 @@ use core::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
/// Future for the [`ready`](ready()) function.
|
||||
/// Future for the [`ready`] function.
|
||||
///
|
||||
/// Panic will occur if polled more than once.
|
||||
///
|
||||
@@ -65,6 +65,7 @@ impl<T> Future for Ready<T> {
|
||||
/// let a = ready(1);
|
||||
/// assert_eq!(a.into_inner(), 1);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn ready<T>(val: T) -> Ready<T> {
|
||||
Ready { val: Some(val) }
|
||||
}
|
||||
@@ -80,6 +81,7 @@ pub fn ready<T>(val: T) -> Ready<T> {
|
||||
/// assert_eq!(a.await, Ok(1));
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn ok<T, E>(val: T) -> Ready<Result<T, E>> {
|
||||
Ready { val: Some(Ok(val)) }
|
||||
}
|
||||
@@ -95,6 +97,7 @@ pub fn ok<T, E>(val: T) -> Ready<Result<T, E>> {
|
||||
/// assert_eq!(a.await, Err(1));
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn err<T, E>(err: E) -> Ready<Result<T, E>> {
|
||||
Ready {
|
||||
val: Some(Err(err)),
|
||||
@@ -106,12 +109,13 @@ mod tests {
|
||||
use std::rc::Rc;
|
||||
|
||||
use futures_util::task::noop_waker;
|
||||
use static_assertions::{assert_impl_all, assert_not_impl_all};
|
||||
use static_assertions::{assert_impl_all, assert_not_impl_any};
|
||||
|
||||
use super::*;
|
||||
|
||||
assert_impl_all!(Ready<()>: Send, Sync, Clone);
|
||||
assert_not_impl_all!(Ready<Rc<()>>: Send, Sync);
|
||||
assert_impl_all!(Ready<()>: Send, Sync, Unpin, Clone);
|
||||
assert_impl_all!(Ready<Rc<()>>: Unpin, Clone);
|
||||
assert_not_impl_any!(Ready<Rc<()>>: Send, Sync);
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//! Various utilities used in the Actix ecosystem.
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||
|
||||
|
@@ -1,36 +1,45 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 1.1.0 - 2022-06-11
|
||||
- Implement `From<Box<str>>` for `ByteString`. [#458]
|
||||
- Implement `Into<String>` for `ByteString`. [#458]
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
[#458]: https://github.com/actix/actix-net/pull/458
|
||||
|
||||
|
||||
## 1.0.0 - 2020-12-31
|
||||
* Update `bytes` dependency to `1`.
|
||||
* Add array and slice of `u8` impls of `TryFrom` up to 32 in length.
|
||||
* Rename `get_ref` to `as_bytes` and rename `into_inner` to `into_bytes`.
|
||||
* `ByteString::new` is now a `const fn`.
|
||||
* Crate is now `#[no_std]` compatible.
|
||||
- Update `bytes` dependency to `1`.
|
||||
- Add array and slice of `u8` impls of `TryFrom` up to 32 in length.
|
||||
- Rename `get_ref` to `as_bytes` and rename `into_inner` to `into_bytes`.
|
||||
- `ByteString::new` is now a `const fn`.
|
||||
- Crate is now `#[no_std]` compatible.
|
||||
|
||||
|
||||
## 0.1.5 - 2020-03-30
|
||||
* Serde support
|
||||
- Serde support
|
||||
|
||||
|
||||
## 0.1.4 - 2020-01-14
|
||||
* Fix `AsRef<str>` impl
|
||||
- Fix `AsRef<str>` impl
|
||||
|
||||
|
||||
## 0.1.3 - 2020-01-13
|
||||
* Add `PartialEq<T: AsRef<str>>`, `AsRef<[u8]>` impls
|
||||
- Add `PartialEq<T: AsRef<str>>`, `AsRef<[u8]>` impls
|
||||
|
||||
|
||||
## 0.1.2 - 2019-12-22
|
||||
* Fix `new()` method
|
||||
* Make `ByteString::from_static()` and `ByteString::from_bytes_unchecked()` methods const.
|
||||
- Fix `new()` method
|
||||
- Make `ByteString::from_static()` and `ByteString::from_bytes_unchecked()` methods const.
|
||||
|
||||
|
||||
## 0.1.1 - 2019-12-07
|
||||
* Fix hash impl
|
||||
- Fix hash impl
|
||||
|
||||
|
||||
## 0.1.0 - 2019-12-07
|
||||
* Initial release
|
||||
- Initial release
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bytestring"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
"Rob Ede <robjtede@icloud.com>",
|
||||
@@ -18,7 +18,7 @@ name = "bytestring"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
bytes = "1"
|
||||
bytes = "1.2"
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -2,11 +2,15 @@
|
||||
|
||||
#![no_std]
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use core::{borrow, convert::TryFrom, fmt, hash, ops, str};
|
||||
|
||||
use bytes::Bytes;
|
||||
@@ -68,7 +72,7 @@ impl AsRef<[u8]> for ByteString {
|
||||
|
||||
impl AsRef<str> for ByteString {
|
||||
fn as_ref(&self) -> &str {
|
||||
&*self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +96,7 @@ impl ops::Deref for ByteString {
|
||||
|
||||
impl borrow::Borrow<str> for ByteString {
|
||||
fn borrow(&self) -> &str {
|
||||
&*self
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +114,20 @@ impl From<&str> for ByteString {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<str>> for ByteString {
|
||||
#[inline]
|
||||
fn from(value: Box<str>) -> Self {
|
||||
Self(Bytes::from(value.into_boxed_bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ByteString> for String {
|
||||
#[inline]
|
||||
fn from(value: ByteString) -> Self {
|
||||
value.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for ByteString {
|
||||
type Error = str::Utf8Error;
|
||||
|
||||
@@ -219,11 +237,11 @@ mod serde {
|
||||
|
||||
#[cfg(test)]
|
||||
mod serde_impl_tests {
|
||||
use super::*;
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use static_assertions::assert_impl_all;
|
||||
|
||||
use super::*;
|
||||
|
||||
assert_impl_all!(ByteString: Serialize, DeserializeOwned);
|
||||
}
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
msrv = "1.48"
|
||||
msrv = "1.57"
|
||||
|
@@ -1,7 +1,16 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.1.3 - 2022-05-03
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
|
||||
## 0.1.2 - 2021-04-01
|
||||
- No significant changes from `0.1.1`.
|
||||
|
||||
|
||||
## 0.1.1 - 2021-03-29
|
||||
* Move local mpsc channel to it's own crate.
|
||||
- Move local mpsc channel to it's own crate.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "local-channel"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
description = "A non-threadsafe multi-producer, single-consumer, futures-aware, FIFO queue"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
@@ -18,4 +18,4 @@ futures-util = { version = "0.3.7", default-features = false }
|
||||
local-waker = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.5.1", features = ["rt", "macros"] }
|
||||
tokio = { version = "1.13.1", features = ["rt", "macros"] }
|
||||
|
1
local-channel/LICENSE-APACHE
Symbolic link
1
local-channel/LICENSE-APACHE
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-APACHE
|
1
local-channel/LICENSE-MIT
Symbolic link
1
local-channel/LICENSE-MIT
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-MIT
|
@@ -1,7 +1,7 @@
|
||||
//! Non-thread-safe channels.
|
||||
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
|
@@ -1,11 +1,16 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2021-xx-xx
|
||||
## Unreleased - 2022-xx-xx
|
||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||
|
||||
|
||||
## 0.1.2 - 2021-04-01
|
||||
* Fix crate metadata.
|
||||
## 0.1.3 - 2022-05-03
|
||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||
|
||||
|
||||
## 0.1.2 - 2021-12-18
|
||||
- Fix crate metadata.
|
||||
|
||||
|
||||
## 0.1.1 - 2021-03-29
|
||||
* Move `LocalWaker` to it's own crate.
|
||||
- Move `LocalWaker` to it's own crate.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "local-waker"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
description = "A synchronization primitive for thread-local task wakeup"
|
||||
authors = [
|
||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||
|
1
local-waker/LICENSE-APACHE
Symbolic link
1
local-waker/LICENSE-APACHE
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-APACHE
|
1
local-waker/LICENSE-MIT
Symbolic link
1
local-waker/LICENSE-MIT
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE-MIT
|
@@ -4,7 +4,7 @@
|
||||
|
||||
#![no_std]
|
||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(future_incompatible, missing_docs)]
|
||||
|
||||
use core::{cell::Cell, fmt, marker::PhantomData, task::Waker};
|
||||
|
||||
|
@@ -1,5 +1,2 @@
|
||||
max_width = 96
|
||||
reorder_imports = true
|
||||
#wrap_comments = true
|
||||
#fn_args_density = "Compressed"
|
||||
#use_small_heuristics = false
|
||||
group_imports = "StdExternalCrate"
|
||||
|
Reference in New Issue
Block a user