mirror of https://github.com/fafhrd91/actix-net
Compare commits
192 Commits
Author | SHA1 | Date |
---|---|---|
|
b57ab7e8f0 | |
|
887975ab11 | |
|
9069fd8590 | |
|
8204690568 | |
|
bbb3139c45 | |
|
0915904bdb | |
|
70f0008f42 | |
|
12df4d7027 | |
|
6f5b81d2a0 | |
|
4cf37171b5 | |
|
00f40e1471 | |
|
15f0b63492 | |
|
9d4b1673aa | |
|
fc902b2d56 | |
|
f4175a4ad4 | |
|
323a2e2931 | |
|
4b9f7ae46d | |
|
0e119fd9b2 | |
|
b04b88e81a | |
|
0a8f2baa11 | |
|
d79d500ffe | |
|
7a7e3de430 | |
|
f062ede06f | |
|
1338276934 | |
|
4746b4e2fa | |
|
0509f0cede | |
|
3831e0d7fe | |
|
60945d0481 | |
|
2615a19e28 | |
|
1a0f44fff1 | |
|
8d1cd2ec87 | |
|
b87174b5f2 | |
|
8097af6a27 | |
|
ecba6e21da | |
|
23f797a81d | |
|
d2a5091451 | |
|
e0c09c2aa4 | |
|
8234543066 | |
|
34826c6253 | |
|
42b788d131 | |
|
9796593b24 | |
|
c362fc4414 | |
|
52733337e4 | |
|
0e36c5f5c4 | |
|
47f0017899 | |
|
bb4fc31461 | |
|
01a104eb82 | |
|
4ab27bfc4a | |
|
8084cec705 | |
|
a2517da225 | |
|
a4b6943ddc | |
|
7d24196d5c | |
|
582edf5444 | |
|
57485f1a21 | |
|
e8871d0d06 | |
|
83e896a6e5 | |
|
af00dada5c | |
|
0681b515de | |
|
3672137d17 | |
|
fad1fda194 | |
|
cfae737314 | |
|
4583daa3c2 | |
|
b1cbacc7f6 | |
|
77588aba81 | |
|
aad3a48edd | |
|
97e8c571cf | |
|
0d8c7e5085 | |
|
baf1b6042a | |
|
779fa28bd5 | |
|
e282811d69 | |
|
5c44115978 | |
|
ead0e2b200 | |
|
ace737fc4c | |
|
c45ae294fb | |
|
939377f6ab | |
|
20149f957b | |
|
544e5d3b40 | |
|
d482af529c | |
|
0030800b9a | |
|
64fa2f8462 | |
|
b0d1c8d193 | |
|
46cc62c6d8 | |
|
912daa3d0a | |
|
aefa810496 | |
|
2c443a7620 | |
|
b3b1583115 | |
|
0d3d1926bc | |
|
0c26ecf9fa | |
|
1bdb15ec20 | |
|
a524f15e34 | |
|
451a44c2e0 | |
|
18071d1fc0 | |
|
786014cc2f | |
|
a7ef438f25 | |
|
375c352810 | |
|
2d1b5468d0 | |
|
3696cda155 | |
|
55e89d1f30 | |
|
24be36b18d | |
|
38ae762569 | |
|
8cf79d3d13 | |
|
73451070db | |
|
2632c984cc | |
|
af8e6cd656 | |
|
db7988609e | |
|
1db640f62e | |
|
9e7d612121 | |
|
5edbf9e3dc | |
|
f028a74240 | |
|
f4139a0878 | |
|
3147dbe7ca | |
|
95ca8f0318 | |
|
f947374a73 | |
|
85191934c8 | |
|
234a4c9c7f | |
|
d5171c2ab3 | |
|
875218488c | |
|
b826bf8471 | |
|
10bd847177 | |
|
481cf55414 | |
|
b4990023c4 | |
|
eb5cec0064 | |
|
db925bf8e6 | |
|
850f6c0491 | |
|
0f71fd5a7a | |
|
40b10847df | |
|
39bab04800 | |
|
3cb247874e | |
|
5792d9f010 | |
|
bd8bd1020b | |
|
21be7d84bd | |
|
57fd6ea809 | |
|
9a3f3eef6a | |
|
e427911cdb | |
|
a1ae524512 | |
|
88833355e4 | |
|
7737ba5cfb | |
|
fd32a0a97a | |
|
07e7f82345 | |
|
1a5d85ec8b | |
|
bd1467e928 | |
|
968ad3b854 | |
|
079f0f66f0 | |
|
d85903b31a | |
|
a0675fb0dd | |
|
af9ccd17d9 | |
|
eb977e9aeb | |
|
d28c7db3b3 | |
|
c5b2d0cd36 | |
|
02ac0bb4f7 | |
|
86b000fe71 | |
|
951e46186b | |
|
9edc0b393a | |
|
1945fa0675 | |
|
923a443950 | |
|
b526197a9a | |
|
8fc2253c61 | |
|
4c12b81492 | |
|
ef716a8488 | |
|
2a4df30c63 | |
|
2d9b147cc3 | |
|
5515a37002 | |
|
4067fbe8f0 | |
|
01f9910e7c | |
|
df12c10a3f | |
|
f632ef2ba8 | |
|
19d03f0454 | |
|
e9c2a0c318 | |
|
f967562ac4 | |
|
61b6e01b02 | |
|
392e591820 | |
|
87440e5734 | |
|
665dec456f | |
|
7d138f0c31 | |
|
3cd5d8b07a | |
|
09548c96b0 | |
|
17fd135349 | |
|
b9b628c47b | |
|
580af3dec4 | |
|
db54639f0f | |
|
6d9eb7e162 | |
|
69e50b5e66 | |
|
17409cd203 | |
|
4a7f2c95af | |
|
c69b8e9ade | |
|
9f59093adc | |
|
bfeb4cd9e7 | |
|
14272a1762 | |
|
7e043048a0 | |
|
45a7dcba90 | |
|
5029beb866 | |
|
910c181251 |
|
@ -2,24 +2,14 @@
|
||||||
lint = "clippy --workspace --tests --examples --bins -- -Dclippy::todo"
|
lint = "clippy --workspace --tests --examples --bins -- -Dclippy::todo"
|
||||||
lint-all = "clippy --workspace --all-features --tests --examples --bins -- -Dclippy::todo"
|
lint-all = "clippy --workspace --all-features --tests --examples --bins -- -Dclippy::todo"
|
||||||
|
|
||||||
ci-doctest = "test --workspace --all-features --doc --no-fail-fast -- --nocapture"
|
|
||||||
|
|
||||||
# just check the library (without dev deps)
|
# just check the library (without dev deps)
|
||||||
ci-check-min = "hack --workspace check --no-default-features"
|
ci-check-min = "hack --workspace check --no-default-features"
|
||||||
ci-check-lib = "hack --workspace --feature-powerset --exclude-features=io-uring check"
|
ci-check-lib = "hack --workspace --feature-powerset --depth=2 --exclude-features=io-uring check"
|
||||||
ci-check-lib-linux = "hack --workspace --feature-powerset check"
|
ci-check-lib-linux = "hack --workspace --feature-powerset --depth=2 check"
|
||||||
|
|
||||||
# check everything
|
# check everything
|
||||||
ci-check = "hack --workspace --feature-powerset --exclude-features=io-uring check --tests --examples"
|
ci-check = "hack --workspace --feature-powerset --depth=2 --exclude-features=io-uring check --tests --examples"
|
||||||
ci-check-linux = "hack --workspace --feature-powerset check --tests --examples"
|
ci-check-linux = "hack --workspace --feature-powerset --depth=2 check --tests --examples"
|
||||||
|
|
||||||
# tests avoiding io-uring feature
|
# tests avoiding io-uring feature
|
||||||
ci-test = "hack --feature-powerset --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
ci-test = "hack --feature-powerset --depth=2 --exclude-features=io-uring test --lib --tests --no-fail-fast -- --nocapture"
|
||||||
ci-test-rustls-020 = "hack --feature-powerset --exclude-features=io-uring,rustls-0_21 test --lib --tests --no-fail-fast -- --nocapture"
|
|
||||||
ci-test-rustls-021 = "hack --feature-powerset --exclude-features=io-uring,rustls-0_20 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-linux = "hack --feature-powerset --exclude-features=rustls-0_20 test --lib --tests --no-fail-fast -- --nocapture"
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
## PR Type
|
## PR Type
|
||||||
|
|
||||||
<!-- What kind of change does this PR make? -->
|
<!-- What kind of change does this PR make? -->
|
||||||
<!-- Bug Fix / Feature / Refactor / Code Style / Other -->
|
<!-- Bug Fix / Feature / Refactor / Code Style / Other -->
|
||||||
|
|
||||||
INSERT_PR_TYPE
|
INSERT_PR_TYPE
|
||||||
|
|
||||||
|
|
||||||
## PR Checklist
|
## PR Checklist
|
||||||
|
|
||||||
Check your PR fulfills the following:
|
Check your PR fulfills the following:
|
||||||
|
|
||||||
<!-- For draft PRs check the boxes as you complete them. -->
|
<!-- For draft PRs check the boxes as you complete them. -->
|
||||||
|
@ -14,11 +16,10 @@ Check your PR fulfills the following:
|
||||||
- [ ] A changelog entry has been made for the appropriate packages.
|
- [ ] A changelog entry has been made for the appropriate packages.
|
||||||
- [ ] Format code with the latest stable rustfmt
|
- [ ] Format code with the latest stable rustfmt
|
||||||
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
<!-- Describe the current and new behavior. -->
|
<!-- Describe the current and new behavior. -->
|
||||||
<!-- Emphasize any breaking changes. -->
|
<!-- Emphasize any breaking changes. -->
|
||||||
|
|
||||||
|
|
||||||
<!-- If this PR fixes or closes an issue, reference it here. -->
|
<!-- If this PR fixes or closes an issue, reference it here. -->
|
||||||
<!-- Closes #000 -->
|
<!-- Closes #000 -->
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: github-actions
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
||||||
|
- package-ecosystem: cargo
|
||||||
|
directory: /
|
||||||
|
schedule:
|
||||||
|
interval: weekly
|
|
@ -1,4 +1,4 @@
|
||||||
name: CI (master only)
|
name: CI (post-merge)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
@ -22,7 +22,6 @@ jobs:
|
||||||
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
||||||
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
|
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
|
||||||
- { name: Windows (MinGW), os: windows-latest, triple: x86_64-pc-windows-gnu }
|
- { 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:
|
version:
|
||||||
- nightly
|
- nightly
|
||||||
|
|
||||||
|
@ -36,28 +35,38 @@ jobs:
|
||||||
if: matrix.target.os == 'macos-latest'
|
if: matrix.target.os == 'macos-latest'
|
||||||
run: sudo ifconfig lo0 alias 127.0.0.3
|
run: sudo ifconfig lo0 alias 127.0.0.3
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Free Disk Space
|
- name: Free Disk Space
|
||||||
if: matrix.target.os == 'ubuntu-latest'
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
run: ./scripts/free-disk-space.sh
|
run: ./scripts/free-disk-space.sh
|
||||||
|
|
||||||
|
- name: Setup mold linker
|
||||||
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
|
uses: rui314/setup-mold@v1
|
||||||
|
|
||||||
|
- name: Install nasm
|
||||||
|
if: matrix.target.os == 'windows-latest'
|
||||||
|
uses: ilammy/setup-nasm@v1.5.2
|
||||||
|
|
||||||
- name: Install OpenSSL
|
- name: Install OpenSSL
|
||||||
if: matrix.target.os == 'windows-latest'
|
if: matrix.target.os == 'windows-latest'
|
||||||
run: choco install openssl -y --forcex64 --no-progress
|
shell: bash
|
||||||
- name: Set OpenSSL dir in env
|
|
||||||
if: matrix.target.os == 'windows-latest'
|
|
||||||
run: |
|
run: |
|
||||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append
|
set -e
|
||||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
|
choco install openssl --version=1.1.1.2100 -y --no-progress
|
||||||
|
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV
|
||||||
|
echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Install Rust (${{ matrix.version }})
|
- name: Install Rust (${{ matrix.version }})
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.version }}
|
toolchain: ${{ matrix.version }}
|
||||||
|
|
||||||
- uses: taiki-e/install-action@v2
|
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
|
||||||
with: { tool: cargo-hack }
|
uses: taiki-e/install-action@v2.49.34
|
||||||
|
with:
|
||||||
|
tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean
|
||||||
|
|
||||||
- name: check lib
|
- name: check lib
|
||||||
if: >
|
if: >
|
||||||
|
@ -82,78 +91,39 @@ jobs:
|
||||||
run: cargo ci-check-linux
|
run: cargo ci-check-linux
|
||||||
|
|
||||||
- name: tests
|
- name: tests
|
||||||
if: >
|
run: just test
|
||||||
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-rustls-020
|
|
||||||
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-021
|
|
||||||
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
|
|
||||||
"
|
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
# TODO: re-instate some io-uring tests PRs
|
||||||
run: |
|
# - name: tests
|
||||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
# if: matrix.target.os == 'ubuntu-latest'
|
||||||
cargo-cache
|
# run: >-
|
||||||
|
# sudo bash -c "
|
||||||
|
# ulimit -Sl 512
|
||||||
|
# && ulimit -Hl 512
|
||||||
|
# && PATH=$PATH:/usr/share/rust/.cargo/bin
|
||||||
|
# && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-020
|
||||||
|
# && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-021
|
||||||
|
# && RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
|
||||||
|
# "
|
||||||
|
|
||||||
coverage:
|
- name: CI cache clean
|
||||||
name: coverage
|
run: cargo-ci-cache-clean
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Install Rust (nightly)
|
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
with: { toolchain: nightly }
|
|
||||||
|
|
||||||
- name: Install cargo-tarpaulin
|
|
||||||
uses: taiki-e/install-action@v1
|
|
||||||
with: { tool: cargo-tarpaulin }
|
|
||||||
|
|
||||||
- name: Generate coverage file
|
|
||||||
if: github.ref == 'refs/heads/master'
|
|
||||||
run: cargo tarpaulin --out Xml --verbose
|
|
||||||
- name: Upload to Codecov
|
|
||||||
if: github.ref == 'refs/heads/master'
|
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with: { files: cobertura.xml }
|
|
||||||
|
|
||||||
minimal-versions:
|
minimal-versions:
|
||||||
name: minimal versions
|
name: minimal versions
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust (nightly)
|
- name: Install Rust (nightly)
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
|
||||||
with: { toolchain: nightly }
|
with:
|
||||||
|
toolchain: nightly
|
||||||
|
|
||||||
- name: Install cargo-hack & cargo-minimal-versions
|
- name: Install cargo-hack & cargo-minimal-versions
|
||||||
uses: taiki-e/install-action@v1
|
uses: taiki-e/install-action@v2.49.34
|
||||||
with: { tool: 'cargo-hack,cargo-minimal-versions' }
|
with:
|
||||||
|
tool: cargo-hack,cargo-minimal-versions
|
||||||
|
|
||||||
- name: Check With Minimal Versions
|
- name: Check With Minimal Versions
|
||||||
run: cargo minimal-versions check
|
run: cargo minimal-versions check
|
||||||
|
|
||||||
nextest:
|
|
||||||
name: nextest
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Install Rust
|
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
|
|
||||||
- name: Install cargo-nextest
|
|
||||||
uses: taiki-e/install-action@v1
|
|
||||||
with: { tool: cargo-nextest }
|
|
||||||
|
|
||||||
- name: Test with cargo-nextest
|
|
||||||
run: cargo nextest run
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request: {}
|
pull_request: {}
|
||||||
|
merge_group: { types: [checks_requested] }
|
||||||
push: { branches: [master] }
|
push: { branches: [master] }
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
|
@ -12,7 +13,14 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
read_msrv:
|
||||||
|
name: Read MSRV
|
||||||
|
uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@v0.1.0
|
||||||
|
|
||||||
build_and_test:
|
build_and_test:
|
||||||
|
needs:
|
||||||
|
- read_msrv
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -22,12 +30,11 @@ jobs:
|
||||||
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
|
||||||
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
|
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
|
||||||
- { name: Windows (MinGW), os: windows-latest, triple: x86_64-pc-windows-gnu }
|
- { 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:
|
version:
|
||||||
- 1.65.0 # MSRV
|
- { name: msrv, version: "${{ needs.read_msrv.outputs.msrv }}" }
|
||||||
- stable
|
- { name: stable, version: stable }
|
||||||
|
|
||||||
name: ${{ matrix.target.name }} / ${{ matrix.version }}
|
name: ${{ matrix.target.name }} / ${{ matrix.version.name }}
|
||||||
runs-on: ${{ matrix.target.os }}
|
runs-on: ${{ matrix.target.os }}
|
||||||
|
|
||||||
env: {}
|
env: {}
|
||||||
|
@ -37,36 +44,45 @@ jobs:
|
||||||
if: matrix.target.os == 'macos-latest'
|
if: matrix.target.os == 'macos-latest'
|
||||||
run: sudo ifconfig lo0 alias 127.0.0.3
|
run: sudo ifconfig lo0 alias 127.0.0.3
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Free Disk Space
|
- name: Free Disk Space
|
||||||
if: matrix.target.os == 'ubuntu-latest'
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
run: ./scripts/free-disk-space.sh
|
run: ./scripts/free-disk-space.sh
|
||||||
|
|
||||||
|
- name: Setup mold linker
|
||||||
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
|
uses: rui314/setup-mold@v1
|
||||||
|
|
||||||
|
- name: Install nasm
|
||||||
|
if: matrix.target.os == 'windows-latest'
|
||||||
|
uses: ilammy/setup-nasm@v1.5.2
|
||||||
|
|
||||||
- name: Install OpenSSL
|
- name: Install OpenSSL
|
||||||
if: matrix.target.os == 'windows-latest'
|
if: matrix.target.os == 'windows-latest'
|
||||||
run: choco install openssl -y --forcex64 --no-progress
|
shell: bash
|
||||||
- name: Set OpenSSL dir in env
|
|
||||||
if: matrix.target.os == 'windows-latest'
|
|
||||||
run: |
|
run: |
|
||||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append
|
set -e
|
||||||
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append
|
choco install openssl --version=1.1.1.2100 -y --no-progress
|
||||||
|
echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV
|
||||||
|
echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Install Rust (${{ matrix.version }})
|
- name: Install Rust (${{ matrix.version.name }})
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ matrix.version }}
|
toolchain: ${{ matrix.version.version }}
|
||||||
|
|
||||||
- uses: taiki-e/install-action@v1
|
- name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean
|
||||||
with: { tool: cargo-hack }
|
uses: taiki-e/install-action@v2.49.34
|
||||||
|
with:
|
||||||
|
tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean
|
||||||
|
|
||||||
- name: Generate Cargo.lock
|
- name: Generate Cargo.lock
|
||||||
run: cargo generate-lockfile
|
run: cargo generate-lockfile
|
||||||
|
|
||||||
- name: workaround MSRV issues
|
- name: workaround MSRV issues
|
||||||
if: matrix.version != 'stable'
|
if: matrix.version.name == 'msrv'
|
||||||
run: |
|
run: just downgrade-for-msrv
|
||||||
cargo update -p=time --precise=0.3.16 # time is only a dev dep so shouldn't affect msrv
|
|
||||||
|
|
||||||
- name: check lib
|
- name: check lib
|
||||||
if: >
|
if: >
|
||||||
|
@ -77,7 +93,7 @@ jobs:
|
||||||
if: matrix.target.os == 'ubuntu-latest'
|
if: matrix.target.os == 'ubuntu-latest'
|
||||||
run: cargo ci-check-lib-linux
|
run: cargo ci-check-lib-linux
|
||||||
- name: check lib
|
- name: check lib
|
||||||
if: matrix.target.triple == 'x86_64-pc-windows-gnu'
|
if: matrix.target.triple != 'x86_64-pc-windows-gnu'
|
||||||
run: cargo ci-check-min
|
run: cargo ci-check-min
|
||||||
|
|
||||||
- name: check full
|
- name: check full
|
||||||
|
@ -91,41 +107,27 @@ jobs:
|
||||||
run: cargo ci-check-linux
|
run: cargo ci-check-linux
|
||||||
|
|
||||||
- name: tests
|
- name: tests
|
||||||
if: matrix.target.os == 'macos-latest'
|
run: just test
|
||||||
run: cargo ci-test
|
|
||||||
- name: tests
|
|
||||||
if: >
|
|
||||||
matrix.target.os == 'windows-latest'
|
|
||||||
&& matrix.target.triple != 'x86_64-pc-windows-gnu'
|
|
||||||
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-rustls-020
|
|
||||||
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-rustls-021
|
|
||||||
&& RUSTUP_TOOLCHAIN=${{ matrix.version }} cargo ci-test-linux
|
|
||||||
"
|
|
||||||
|
|
||||||
- name: Clear the cargo caches
|
- name: CI cache clean
|
||||||
run: |
|
run: cargo-ci-cache-clean
|
||||||
cargo install cargo-cache --version 0.6.2 --no-default-features --features ci-autoclean
|
|
||||||
cargo-cache
|
|
||||||
|
|
||||||
rustdoc:
|
docs:
|
||||||
name: rustdoc
|
name: Documentation
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Rust (nightly)
|
- name: Install Rust (nightly)
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
|
||||||
with: { toolchain: nightly }
|
with:
|
||||||
|
toolchain: nightly
|
||||||
|
|
||||||
- name: doc tests io-uring
|
- name: Install just
|
||||||
run: |
|
uses: taiki-e/install-action@v2.49.34
|
||||||
sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=nightly cargo ci-doctest"
|
with:
|
||||||
|
tool: just
|
||||||
|
|
||||||
|
- name: doc tests
|
||||||
|
run: just test-docs
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
name: Lint
|
|
||||||
|
|
||||||
on: [pull_request]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
fmt:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: nightly
|
|
||||||
components: rustfmt
|
|
||||||
|
|
||||||
- name: Rustfmt Check
|
|
||||||
run: cargo fmt --all -- --check
|
|
||||||
|
|
||||||
clippy:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
with: { components: clippy }
|
|
||||||
|
|
||||||
- uses: giraffate/clippy-action@v1
|
|
||||||
with:
|
|
||||||
reporter: 'github-pr-check'
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
name: Coverage
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
coverage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Rust
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
|
||||||
|
with:
|
||||||
|
components: llvm-tools-preview
|
||||||
|
|
||||||
|
- name: Install cargo-llvm-cov
|
||||||
|
uses: taiki-e/install-action@v2.49.34
|
||||||
|
with:
|
||||||
|
tool: cargo-llvm-cov
|
||||||
|
|
||||||
|
- name: Generate code coverage
|
||||||
|
run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json
|
||||||
|
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v5.4.0
|
||||||
|
with:
|
||||||
|
files: codecov.json
|
||||||
|
fail_ci_if_error: true
|
||||||
|
env:
|
||||||
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
@ -0,0 +1,69 @@
|
||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request: {}
|
||||||
|
merge_group: { types: [checks_requested] }
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fmt:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
|
||||||
|
with:
|
||||||
|
toolchain: nightly
|
||||||
|
components: rustfmt
|
||||||
|
|
||||||
|
- name: Rustfmt Check
|
||||||
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
|
clippy:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
|
||||||
|
with: { components: clippy }
|
||||||
|
|
||||||
|
- uses: giraffate/clippy-action@v1.0.1
|
||||||
|
with:
|
||||||
|
reporter: "github-pr-check"
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo -Aunknown_lints
|
||||||
|
|
||||||
|
check-external-types:
|
||||||
|
if: false # rustdoc mismatch currently
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Rust (${{ vars.RUST_VERSION_EXTERNAL_TYPES }})
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1.11.0
|
||||||
|
with:
|
||||||
|
toolchain: ${{ vars.RUST_VERSION_EXTERNAL_TYPES }}
|
||||||
|
|
||||||
|
- name: Install just
|
||||||
|
uses: taiki-e/install-action@v2.49.34
|
||||||
|
with:
|
||||||
|
tool: just
|
||||||
|
|
||||||
|
- name: Install cargo-check-external-types
|
||||||
|
uses: taiki-e/cache-cargo-install-action@v2.1.1
|
||||||
|
with:
|
||||||
|
tool: cargo-check-external-types
|
||||||
|
|
||||||
|
- name: check external types
|
||||||
|
run: just check-external-types-all +${{ vars.RUST_VERSION_EXTERNAL_TYPES }}
|
|
@ -1,35 +0,0 @@
|
||||||
name: Upload documentation
|
|
||||||
|
|
||||||
on:
|
|
||||||
push: { branches: [master] }
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
with: { toolchain: nightly }
|
|
||||||
|
|
||||||
- name: Build Docs
|
|
||||||
run: cargo doc --workspace --all-features --no-deps
|
|
||||||
|
|
||||||
- name: Tweak HTML
|
|
||||||
run: echo '<meta http-equiv="refresh" content="0;url=actix_server/index.html">' > target/doc/index.html
|
|
||||||
|
|
||||||
- name: Deploy to GitHub Pages
|
|
||||||
uses: JamesIves/github-pages-deploy-action@v4
|
|
||||||
with:
|
|
||||||
folder: target/doc
|
|
|
@ -1,4 +1,3 @@
|
||||||
Cargo.lock
|
|
||||||
target/
|
target/
|
||||||
guide/build/
|
guide/build/
|
||||||
/gh-pages
|
/gh-pages
|
||||||
|
@ -13,4 +12,8 @@ guide/build/
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# IDEs
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
# direnv
|
||||||
|
/.direnv
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
exclude = ["target/*"]
|
||||||
|
include = ["**/*.toml"]
|
||||||
|
|
||||||
|
[formatting]
|
||||||
|
column_width = 110
|
||||||
|
|
||||||
|
[[rule]]
|
||||||
|
include = ["**/Cargo.toml"]
|
||||||
|
keys = [
|
||||||
|
"dependencies",
|
||||||
|
"*-dependencies",
|
||||||
|
"workspace.dependencies",
|
||||||
|
"workspace.*-dependencies",
|
||||||
|
"target.*.dependencies",
|
||||||
|
"target.*.*-dependencies",
|
||||||
|
]
|
||||||
|
formatting.reorder_keys = true
|
||||||
|
|
||||||
|
[[rule]]
|
||||||
|
include = ["**/Cargo.toml"]
|
||||||
|
keys = [
|
||||||
|
"dependencies.*",
|
||||||
|
"*-dependencies.*",
|
||||||
|
"workspace.dependencies.*",
|
||||||
|
"workspace.*-dependencies.*",
|
||||||
|
"target.*.dependencies",
|
||||||
|
"target.*.*-dependencies",
|
||||||
|
]
|
||||||
|
formatting.reorder_keys = false
|
File diff suppressed because it is too large
Load Diff
10
Cargo.toml
10
Cargo.toml
|
@ -1,4 +1,5 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"actix-codec",
|
"actix-codec",
|
||||||
"actix-macros",
|
"actix-macros",
|
||||||
|
@ -12,12 +13,11 @@ members = [
|
||||||
"local-channel",
|
"local-channel",
|
||||||
"local-waker",
|
"local-waker",
|
||||||
]
|
]
|
||||||
resolver = "2"
|
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.65"
|
rust-version = "1.71.1"
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
actix-codec = { path = "actix-codec" }
|
actix-codec = { path = "actix-codec" }
|
||||||
|
@ -36,3 +36,9 @@ local-waker = { path = "local-waker" }
|
||||||
lto = true
|
lto = true
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
|
[workspace.lints.rust]
|
||||||
|
rust_2018_idioms = "deny"
|
||||||
|
nonstandard-style = "deny"
|
||||||
|
future_incompatible = "deny"
|
||||||
|
missing_docs = { level = "warn", priority = -1 }
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
> A collection of lower-level libraries for composable network services.
|
> A collection of lower-level libraries for composable network services.
|
||||||
|
|
||||||
[](https://github.com/actix/actix-net/actions/workflows/ci.yml)
|
[](https://github.com/actix/actix-net/actions/workflows/ci.yml)
|
||||||
[](https://codecov.io/gh/actix/actix-net)
|
[](https://codecov.io/gh/actix/actix-net)
|
||||||
[](https://discord.gg/NWpN5mmg3x)
|
[](https://discord.gg/NWpN5mmg3x)
|
||||||
[](https://deps.rs/repo/github/actix/actix-net)
|
[](https://deps.rs/repo/github/actix/actix-net)
|
||||||
|
|
||||||
|
|
|
@ -1,56 +1,51 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
|
## 0.5.2
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 0.5.1 - 2022-03-15
|
## 0.5.1
|
||||||
|
|
||||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#451]
|
- Logs emitted now use the `tracing` crate with `log` compatibility.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||||
|
|
||||||
[#451]: https://github.com/actix/actix-net/pull/451
|
## 0.5.0
|
||||||
|
|
||||||
## 0.5.0 - 2022-02-15
|
- Updated `tokio-util` dependency to `0.7.0`.
|
||||||
|
|
||||||
- Updated `tokio-util` dependency to `0.7.0`. [#446]
|
## 0.4.2
|
||||||
|
|
||||||
[#446]: https://github.com/actix/actix-net/pull/446
|
|
||||||
|
|
||||||
## 0.4.2 - 2021-12-31
|
|
||||||
|
|
||||||
- No significant changes since `0.4.1`.
|
- No significant changes since `0.4.1`.
|
||||||
|
|
||||||
## 0.4.1 - 2021-11-05
|
## 0.4.1
|
||||||
|
|
||||||
- Added `LinesCodec.` [#338]
|
- Added `LinesCodec`.
|
||||||
- `Framed::poll_ready` flushes when the buffer is full. [#409]
|
- `Framed::poll_ready` flushes when the buffer is full.
|
||||||
|
|
||||||
[#338]: https://github.com/actix/actix-net/pull/338
|
## 0.4.0
|
||||||
[#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
|
## 0.4.0-beta.1
|
||||||
|
|
||||||
- Replace `pin-project` with `pin-project-lite`. [#237]
|
- Replace `pin-project` with `pin-project-lite`.
|
||||||
- Upgrade `tokio` dependency to `1`. [#237]
|
- Upgrade `tokio` dependency to `1`.
|
||||||
- Upgrade `tokio-util` dependency to `0.6`. [#237]
|
- Upgrade `tokio-util` dependency to `0.6`.
|
||||||
- Upgrade `bytes` dependency to `1`. [#237]
|
- Upgrade `bytes` dependency to `1`.
|
||||||
|
|
||||||
[#237]: https://github.com/actix/actix-net/pull/237
|
## 0.3.0
|
||||||
|
|
||||||
## 0.3.0 - 2020-08-23
|
|
||||||
|
|
||||||
- No changes from beta 2.
|
- No changes from beta 2.
|
||||||
|
|
||||||
## 0.3.0-beta.2 - 2020-08-19
|
## 0.3.0-beta.2
|
||||||
|
|
||||||
- Remove unused type parameter from `Framed::replace_codec`.
|
- Remove unused type parameter from `Framed::replace_codec`.
|
||||||
|
|
||||||
## 0.3.0-beta.1 - 2020-08-19
|
## 0.3.0-beta.1
|
||||||
|
|
||||||
- Use `.advance()` instead of `.split_to()`.
|
- Use `.advance()` instead of `.split_to()`.
|
||||||
- Upgrade `tokio-util` to `0.3`.
|
- Upgrade `tokio-util` to `0.3`.
|
||||||
|
@ -60,7 +55,7 @@
|
||||||
- Add method on `Framed` to get a pinned reference to the underlying I/O.
|
- Add method on `Framed` to get a pinned reference to the underlying I/O.
|
||||||
- Add method on `Framed` check emptiness of read buffer.
|
- Add method on `Framed` check emptiness of read buffer.
|
||||||
|
|
||||||
## 0.2.0 - 2019-12-10
|
## 0.2.0
|
||||||
|
|
||||||
- Use specific futures dependencies.
|
- Use specific futures dependencies.
|
||||||
|
|
||||||
|
@ -77,14 +72,14 @@
|
||||||
|
|
||||||
- Migrated to `std::future`.
|
- Migrated to `std::future`.
|
||||||
|
|
||||||
## 0.1.2 - 2019-03-27
|
## 0.1.2
|
||||||
|
|
||||||
- Added `Framed::map_io()` method.
|
- Added `Framed::map_io()` method.
|
||||||
|
|
||||||
## 0.1.1 - 2019-03-06
|
## 0.1.1
|
||||||
|
|
||||||
- Added `FramedParts::with_read_buffer()` method.
|
- Added `FramedParts::with_read_buffer()` method.
|
||||||
|
|
||||||
## 0.1.0 - 2018-12-09
|
## 0.1.0
|
||||||
|
|
||||||
- Move codec to separate crate.
|
- Move codec to separate crate.
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-codec"
|
name = "actix-codec"
|
||||||
version = "0.5.1"
|
version = "0.5.2"
|
||||||
authors = [
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
|
||||||
]
|
|
||||||
description = "Codec utilities for working with framed protocols"
|
description = "Codec utilities for working with framed protocols"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
repository = "https://github.com/actix/actix-net"
|
repository = "https://github.com/actix/actix-net"
|
||||||
|
@ -13,6 +10,9 @@ license = "MIT OR Apache-2.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = ["bytes::*", "futures_core::*", "futures_sink::*", "tokio::*", "tokio_util::*"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "2"
|
bitflags = "2"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
|
@ -25,9 +25,12 @@ tokio-util = { version = "0.7", features = ["codec", "io"] }
|
||||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = { version = "0.4", features = ["html_reports"] }
|
criterion = { version = "0.5", features = ["html_reports"] }
|
||||||
tokio-test = "0.4.2"
|
tokio-test = "0.4.2"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "lines"
|
name = "lines"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
//! [`Sink`]: futures_sink::Sink
|
//! [`Sink`]: futures_sink::Sink
|
||||||
//! [`Stream`]: futures_core::Stream
|
//! [`Stream`]: futures_core::Stream
|
||||||
|
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
||||||
#![warn(future_incompatible, missing_docs)]
|
|
||||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
## 0.2.4
|
## 0.2.4
|
||||||
|
|
||||||
- Update `syn` dependency to `2`.
|
- Update `syn` dependency to `2`.
|
||||||
|
|
|
@ -2,17 +2,22 @@
|
||||||
name = "actix-macros"
|
name = "actix-macros"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
authors = [
|
authors = [
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||||
"Ibraheem Ahmed <ibrah1440@gmail.com>",
|
"Ibraheem Ahmed <ibrah1440@gmail.com>",
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
"Rob Ede <robjtede@icloud.com>",
|
||||||
]
|
]
|
||||||
description = "Macros for Actix system and runtime"
|
description = "Macros for Actix system and runtime"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo-machete]
|
||||||
|
ignored = [
|
||||||
|
"proc_macro2", # specified for minimal versions compat
|
||||||
|
]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
|
@ -20,9 +25,15 @@ proc-macro = true
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = { version = "2", features = ["full"] }
|
syn = { version = "2", features = ["full"] }
|
||||||
|
|
||||||
|
# minimal versions compat
|
||||||
|
[target.'cfg(any())'.dependencies]
|
||||||
|
proc-macro2 = "1.0.60"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2"
|
actix-rt = "2"
|
||||||
|
|
||||||
futures-util = { version = "0.3.17", default-features = false }
|
futures-util = { version = "0.3.17", default-features = false }
|
||||||
rustversion = "1"
|
rustversion-msrv = "0.100"
|
||||||
trybuild = "1"
|
trybuild = "1"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
//! # Tests
|
//! # Tests
|
||||||
//! See docs for the [`#[test]`](macro@test) macro.
|
//! 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_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#[rustversion::stable(1.65)] // MSRV
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
|
#[rustversion_msrv::msrv]
|
||||||
#[test]
|
#[test]
|
||||||
fn compile_macros() {
|
fn compile_macros() {
|
||||||
let t = trybuild::TestCases::new();
|
let t = trybuild::TestCases::new();
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
|
## 2.10.0
|
||||||
|
|
||||||
|
- Relax `F`'s bound (`Fn => FnOnce`) on `{Arbiter, System}::with_tokio_rt()` functions.
|
||||||
|
- Update `tokio-uring` dependency to `0.5`.
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.70.
|
||||||
|
|
||||||
## 2.9.0
|
## 2.9.0
|
||||||
|
|
||||||
|
@ -8,204 +16,159 @@
|
||||||
- Add `actix_rt::Runtime::tokio_runtime()` method to retrieve the underlying Tokio runtime.
|
- Add `actix_rt::Runtime::tokio_runtime()` method to retrieve the underlying Tokio runtime.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 2.8.0 - 2022-12-21
|
## 2.8.0
|
||||||
|
|
||||||
- Add `#[track_caller]` attribute to `spawn` functions and methods. [#454]
|
- Add `#[track_caller]` attribute to `spawn` functions and methods.
|
||||||
- Update `tokio-uring` dependency to `0.4`. [#473]
|
- Update `tokio-uring` dependency to `0.4`.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.59.
|
- Minimum supported Rust version (MSRV) is now 1.59.
|
||||||
|
|
||||||
[#454]: https://github.com/actix/actix-net/pull/454
|
## 2.7.0
|
||||||
[#473]: https://github.com/actix/actix-net/pull/473
|
|
||||||
|
|
||||||
## 2.7.0 - 2022-03-08
|
- Update `tokio-uring` dependency to `0.3`.
|
||||||
|
|
||||||
- Update `tokio-uring` dependency to `0.3`. [#448]
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||||
|
|
||||||
[#448]: https://github.com/actix/actix-net/pull/448
|
## 2.6.0
|
||||||
|
|
||||||
## 2.6.0 - 2022-01-12
|
- Update `tokio-uring` dependency to `0.2`.
|
||||||
|
|
||||||
- Update `tokio-uring` dependency to `0.2`. [#436]
|
## 2.5.1
|
||||||
|
|
||||||
[#436]: https://github.com/actix/actix-net/pull/436
|
- Expose `System::with_tokio_rt` and `Arbiter::with_tokio_rt`.
|
||||||
|
|
||||||
## 2.5.1 - 2021-12-31
|
## 2.5.0
|
||||||
|
|
||||||
- Expose `System::with_tokio_rt` and `Arbiter::with_tokio_rt`. [#430]
|
- Add `System::run_with_code` to allow retrieving the exit code on stop.
|
||||||
|
|
||||||
[#430]: https://github.com/actix/actix-net/pull/430
|
## 2.4.0
|
||||||
|
|
||||||
## 2.5.0 - 2021-11-22
|
- Add `Arbiter::try_current` for situations where thread may or may not have Arbiter context.
|
||||||
|
- Start io-uring with `System::new` when feature is enabled.
|
||||||
|
|
||||||
- Add `System::run_with_code` to allow retrieving the exit code on stop. [#411]
|
## 2.3.0
|
||||||
|
|
||||||
[#411]: https://github.com/actix/actix-net/pull/411
|
- The `spawn` method can now resolve with non-unit outputs.
|
||||||
|
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux.
|
||||||
|
|
||||||
## 2.4.0 - 2021-11-05
|
## 2.2.0
|
||||||
|
|
||||||
- Add `Arbiter::try_current` for situations where thread may or may not have Arbiter context. [#408]
|
- **BREAKING** `ActixStream::{poll_read_ready, poll_write_ready}` methods now return `Ready` object in ok variant.
|
||||||
- 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]
|
|
||||||
|
|
||||||
[#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 `Ready` object in ok variant. [#293]
|
|
||||||
- Breakage is acceptable since `ActixStream` was not intended to be public.
|
- Breakage is acceptable since `ActixStream` was not intended to be public.
|
||||||
|
|
||||||
[#293]: https://github.com/actix/actix-net/pull/293
|
## 2.1.0
|
||||||
|
|
||||||
## 2.1.0 - 2021-02-24
|
- Add `ActixStream` extension trait to include readiness methods.
|
||||||
|
- Re-export `tokio::net::TcpSocket` in `net` module
|
||||||
|
|
||||||
- Add `ActixStream` extension trait to include readiness methods. [#276]
|
## 2.0.2
|
||||||
- Re-export `tokio::net::TcpSocket` in `net` module [#282]
|
|
||||||
|
|
||||||
[#276]: https://github.com/actix/actix-net/pull/276
|
- Add `Arbiter::handle` to get a handle of an owned Arbiter.
|
||||||
[#282]: https://github.com/actix/actix-net/pull/282
|
- Add `System::try_current` for situations where actix may or may not be running a System.
|
||||||
|
|
||||||
## 2.0.2 - 2021-02-06
|
## 2.0.1
|
||||||
|
|
||||||
- Add `Arbiter::handle` to get a handle of an owned Arbiter. [#274]
|
- Expose `JoinError` from Tokio.
|
||||||
- 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
|
## 2.0.0
|
||||||
[#275]: https://github.com/actix/actix-net/pull/275
|
|
||||||
|
|
||||||
## 2.0.1 - 2021-02-06
|
- Remove all Arbiter-local storage methods.
|
||||||
|
- Re-export `tokio::pin`.
|
||||||
|
|
||||||
- Expose `JoinError` from Tokio. [#271]
|
## 2.0.0-beta.3
|
||||||
|
|
||||||
[#271]: https://github.com/actix/actix-net/pull/271
|
- Remove `run_in_tokio`, `attach_to_tokio` and `AsyncSystemRunner`.
|
||||||
|
- Return `JoinHandle` from `actix_rt::spawn`.
|
||||||
|
- Remove old `Arbiter::spawn`. Implementation is now inlined into `actix_rt::spawn`.
|
||||||
|
- Rename `Arbiter::{send => spawn}` and `Arbiter::{exec_fn => spawn_fn}`.
|
||||||
|
- Remove `Arbiter::exec`.
|
||||||
|
- Remove deprecated `Arbiter::local_join` and `Arbiter::is_running`.
|
||||||
|
- `Arbiter::spawn` now accepts !Unpin futures.
|
||||||
|
- `System::new` no longer takes arguments.
|
||||||
|
- Remove `System::with_current`.
|
||||||
|
- Remove `Builder`.
|
||||||
|
- Add `System::with_init` as replacement for `Builder::run`.
|
||||||
|
- Rename `System::{is_set => is_registered}`.
|
||||||
|
- Add `ArbiterHandle` for sending messages to non-current-thread arbiters.
|
||||||
|
- `System::arbiter` now returns an `&ArbiterHandle`.
|
||||||
|
- `Arbiter::current` now returns an `ArbiterHandle` instead.
|
||||||
|
- `Arbiter::join` now takes self by value.
|
||||||
|
|
||||||
## 2.0.0 - 2021-02-02
|
## 2.0.0-beta.2
|
||||||
|
|
||||||
- Remove all Arbiter-local storage methods. [#262]
|
- Add `task` mod with re-export of `tokio::task::{spawn_blocking, yield_now, JoinHandle}`
|
||||||
- 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]
|
|
||||||
|
|
||||||
[#253]: https://github.com/actix/actix-net/pull/253
|
|
||||||
[#254]: https://github.com/actix/actix-net/pull/254
|
|
||||||
[#256]: https://github.com/actix/actix-net/pull/256
|
|
||||||
[#257]: https://github.com/actix/actix-net/pull/257
|
|
||||||
|
|
||||||
## 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 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
|
||||||
|
|
||||||
## 2.0.0-beta.1 - 2020-12-28
|
- Add `System::attach_to_tokio` method.
|
||||||
|
- Update `tokio` dependency to `1.0`.
|
||||||
- Add `System::attach_to_tokio` method. [#173]
|
- Rename `time` module `delay_for` to `sleep`, `delay_until` to `sleep_until`, `Delay` to `Sleep` to stay aligned with Tokio's naming.
|
||||||
- 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]
|
- These methods now accept `&self` when calling.
|
||||||
- Remove `'static` lifetime requirement for `System::run` and `Builder::run`. [#236]
|
- Remove `'static` lifetime requirement for `System::run` and `Builder::run`.
|
||||||
- `Arbiter::spawn` now panics when `System` is not in scope. [#207]
|
- `Arbiter::spawn` now panics when `System` is not in scope.
|
||||||
- Fix work load issue by removing `PENDING` thread local. [#207]
|
- Fix work load issue by removing `PENDING` thread local.
|
||||||
|
|
||||||
[#207]: https://github.com/actix/actix-net/pull/207
|
## 1.1.1
|
||||||
[#236]: https://github.com/actix/actix-net/pull/236
|
|
||||||
|
|
||||||
## 1.1.1 - 2020-04-30
|
- Fix memory leak due to
|
||||||
|
|
||||||
- Fix memory leak due to [#94] (see [#129] for more detail)
|
## 1.1.0 _(YANKED)_
|
||||||
|
|
||||||
[#129]: https://github.com/actix/actix-net/issues/129
|
- Expose `System::is_set` to check if current system has ben started
|
||||||
|
- Add `Arbiter::is_running` to check if event loop is running
|
||||||
|
- Add `Arbiter::local_join` associated function to get be able to `await` for spawned futures
|
||||||
|
|
||||||
## 1.1.0 - 2020-04-08 _(YANKED)_
|
## 1.0.0
|
||||||
|
|
||||||
- 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
|
|
||||||
[#99]: https://github.com/actix/actix-net/pull/99
|
|
||||||
[#124]: https://github.com/actix/actix-net/pull/124
|
|
||||||
|
|
||||||
## 1.0.0 - 2019-12-11
|
|
||||||
|
|
||||||
- Update dependencies
|
- Update dependencies
|
||||||
|
|
||||||
## 1.0.0-alpha.3 - 2019-12-07
|
## 1.0.0-alpha.3
|
||||||
|
|
||||||
- Migrate to tokio 0.2
|
- Migrate to tokio 0.2
|
||||||
- Fix compilation on non-unix platforms
|
- Fix compilation on non-unix platforms
|
||||||
|
|
||||||
## 1.0.0-alpha.2 - 2019-12-02
|
## 1.0.0-alpha.2
|
||||||
|
|
||||||
- Export `main` and `test` attribute macros
|
- Export `main` and `test` attribute macros
|
||||||
- Export `time` module (re-export of tokio-timer)
|
- Export `time` module (re-export of tokio-timer)
|
||||||
- Export `net` module (re-export of tokio-net)
|
- Export `net` module (re-export of tokio-net)
|
||||||
|
|
||||||
## 1.0.0-alpha.1 - 2019-11-22
|
## 1.0.0-alpha.1
|
||||||
|
|
||||||
- Migrate to std::future and tokio 0.2
|
- Migrate to std::future and tokio 0.2
|
||||||
|
|
||||||
## 0.2.6 - 2019-11-14
|
## 0.2.6
|
||||||
|
|
||||||
- Allow to join arbiter's thread. #60
|
- Allow to join arbiter's thread. #60
|
||||||
- Fix arbiter's thread panic message.
|
- Fix arbiter's thread panic message.
|
||||||
|
|
||||||
## 0.2.5 - 2019-09-02
|
## 0.2.5
|
||||||
|
|
||||||
- Add arbiter specific storage
|
- Add arbiter specific storage
|
||||||
|
|
||||||
## 0.2.4 - 2019-07-17
|
## 0.2.4
|
||||||
|
|
||||||
- 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
|
## 0.2.3
|
||||||
|
|
||||||
- Allow to start System using existing CurrentThread Handle #22
|
- Allow to start System using existing CurrentThread Handle #22
|
||||||
|
|
||||||
## 0.2.2 - 2019-03-28
|
## 0.2.2
|
||||||
|
|
||||||
- Moved `blocking` module to `actix-threadpool` crate
|
- Moved `blocking` module to `actix-threadpool` crate
|
||||||
|
|
||||||
## 0.2.1 - 2019-03-11
|
## 0.2.1
|
||||||
|
|
||||||
- Added `blocking` module
|
- Added `blocking` module
|
||||||
- Added `Arbiter::exec_fn` - execute fn on the arbiter's thread
|
- 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 `Arbiter::exec` - execute fn on the arbiter's thread and wait result
|
||||||
|
|
||||||
## 0.2.0 - 2019-03-06
|
## 0.2.0
|
||||||
|
|
||||||
- `run` method returns `io::Result<()>`
|
- `run` method returns `io::Result<()>`
|
||||||
- Removed `Handle`
|
- Removed `Handle`
|
||||||
|
|
||||||
## 0.1.0 - 2018-12-09
|
## 0.1.0
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-rt"
|
name = "actix-rt"
|
||||||
version = "2.9.0"
|
version = "2.10.0"
|
||||||
authors = [
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
|
||||||
]
|
|
||||||
description = "Tokio-based single-threaded async runtime for the Actix ecosystem"
|
description = "Tokio-based single-threaded async runtime for the Actix ecosystem"
|
||||||
keywords = ["async", "futures", "io", "runtime"]
|
keywords = ["async", "futures", "io", "runtime"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = ["actix_macros::*", "tokio::*"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["macros"]
|
default = ["macros"]
|
||||||
macros = ["actix-macros"]
|
macros = ["actix-macros"]
|
||||||
|
@ -27,8 +27,10 @@ tokio = { version = "1.23.1", features = ["rt", "net", "parking_lot", "signal",
|
||||||
|
|
||||||
# runtime for `io-uring` feature
|
# runtime for `io-uring` feature
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
tokio-uring = { version = "0.4", optional = true }
|
tokio-uring = { version = "0.5", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1.23.1", features = ["full"] }
|
tokio = { version = "1.23.1", features = ["full"] }
|
||||||
hyper = { version = "0.14.10", default-features = false, features = ["server", "tcp", "http1"] }
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
> Tokio-based single-threaded async runtime for the Actix ecosystem.
|
> Tokio-based single-threaded async runtime for the Actix ecosystem.
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-rt)
|
[](https://crates.io/crates/actix-rt)
|
||||||
[](https://docs.rs/actix-rt/2.9.0)
|
[](https://docs.rs/actix-rt/2.10.0)
|
||||||
[](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
|
[](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
|
||||||

|

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

|

|
||||||
[](https://discord.gg/WghFtEH6Hb)
|
[](https://discord.gg/WghFtEH6Hb)
|
||||||
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
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")))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
actix_rt::System::with_tokio_rt(|| {
|
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
})
|
|
||||||
.block_on(async {
|
|
||||||
let make_service =
|
|
||||||
make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) });
|
|
||||||
|
|
||||||
let server = Server::bind(&SocketAddr::from(([127, 0, 0, 1], 3000))).serve(make_service);
|
|
||||||
|
|
||||||
if let Err(err) = server.await {
|
|
||||||
eprintln!("server error: {}", err);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ use crate::system::{System, SystemCommand};
|
||||||
pub(crate) static COUNT: AtomicUsize = AtomicUsize::new(0);
|
pub(crate) static COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
thread_local!(
|
thread_local!(
|
||||||
static HANDLE: RefCell<Option<ArbiterHandle>> = RefCell::new(None);
|
static HANDLE: RefCell<Option<ArbiterHandle>> = const { RefCell::new(None) };
|
||||||
);
|
);
|
||||||
|
|
||||||
pub(crate) enum ArbiterCommand {
|
pub(crate) enum ArbiterCommand {
|
||||||
|
@ -109,7 +109,7 @@ impl Arbiter {
|
||||||
#[cfg(not(all(target_os = "linux", feature = "io-uring")))]
|
#[cfg(not(all(target_os = "linux", feature = "io-uring")))]
|
||||||
pub fn with_tokio_rt<F>(runtime_factory: F) -> Arbiter
|
pub fn with_tokio_rt<F>(runtime_factory: F) -> Arbiter
|
||||||
where
|
where
|
||||||
F: Fn() -> tokio::runtime::Runtime + Send + 'static,
|
F: FnOnce() -> tokio::runtime::Runtime + Send + 'static,
|
||||||
{
|
{
|
||||||
let sys = System::current();
|
let sys = System::current();
|
||||||
let system_id = sys.id();
|
let system_id = sys.id();
|
||||||
|
|
|
@ -34,14 +34,13 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! # `io-uring` Support
|
//! # `io-uring` Support
|
||||||
|
//!
|
||||||
//! There is experimental support for using io-uring with this crate by enabling the
|
//! There is experimental support for using io-uring with this crate by enabling the
|
||||||
//! `io-uring` feature. For now, it is semver exempt.
|
//! `io-uring` feature. For now, it is semver exempt.
|
||||||
//!
|
//!
|
||||||
//! Note that there are currently some unimplemented parts of using `actix-rt` with `io-uring`.
|
//! Note that there are currently some unimplemented parts of using `actix-rt` with `io-uring`.
|
||||||
//! In particular, when running a `System`, only `System::block_on` is supported.
|
//! In particular, when running a `System`, only `System::block_on` is supported.
|
||||||
|
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
||||||
#![warn(future_incompatible, missing_docs)]
|
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::{arbiter::ArbiterHandle, Arbiter};
|
||||||
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
|
static SYSTEM_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
thread_local!(
|
thread_local!(
|
||||||
static CURRENT: RefCell<Option<System>> = RefCell::new(None);
|
static CURRENT: RefCell<Option<System>> = const { RefCell::new(None) };
|
||||||
);
|
);
|
||||||
|
|
||||||
/// A manager for a per-thread distributed async runtime.
|
/// A manager for a per-thread distributed async runtime.
|
||||||
|
@ -48,7 +48,7 @@ impl System {
|
||||||
/// [tokio-runtime]: tokio::runtime::Runtime
|
/// [tokio-runtime]: tokio::runtime::Runtime
|
||||||
pub fn with_tokio_rt<F>(runtime_factory: F) -> SystemRunner
|
pub fn with_tokio_rt<F>(runtime_factory: F) -> SystemRunner
|
||||||
where
|
where
|
||||||
F: Fn() -> tokio::runtime::Runtime,
|
F: FnOnce() -> tokio::runtime::Runtime,
|
||||||
{
|
{
|
||||||
let (stop_tx, stop_rx) = oneshot::channel();
|
let (stop_tx, stop_rx) = oneshot::channel();
|
||||||
let (sys_tx, sys_rx) = mpsc::unbounded_channel();
|
let (sys_tx, sys_rx) = mpsc::unbounded_channel();
|
||||||
|
@ -87,7 +87,7 @@ impl System {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn with_tokio_rt<F>(_: F) -> SystemRunner
|
pub fn with_tokio_rt<F>(_: F) -> SystemRunner
|
||||||
where
|
where
|
||||||
F: Fn() -> tokio::runtime::Runtime,
|
F: FnOnce() -> tokio::runtime::Runtime,
|
||||||
{
|
{
|
||||||
unimplemented!("System::with_tokio_rt is not implemented for io-uring feature yet")
|
unimplemented!("System::with_tokio_rt is not implemented for io-uring feature yet")
|
||||||
}
|
}
|
||||||
|
@ -203,16 +203,20 @@ impl SystemRunner {
|
||||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
|
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves a reference to the underlying Actix runtime associated with this SystemRunner instance.
|
/// Retrieves a reference to the underlying [Actix runtime](crate::Runtime) associated with this
|
||||||
|
/// `SystemRunner` instance.
|
||||||
///
|
///
|
||||||
/// The Actix runtime is responsible for managing the event loop for an Actix system and executing asynchronous tasks.
|
/// The Actix runtime is responsible for managing the event loop for an Actix system and
|
||||||
/// This method provides access to the runtime, allowing direct interaction with its features.
|
/// executing asynchronous tasks. This method provides access to the runtime, allowing direct
|
||||||
|
/// interaction with its features.
|
||||||
///
|
///
|
||||||
/// In a typical use case, you might need to share the same runtime between different
|
/// In a typical use case, you might need to share the same runtime between different
|
||||||
/// parts of your project. For example, some components might require a [`actix_rt::Runtime`] to spawn tasks on
|
/// parts of your project. For example, some components might require a [`Runtime`] to spawn
|
||||||
/// the same runtime.
|
/// tasks on the same runtime.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// Read more in the documentation for [`Runtime`].
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let system_runner = actix_rt::System::new();
|
/// let system_runner = actix_rt::System::new();
|
||||||
|
@ -221,19 +225,14 @@ impl SystemRunner {
|
||||||
/// // Use the runtime to spawn an async task or perform other operations
|
/// // Use the runtime to spawn an async task or perform other operations
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Read more in the documentation for [`actix_rt::Runtime`]
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
///
|
|
||||||
/// An immutable reference to the [`actix_rt::Runtime`] instance associated with this
|
|
||||||
/// [`actix_rt::SystemRunner`] instance.
|
|
||||||
///
|
|
||||||
/// # Note
|
/// # Note
|
||||||
///
|
///
|
||||||
/// While this method provides an immutable reference to the Actix runtime, which is safe to share across threads,
|
/// While this method provides an immutable reference to the Actix runtime, which is safe to
|
||||||
/// be aware that spawning blocking tasks on the Actix runtime could potentially impact system performance.
|
/// share across threads, be aware that spawning blocking tasks on the Actix runtime could
|
||||||
/// This is because the Actix runtime is responsible for driving the system,
|
/// potentially impact system performance. This is because the Actix runtime is responsible for
|
||||||
/// and blocking tasks could delay other tasks in the run loop.
|
/// driving the system, and blocking tasks could delay other tasks in the run loop.
|
||||||
|
///
|
||||||
|
/// [`Runtime`]: crate::Runtime
|
||||||
pub fn runtime(&self) -> &crate::runtime::Runtime {
|
pub fn runtime(&self) -> &crate::runtime::Runtime {
|
||||||
&self.rt
|
&self.rt
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
future::Future,
|
future::Future,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
|
@ -358,7 +360,7 @@ fn tokio_uring_arbiter() {
|
||||||
let f = tokio_uring::fs::File::create("test.txt").await.unwrap();
|
let f = tokio_uring::fs::File::create("test.txt").await.unwrap();
|
||||||
let buf = b"Hello World!";
|
let buf = b"Hello World!";
|
||||||
|
|
||||||
let (res, _) = f.write_at(&buf[..], 0).await;
|
let (res, _) = f.write_all_at(&buf[..], 0).await;
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
|
|
||||||
f.sync_all().await.unwrap();
|
f.sync_all().await.unwrap();
|
||||||
|
|
|
@ -2,15 +2,29 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## 2.5.1
|
||||||
|
|
||||||
|
- Fix panic in test server.
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
|
## 2.5.0
|
||||||
|
|
||||||
|
- Update `mio` dependency to `1`.
|
||||||
|
|
||||||
|
## 2.4.0
|
||||||
|
|
||||||
|
- Update `tokio-uring` dependency to `0.5`.
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.70.
|
||||||
|
|
||||||
|
## 2.3.0
|
||||||
|
|
||||||
- Add support for MultiPath TCP (MPTCP) with `MpTcp` enum and `ServerBuilder::mptcp()` method.
|
- Add support for MultiPath TCP (MPTCP) with `MpTcp` enum and `ServerBuilder::mptcp()` method.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 2.2.0
|
## 2.2.0
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.59.
|
- Minimum supported Rust version (MSRV) is now 1.59.
|
||||||
- Update `tokio-uring` dependency to `0.4`. [#473]
|
- Update `tokio-uring` dependency to `0.4`.
|
||||||
|
|
||||||
[#473]: https://github.com/actix/actix-net/pull/473
|
|
||||||
|
|
||||||
## 2.1.1
|
## 2.1.1
|
||||||
|
|
||||||
|
@ -18,12 +32,9 @@
|
||||||
|
|
||||||
## 2.1.0
|
## 2.1.0
|
||||||
|
|
||||||
- Update `tokio-uring` dependency to `0.3`. [#448]
|
- Update `tokio-uring` dependency to `0.3`.
|
||||||
- Logs emitted now use the `tracing` crate with `log` compatibility. [#448]
|
- Logs emitted now use the `tracing` crate with `log` compatibility.
|
||||||
- Wait for accept thread to stop before sending completion signal. [#443]
|
- Wait for accept thread to stop before sending completion signal.
|
||||||
|
|
||||||
[#443]: https://github.com/actix/actix-net/pull/443
|
|
||||||
[#448]: https://github.com/actix/actix-net/pull/448
|
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
|
@ -31,9 +42,7 @@
|
||||||
|
|
||||||
## 2.0.0-rc.4
|
## 2.0.0-rc.4
|
||||||
|
|
||||||
- Update `tokio-uring` dependency to `0.2`. [#436]
|
- Update `tokio-uring` dependency to `0.2`.
|
||||||
|
|
||||||
[#436]: https://github.com/actix/actix-net/pull/436
|
|
||||||
|
|
||||||
## 2.0.0-rc.3
|
## 2.0.0-rc.3
|
||||||
|
|
||||||
|
@ -41,117 +50,80 @@
|
||||||
|
|
||||||
## 2.0.0-rc.2
|
## 2.0.0-rc.2
|
||||||
|
|
||||||
- Simplify `TestServer`. [#431]
|
- Simplify `TestServer`.
|
||||||
|
|
||||||
[#431]: https://github.com/actix/actix-net/pull/431
|
|
||||||
|
|
||||||
## 2.0.0-rc.1
|
## 2.0.0-rc.1
|
||||||
|
|
||||||
- Hide implementation details of `Server`. [#424]
|
- Hide implementation details of `Server`.
|
||||||
- `Server` now runs only after awaiting it. [#425]
|
- `Server` now runs only after awaiting it.
|
||||||
|
|
||||||
[#424]: https://github.com/actix/actix-net/pull/424
|
|
||||||
[#425]: https://github.com/actix/actix-net/pull/425
|
|
||||||
|
|
||||||
## 2.0.0-beta.9
|
## 2.0.0-beta.9
|
||||||
|
|
||||||
- Restore `Arbiter` support lost in `beta.8`. [#417]
|
- Restore `Arbiter` support lost in `beta.8`.
|
||||||
|
|
||||||
[#417]: https://github.com/actix/actix-net/pull/417
|
|
||||||
|
|
||||||
## 2.0.0-beta.8
|
## 2.0.0-beta.8
|
||||||
|
|
||||||
- Fix non-unix signal handler. [#410]
|
- Fix non-unix signal handler.
|
||||||
|
|
||||||
[#410]: https://github.com/actix/actix-net/pull/410
|
|
||||||
|
|
||||||
## 2.0.0-beta.7
|
## 2.0.0-beta.7
|
||||||
|
|
||||||
- Server can be started in regular Tokio runtime. [#408]
|
- Server can be started in regular Tokio runtime.
|
||||||
- Expose new `Server` type whose `Future` impl resolves when server stops. [#408]
|
- Expose new `Server` type whose `Future` impl resolves when server stops.
|
||||||
- Rename `Server` to `ServerHandle`. [#407]
|
- Rename `Server` to `ServerHandle`.
|
||||||
- Add `Server::handle` to obtain handle to server. [#408]
|
- Add `Server::handle` to obtain handle to server.
|
||||||
- Rename `ServerBuilder::{maxconn => max_concurrent_connections}`. [#407]
|
- Rename `ServerBuilder::{maxconn => max_concurrent_connections}`.
|
||||||
- Deprecate crate-level `new` shortcut for server builder. [#408]
|
- Deprecate crate-level `new` shortcut for server builder.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.52.
|
- 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
|
## 2.0.0-beta.6
|
||||||
|
|
||||||
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux. [#374]
|
- Add experimental (semver-exempt) `io-uring` feature for enabling async file I/O on linux.
|
||||||
- Server no long listens to `SIGHUP` signal. Previously, the received was not used but did block subsequent exit signals from working. [#389]
|
- Server no long listens to `SIGHUP` signal. Previously, the received was not used but did block subsequent exit signals from working.
|
||||||
- Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to this change. [#349]
|
- Remove `config` module. `ServiceConfig`, `ServiceRuntime` public types are removed due to this change.
|
||||||
- Remove `ServerBuilder::configure` [#349]
|
- Remove `ServerBuilder::configure`.
|
||||||
|
|
||||||
[#374]: https://github.com/actix/actix-net/pull/374
|
|
||||||
[#349]: https://github.com/actix/actix-net/pull/349
|
|
||||||
[#389]: https://github.com/actix/actix-net/pull/389
|
|
||||||
|
|
||||||
## 2.0.0-beta.5
|
## 2.0.0-beta.5
|
||||||
|
|
||||||
- Server shutdown notifies all workers to exit regardless if shutdown is graceful. This causes all workers to shutdown immediately in force shutdown case. [#333]
|
- Server shutdown notifies all workers to exit regardless if shutdown is graceful. This causes all workers to shutdown immediately in force shutdown case.
|
||||||
|
|
||||||
[#333]: https://github.com/actix/actix-net/pull/333
|
|
||||||
|
|
||||||
## 2.0.0-beta.4
|
## 2.0.0-beta.4
|
||||||
|
|
||||||
- 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
|
## 2.0.0-beta.3
|
||||||
|
|
||||||
- Hidden `ServerBuilder::start` method has been removed. Use `ServerBuilder::run`. [#246]
|
- Hidden `ServerBuilder::start` method has been removed. Use `ServerBuilder::run`.
|
||||||
- Add retry for EINTR signal (`io::Interrupted`) in `Accept`'s poll loop. [#264]
|
- Add retry for EINTR signal (`io::Interrupted`) in `Accept`'s poll loop.
|
||||||
- Add `ServerBuilder::worker_max_blocking_threads` to customize blocking thread pool size. [#265]
|
- Add `ServerBuilder::worker_max_blocking_threads` to customize blocking thread pool size.
|
||||||
- Update `actix-rt` to `2.0.0`. [#273]
|
- Update `actix-rt` to `2.0.0`.
|
||||||
|
|
||||||
[#246]: https://github.com/actix/actix-net/pull/246
|
|
||||||
[#264]: https://github.com/actix/actix-net/pull/264
|
|
||||||
[#265]: https://github.com/actix/actix-net/pull/265
|
|
||||||
[#273]: https://github.com/actix/actix-net/pull/273
|
|
||||||
|
|
||||||
## 2.0.0-beta.2
|
## 2.0.0-beta.2
|
||||||
|
|
||||||
- Merge `actix-testing` to `actix-server` as `test_server` mod. [#242]
|
- Merge `actix-testing` to `actix-server` as `test_server` mod.
|
||||||
|
|
||||||
[#242]: https://github.com/actix/actix-net/pull/242
|
|
||||||
|
|
||||||
## 2.0.0-beta.1
|
## 2.0.0-beta.1
|
||||||
|
|
||||||
- Added explicit info log message on accept queue pause. [#215]
|
- Added explicit info log message on accept queue pause.
|
||||||
- Prevent double registration of sockets when back-pressure is resolved. [#223]
|
- Prevent double registration of sockets when back-pressure is resolved.
|
||||||
- Update `mio` dependency to `0.7.3`. [#239]
|
- Update `mio` dependency to `0.7.3`.
|
||||||
- Remove `socket2` dependency. [#239]
|
- Remove `socket2` dependency.
|
||||||
- `ServerBuilder::backlog` now accepts `u32` instead of `i32`. [#239]
|
- `ServerBuilder::backlog` now accepts `u32` instead of `i32`.
|
||||||
- Remove `AcceptNotify` type and pass `WakerQueue` to `Worker` to wake up `Accept`'s `Poll`. [#239]
|
- Remove `AcceptNotify` type and pass `WakerQueue` to `Worker` to wake up `Accept`'s `Poll`.
|
||||||
- Convert `mio::net::TcpStream` to `actix_rt::net::TcpStream`(`UnixStream` for uds) using `FromRawFd` and `IntoRawFd`(`FromRawSocket` and `IntoRawSocket` on windows). [#239]
|
- Convert `mio::net::TcpStream` to `actix_rt::net::TcpStream`(`UnixStream` for uds) using `FromRawFd` and `IntoRawFd`(`FromRawSocket` and `IntoRawSocket` on windows).
|
||||||
- Remove `AsyncRead` and `AsyncWrite` trait bound for `socket::FromStream` trait. [#239]
|
- Remove `AsyncRead` and `AsyncWrite` trait bound for `socket::FromStream` trait.
|
||||||
|
|
||||||
[#215]: https://github.com/actix/actix-net/pull/215
|
|
||||||
[#223]: https://github.com/actix/actix-net/pull/223
|
|
||||||
[#239]: https://github.com/actix/actix-net/pull/239
|
|
||||||
|
|
||||||
## 1.0.4
|
## 1.0.4
|
||||||
|
|
||||||
- Update actix-codec to 0.3.0.
|
- Update actix-codec to 0.3.0.
|
||||||
- Workers must be greater than 0. [#167]
|
- Workers must be greater than 0.
|
||||||
|
|
||||||
[#167]: https://github.com/actix/actix-net/pull/167
|
|
||||||
|
|
||||||
## 1.0.3
|
## 1.0.3
|
||||||
|
|
||||||
- Replace deprecated `net2` crate with `socket2` [#140]
|
- Replace deprecated `net2` crate with `socket2`.
|
||||||
|
|
||||||
[#140]: https://github.com/actix/actix-net/pull/140
|
|
||||||
|
|
||||||
## 1.0.2
|
## 1.0.2
|
||||||
|
|
||||||
- Avoid error by calling `reregister()` on Windows [#103]
|
- Avoid error by calling `reregister()` on Windows.
|
||||||
|
|
||||||
[#103]: https://github.com/actix/actix-net/pull/103
|
|
||||||
|
|
||||||
## 1.0.1
|
## 1.0.1
|
||||||
|
|
||||||
|
|
|
@ -1,45 +1,50 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-server"
|
name = "actix-server"
|
||||||
version = "2.2.0"
|
version = "2.5.1"
|
||||||
authors = [
|
authors = [
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
"Nikolay Kim <fafhrd91@gmail.com>",
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
"Rob Ede <robjtede@icloud.com>",
|
||||||
"Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>",
|
"Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>",
|
||||||
]
|
]
|
||||||
description = "General purpose TCP server built for the Actix ecosystem"
|
description = "General purpose TCP server built for the Actix ecosystem"
|
||||||
keywords = ["network", "tcp", "server", "framework", "async"]
|
keywords = ["network", "tcp", "server", "framework", "async"]
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net/tree/master/actix-server"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = ["tokio::*"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
io-uring = ["tokio-uring", "actix-rt/io-uring"]
|
io-uring = ["tokio-uring", "actix-rt/io-uring"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = { version = "2.8", default-features = false }
|
actix-rt = { version = "2.10", default-features = false }
|
||||||
actix-service = "2"
|
actix-service = "2"
|
||||||
actix-utils = "3"
|
actix-utils = "3"
|
||||||
|
|
||||||
futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] }
|
futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] }
|
||||||
futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
|
futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
|
||||||
mio = { version = "0.8", features = ["os-poll", "net"] }
|
mio = { version = "1", features = ["os-poll", "net"] }
|
||||||
socket2 = "0.5"
|
socket2 = "0.5"
|
||||||
tokio = { version = "1.23.1", features = ["sync"] }
|
tokio = { version = "1.23.1", features = ["sync"] }
|
||||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||||
|
|
||||||
# runtime for `io-uring` feature
|
# runtime for `io-uring` feature
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
tokio-uring = { version = "0.4", optional = true }
|
tokio-uring = { version = "0.5", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-codec = "0.5"
|
actix-codec = "0.5"
|
||||||
actix-rt = "2.8"
|
actix-rt = "2.8"
|
||||||
|
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
env_logger = "0.10"
|
|
||||||
futures-util = { version = "0.3.17", default-features = false, features = ["sink", "async-await-macro"] }
|
futures-util = { version = "0.3.17", default-features = false, features = ["sink", "async-await-macro"] }
|
||||||
|
pretty_env_logger = "0.5"
|
||||||
tokio = { version = "1.23.1", features = ["io-util", "rt-multi-thread", "macros", "fs"] }
|
tokio = { version = "1.23.1", features = ["io-util", "rt-multi-thread", "macros", "fs"] }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -2,14 +2,20 @@
|
||||||
|
|
||||||
> General purpose TCP server built for the Actix ecosystem.
|
> General purpose TCP server built for the Actix ecosystem.
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-server)
|
[](https://crates.io/crates/actix-server)
|
||||||
[](https://docs.rs/actix-server/2.2.0)
|
[](https://docs.rs/actix-server/2.5.1)
|
||||||
[](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
[](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
||||||

|

|
||||||
[](https://deps.rs/crate/actix-server/2.2.0)
|
<br />
|
||||||
|
[](https://deps.rs/crate/actix-server/2.5.1)
|
||||||

|

|
||||||
[](https://discord.gg/NWpN5mmg3x)
|
[](https://discord.gg/NWpN5mmg3x)
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
- [Library Documentation](https://docs.rs/actix-server)
|
- [Library Documentation](https://docs.rs/actix-server)
|
||||||
- [Examples](/actix-server/examples)
|
- [Examples](/actix-server/examples)
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
//!
|
//!
|
||||||
//! Follow the prompt and enter a file path, relative or absolute.
|
//! Follow the prompt and enter a file path, relative or absolute.
|
||||||
|
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use actix_codec::{Framed, LinesCodec};
|
use actix_codec::{Framed, LinesCodec};
|
||||||
|
@ -18,7 +20,8 @@ use futures_util::{SinkExt as _, StreamExt as _};
|
||||||
use tokio::{fs::File, io::AsyncReadExt as _};
|
use tokio::{fs::File, io::AsyncReadExt as _};
|
||||||
|
|
||||||
async fn run() -> io::Result<()> {
|
async fn run() -> io::Result<()> {
|
||||||
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
|
pretty_env_logger::formatted_timed_builder()
|
||||||
|
.parse_env(pretty_env_logger::env_logger::Env::default().default_filter_or("info"));
|
||||||
|
|
||||||
let addr = ("127.0.0.1", 8080);
|
let addr = ("127.0.0.1", 8080);
|
||||||
tracing::info!("starting server on port: {}", &addr.0);
|
tracing::info!("starting server on port: {}", &addr.0);
|
||||||
|
|
|
@ -25,7 +25,8 @@ use futures_util::future::ok;
|
||||||
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
|
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _};
|
||||||
|
|
||||||
async fn run() -> io::Result<()> {
|
async fn run() -> io::Result<()> {
|
||||||
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
|
pretty_env_logger::formatted_timed_builder()
|
||||||
|
.parse_env(pretty_env_logger::env_logger::Env::default().default_filter_or("info"));
|
||||||
|
|
||||||
let count = Arc::new(AtomicUsize::new(0));
|
let count = Arc::new(AtomicUsize::new(0));
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ use std::{io, num::NonZeroUsize, time::Duration};
|
||||||
|
|
||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
||||||
use tracing::{info, trace};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
server::ServerCommand,
|
server::ServerCommand,
|
||||||
|
@ -14,7 +13,9 @@ use crate::{
|
||||||
|
|
||||||
/// Multipath TCP (MPTCP) preference.
|
/// Multipath TCP (MPTCP) preference.
|
||||||
///
|
///
|
||||||
/// Also see [`ServerBuilder::mptcp()`].
|
/// Currently only useful on Linux.
|
||||||
|
///
|
||||||
|
#[cfg_attr(target_os = "linux", doc = "Also see [`ServerBuilder::mptcp()`].")]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum MpTcp {
|
pub enum MpTcp {
|
||||||
/// MPTCP will not be used when binding sockets.
|
/// MPTCP will not be used when binding sockets.
|
||||||
|
@ -69,19 +70,19 @@ impl ServerBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set number of workers to start.
|
/// Sets number of workers to start.
|
||||||
|
///
|
||||||
|
/// See [`bind()`](Self::bind()) for more details on how worker count affects the number of
|
||||||
|
/// server factory instantiations.
|
||||||
|
///
|
||||||
|
/// The default worker count is the determined by [`std::thread::available_parallelism()`]. See
|
||||||
|
/// its documentation to determine what behavior you should expect when server is run.
|
||||||
///
|
///
|
||||||
/// `num` 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.
|
|
||||||
///
|
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `num` is 0.
|
/// Panics if `num` is 0.
|
||||||
///
|
|
||||||
/// [`num_cpus`]: https://docs.rs/num_cpus
|
|
||||||
pub fn workers(mut self, num: usize) -> Self {
|
pub fn workers(mut self, num: usize) -> Self {
|
||||||
assert_ne!(num, 0, "workers must be greater than 0");
|
assert_ne!(num, 0, "workers must be greater than 0");
|
||||||
self.threads = num;
|
self.threads = num;
|
||||||
|
@ -155,13 +156,15 @@ impl ServerBuilder {
|
||||||
self.max_concurrent_connections(num)
|
self.max_concurrent_connections(num)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stop Actix `System` after server shutdown.
|
/// Sets flag to stop Actix `System` after server shutdown.
|
||||||
|
///
|
||||||
|
/// This has no effect when server is running in a Tokio-only runtime.
|
||||||
pub fn system_exit(mut self) -> Self {
|
pub fn system_exit(mut self) -> Self {
|
||||||
self.exit = true;
|
self.exit = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disable OS signal handling.
|
/// Disables OS signal handling.
|
||||||
pub fn disable_signals(mut self) -> Self {
|
pub fn disable_signals(mut self) -> Self {
|
||||||
self.listen_os_signals = false;
|
self.listen_os_signals = false;
|
||||||
self
|
self
|
||||||
|
@ -179,25 +182,49 @@ impl ServerBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add new service to the server.
|
/// Adds new service to the server.
|
||||||
pub fn bind<F, U, N>(mut self, name: N, addr: U, factory: F) -> io::Result<Self>
|
///
|
||||||
|
/// Note that, if a DNS lookup is required, resolving hostnames is a blocking operation.
|
||||||
|
///
|
||||||
|
/// # Worker Count
|
||||||
|
///
|
||||||
|
/// The `factory` will be instantiated multiple times in most scenarios. The number of
|
||||||
|
/// instantiations is number of [`workers`](Self::workers()) × number of sockets resolved by
|
||||||
|
/// `addrs`.
|
||||||
|
///
|
||||||
|
/// For example, if you've manually set [`workers`](Self::workers()) to 2, and use `127.0.0.1`
|
||||||
|
/// as the bind `addrs`, then `factory` will be instantiated twice. However, using `localhost`
|
||||||
|
/// as the bind `addrs` can often resolve to both `127.0.0.1` (IPv4) _and_ `::1` (IPv6), causing
|
||||||
|
/// the `factory` to be instantiated 4 times (2 workers × 2 bind addresses).
|
||||||
|
///
|
||||||
|
/// Using a bind address of `0.0.0.0`, which signals to use all interfaces, may also multiple
|
||||||
|
/// the number of instantiations in a similar way.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an `io::Error` if:
|
||||||
|
/// - `addrs` cannot be resolved into one or more socket addresses;
|
||||||
|
/// - all the resolved socket addresses are already bound.
|
||||||
|
pub fn bind<F, U, N>(mut self, name: N, addrs: U, factory: F) -> io::Result<Self>
|
||||||
where
|
where
|
||||||
F: ServerServiceFactory<TcpStream>,
|
F: ServerServiceFactory<TcpStream>,
|
||||||
U: ToSocketAddrs,
|
U: ToSocketAddrs,
|
||||||
N: AsRef<str>,
|
N: AsRef<str>,
|
||||||
{
|
{
|
||||||
let sockets = bind_addr(addr, self.backlog, &self.mptcp)?;
|
let sockets = bind_addr(addrs, self.backlog, &self.mptcp)?;
|
||||||
|
|
||||||
trace!("binding server to: {:?}", &sockets);
|
tracing::trace!("binding server to: {sockets:?}");
|
||||||
|
|
||||||
for lst in sockets {
|
for lst in sockets {
|
||||||
let token = self.next_token();
|
let token = self.next_token();
|
||||||
|
|
||||||
self.factories.push(StreamNewService::create(
|
self.factories.push(StreamNewService::create(
|
||||||
name.as_ref().to_string(),
|
name.as_ref().to_string(),
|
||||||
token,
|
token,
|
||||||
factory.clone(),
|
factory.clone(),
|
||||||
lst.local_addr()?,
|
lst.local_addr()?,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.sockets
|
self.sockets
|
||||||
.push((token, name.as_ref().to_string(), MioListener::Tcp(lst)));
|
.push((token, name.as_ref().to_string(), MioListener::Tcp(lst)));
|
||||||
}
|
}
|
||||||
|
@ -205,7 +232,12 @@ impl ServerBuilder {
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add new service to the server.
|
/// Adds service to the server using a socket listener already bound.
|
||||||
|
///
|
||||||
|
/// # Worker Count
|
||||||
|
///
|
||||||
|
/// The `factory` will be instantiated multiple times in most scenarios. The number of
|
||||||
|
/// instantiations is: number of [`workers`](Self::workers()).
|
||||||
pub fn listen<F, N: AsRef<str>>(
|
pub fn listen<F, N: AsRef<str>>(
|
||||||
mut self,
|
mut self,
|
||||||
name: N,
|
name: N,
|
||||||
|
@ -237,7 +269,7 @@ impl ServerBuilder {
|
||||||
if self.sockets.is_empty() {
|
if self.sockets.is_empty() {
|
||||||
panic!("Server should have at least one bound socket");
|
panic!("Server should have at least one bound socket");
|
||||||
} else {
|
} else {
|
||||||
info!("starting {} workers", self.threads);
|
tracing::info!("starting {} workers", self.threads);
|
||||||
Server::new(self)
|
Server::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +283,12 @@ impl ServerBuilder {
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
impl ServerBuilder {
|
impl ServerBuilder {
|
||||||
/// Add new unix domain service to the server.
|
/// Adds new service to the server using a UDS (unix domain socket) address.
|
||||||
|
///
|
||||||
|
/// # Worker Count
|
||||||
|
///
|
||||||
|
/// The `factory` will be instantiated multiple times in most scenarios. The number of
|
||||||
|
/// instantiations is: number of [`workers`](Self::workers()).
|
||||||
pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> io::Result<Self>
|
pub fn bind_uds<F, U, N>(self, name: N, addr: U, factory: F) -> io::Result<Self>
|
||||||
where
|
where
|
||||||
F: ServerServiceFactory<actix_rt::net::UnixStream>,
|
F: ServerServiceFactory<actix_rt::net::UnixStream>,
|
||||||
|
@ -271,9 +308,14 @@ impl ServerBuilder {
|
||||||
self.listen_uds(name, lst, factory)
|
self.listen_uds(name, lst, factory)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add new unix domain service to the server.
|
/// Adds new service to the server using a UDS (unix domain socket) listener already bound.
|
||||||
///
|
///
|
||||||
/// Useful when running as a systemd service and a socket FD is acquired externally.
|
/// Useful when running as a systemd service and a socket FD is acquired externally.
|
||||||
|
///
|
||||||
|
/// # Worker Count
|
||||||
|
///
|
||||||
|
/// The `factory` will be instantiated multiple times in most scenarios. The number of
|
||||||
|
/// instantiations is: number of [`workers`](Self::workers()).
|
||||||
pub fn listen_uds<F, N: AsRef<str>>(
|
pub fn listen_uds<F, N: AsRef<str>>(
|
||||||
mut self,
|
mut self,
|
||||||
name: N,
|
name: N,
|
||||||
|
@ -284,17 +326,22 @@ impl ServerBuilder {
|
||||||
F: ServerServiceFactory<actix_rt::net::UnixStream>,
|
F: ServerServiceFactory<actix_rt::net::UnixStream>,
|
||||||
{
|
{
|
||||||
use std::net::{IpAddr, Ipv4Addr};
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
|
|
||||||
lst.set_nonblocking(true)?;
|
lst.set_nonblocking(true)?;
|
||||||
|
|
||||||
let token = self.next_token();
|
let token = self.next_token();
|
||||||
let addr = crate::socket::StdSocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
let addr = crate::socket::StdSocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
|
||||||
|
|
||||||
self.factories.push(StreamNewService::create(
|
self.factories.push(StreamNewService::create(
|
||||||
name.as_ref().to_string(),
|
name.as_ref().to_string(),
|
||||||
token,
|
token,
|
||||||
factory,
|
factory,
|
||||||
addr,
|
addr,
|
||||||
));
|
));
|
||||||
|
|
||||||
self.sockets
|
self.sockets
|
||||||
.push((token, name.as_ref().to_string(), MioListener::from(lst)));
|
.push((token, name.as_ref().to_string(), MioListener::from(lst)));
|
||||||
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
//! General purpose TCP server.
|
//! 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_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
|
||||||
|
|
|
@ -183,11 +183,6 @@ impl ServerInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_sync(mut builder: ServerBuilder) -> io::Result<(Self, ServerEventMultiplexer)> {
|
fn run_sync(mut builder: ServerBuilder) -> io::Result<(Self, ServerEventMultiplexer)> {
|
||||||
let sockets = mem::take(&mut builder.sockets)
|
|
||||||
.into_iter()
|
|
||||||
.map(|t| (t.0, t.2))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Give log information on what runtime will be used.
|
// Give log information on what runtime will be used.
|
||||||
let is_actix = actix_rt::System::try_current().is_some();
|
let is_actix = actix_rt::System::try_current().is_some();
|
||||||
let is_tokio = tokio::runtime::Handle::try_current().is_ok();
|
let is_tokio = tokio::runtime::Handle::try_current().is_ok();
|
||||||
|
@ -207,6 +202,11 @@ impl ServerInner {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let sockets = mem::take(&mut builder.sockets)
|
||||||
|
.into_iter()
|
||||||
|
.map(|t| (t.0, t.2))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let (waker_queue, worker_handles, accept_handle) = Accept::start(sockets, &builder)?;
|
let (waker_queue, worker_handles, accept_handle) = Accept::start(sockets, &builder)?;
|
||||||
|
|
||||||
let mux = ServerEventMultiplexer {
|
let mux = ServerEventMultiplexer {
|
||||||
|
|
|
@ -126,7 +126,7 @@ pub(crate) enum SocketAddr {
|
||||||
Unknown,
|
Unknown,
|
||||||
Tcp(StdSocketAddr),
|
Tcp(StdSocketAddr),
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
Uds(mio::net::SocketAddr),
|
Uds(std::os::unix::net::SocketAddr),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for SocketAddr {
|
impl fmt::Display for SocketAddr {
|
||||||
|
@ -160,6 +160,7 @@ pub enum MioStream {
|
||||||
|
|
||||||
/// Helper trait for converting a Mio stream into a Tokio stream.
|
/// Helper trait for converting a Mio stream into a Tokio stream.
|
||||||
pub trait FromStream: Sized {
|
pub trait FromStream: Sized {
|
||||||
|
/// Creates stream from a `mio` stream.
|
||||||
fn from_mio(sock: MioStream) -> io::Result<Self>;
|
fn from_mio(sock: MioStream) -> io::Result<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,9 @@ impl TestServerHandle {
|
||||||
|
|
||||||
/// Connect to server, returning a Tokio `TcpStream`.
|
/// Connect to server, returning a Tokio `TcpStream`.
|
||||||
pub fn connect(&self) -> io::Result<TcpStream> {
|
pub fn connect(&self) -> io::Result<TcpStream> {
|
||||||
TcpStream::from_std(net::TcpStream::connect(self.addr)?)
|
let stream = net::TcpStream::connect(self.addr)?;
|
||||||
|
stream.set_nonblocking(true)?;
|
||||||
|
TcpStream::from_std(stream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![allow(clippy::let_underscore_future)]
|
#![allow(clippy::let_underscore_future, missing_docs)]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
net,
|
net,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use std::net;
|
use std::net;
|
||||||
|
|
||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
|
@ -69,5 +71,7 @@ async fn new_with_builder() {
|
||||||
srv.connect().unwrap();
|
srv.connect().unwrap();
|
||||||
|
|
||||||
// connect to alt service defined in custom ServerBuilder
|
// connect to alt service defined in custom ServerBuilder
|
||||||
TcpStream::from_std(net::TcpStream::connect(alt_addr).unwrap()).unwrap();
|
let stream = net::TcpStream::connect(alt_addr).unwrap();
|
||||||
|
stream.set_nonblocking(true).unwrap();
|
||||||
|
TcpStream::from_std(stream).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,30 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
## 2.0.3
|
||||||
|
|
||||||
## 2.0.2 - 2021-12-18
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
|
## 2.0.2
|
||||||
|
|
||||||
- Service types can now be `Send` and `'static` regardless of request, response, and config types, etc. [#397]
|
- 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
|
[#397]: https://github.com/actix/actix-net/pull/397
|
||||||
|
|
||||||
## 2.0.1 - 2021-10-11
|
## 2.0.1
|
||||||
|
|
||||||
- Documentation fix. [#388]
|
- Documentation fix. [#388]
|
||||||
|
|
||||||
[#388]: https://github.com/actix/actix-net/pull/388
|
[#388]: https://github.com/actix/actix-net/pull/388
|
||||||
|
|
||||||
## 2.0.0 - 2021-04-16
|
## 2.0.0
|
||||||
|
|
||||||
- Removed pipeline and related structs/functions. [#335]
|
- Removed pipeline and related structs/functions. [#335]
|
||||||
|
|
||||||
[#335]: https://github.com/actix/actix-net/pull/335
|
[#335]: https://github.com/actix/actix-net/pull/335
|
||||||
|
|
||||||
## 2.0.0-beta.5 - 2021-03-15
|
## 2.0.0-beta.5
|
||||||
|
|
||||||
- Add default `Service` trait impl for `Rc<S: Service>` and `&S: Service`. [#288]
|
- 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 `boxed::rc_service` function for constructing `boxed::RcService` type [#290]
|
||||||
|
@ -30,7 +32,7 @@
|
||||||
[#288]: https://github.com/actix/actix-net/pull/288
|
[#288]: https://github.com/actix/actix-net/pull/288
|
||||||
[#290]: https://github.com/actix/actix-net/pull/290
|
[#290]: https://github.com/actix/actix-net/pull/290
|
||||||
|
|
||||||
## 2.0.0-beta.4 - 2021-02-04
|
## 2.0.0-beta.4
|
||||||
|
|
||||||
- `Service::poll_ready` and `Service::call` receive `&self`. [#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_fn` and `apply_fn_factory` now receive `Fn(Req, &Service)` function type. [#247]
|
||||||
|
@ -39,17 +41,17 @@
|
||||||
|
|
||||||
[#247]: https://github.com/actix/actix-net/pull/247
|
[#247]: https://github.com/actix/actix-net/pull/247
|
||||||
|
|
||||||
## 2.0.0-beta.3 - 2021-01-09
|
## 2.0.0-beta.3
|
||||||
|
|
||||||
- The `forward_ready!` macro converts errors. [#246]
|
- The `forward_ready!` macro converts errors. [#246]
|
||||||
|
|
||||||
[#246]: https://github.com/actix/actix-net/pull/246
|
[#246]: https://github.com/actix/actix-net/pull/246
|
||||||
|
|
||||||
## 2.0.0-beta.2 - 2021-01-03
|
## 2.0.0-beta.2
|
||||||
|
|
||||||
- Remove redundant type parameter from `map_config`.
|
- Remove redundant type parameter from `map_config`.
|
||||||
|
|
||||||
## 2.0.0-beta.1 - 2020-12-28
|
## 2.0.0-beta.1
|
||||||
|
|
||||||
- `Service`, other traits, and many type signatures now take the the request type as a type parameter instead of an associated type. [#232]
|
- `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]
|
- Add `always_ready!` and `forward_ready!` macros. [#233]
|
||||||
|
@ -62,82 +64,82 @@
|
||||||
[#233]: https://github.com/actix/actix-net/pull/233
|
[#233]: https://github.com/actix/actix-net/pull/233
|
||||||
[#235]: https://github.com/actix/actix-net/pull/235
|
[#235]: https://github.com/actix/actix-net/pull/235
|
||||||
|
|
||||||
## 1.0.6 - 2020-08-09
|
## 1.0.6
|
||||||
|
|
||||||
- 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.
|
- 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
|
## 1.0.5
|
||||||
|
|
||||||
- Fixed unsoundness in .and_then()/.then() service combinators.
|
- Fixed unsoundness in .and_then()/.then() service combinators.
|
||||||
|
|
||||||
## 1.0.4 - 2020-01-15
|
## 1.0.4
|
||||||
|
|
||||||
- Revert 1.0.3 change
|
- Revert 1.0.3 change
|
||||||
|
|
||||||
## 1.0.3 - 2020-01-15
|
## 1.0.3
|
||||||
|
|
||||||
- Fixed unsoundness in `AndThenService` impl.
|
- Fixed unsoundness in `AndThenService` impl.
|
||||||
|
|
||||||
## 1.0.2 - 2020-01-08
|
## 1.0.2
|
||||||
|
|
||||||
- Add `into_service` helper function.
|
- Add `into_service` helper function.
|
||||||
|
|
||||||
## 1.0.1 - 2019-12-22
|
## 1.0.1
|
||||||
|
|
||||||
- `map_config()` and `unit_config()` now accept `IntoServiceFactory` type.
|
- `map_config()` and `unit_config()` now accept `IntoServiceFactory` type.
|
||||||
|
|
||||||
## 1.0.0 - 2019-12-11
|
## 1.0.0
|
||||||
|
|
||||||
- Add Clone impl for Apply service
|
- Add Clone impl for Apply service
|
||||||
|
|
||||||
## 1.0.0-alpha.4 - 2019-12-08
|
## 1.0.0-alpha.4
|
||||||
|
|
||||||
- Renamed `service_fn` to `fn_service`
|
- Renamed `service_fn` to `fn_service`
|
||||||
- Renamed `factory_fn` to `fn_factory`
|
- Renamed `factory_fn` to `fn_factory`
|
||||||
- Renamed `factory_fn_cfg` to `fn_factory_with_config`
|
- Renamed `factory_fn_cfg` to `fn_factory_with_config`
|
||||||
|
|
||||||
## 1.0.0-alpha.3 - 2019-12-06
|
## 1.0.0-alpha.3
|
||||||
|
|
||||||
- Add missing Clone impls
|
- Add missing Clone impls
|
||||||
- Restore `Transform::map_init_err()` combinator
|
- Restore `Transform::map_init_err()` combinator
|
||||||
- Restore `Service/Factory::apply_fn()` in form of `Pipeline/Factory::and_then_apply_fn()`
|
- Restore `Service/Factory::apply_fn()` in form of `Pipeline/Factory::and_then_apply_fn()`
|
||||||
- Optimize service combinators and futures memory layout
|
- Optimize service combinators and futures memory layout
|
||||||
|
|
||||||
## 1.0.0-alpha.2 - 2019-12-02
|
## 1.0.0-alpha.2
|
||||||
|
|
||||||
- Use owned config value for service factory
|
- Use owned config value for service factory
|
||||||
- Renamed BoxedNewService/BoxedService to BoxServiceFactory/BoxService
|
- Renamed BoxedNewService/BoxedService to BoxServiceFactory/BoxService
|
||||||
|
|
||||||
## 1.0.0-alpha.1 - 2019-11-25
|
## 1.0.0-alpha.1
|
||||||
|
|
||||||
- Migrated to `std::future`
|
- Migrated to `std::future`
|
||||||
- `NewService` renamed to `ServiceFactory`
|
- `NewService` renamed to `ServiceFactory`
|
||||||
- Added `pipeline` and `pipeline_factory` function
|
- Added `pipeline` and `pipeline_factory` function
|
||||||
|
|
||||||
## 0.4.2 - 2019-08-27
|
## 0.4.2
|
||||||
|
|
||||||
- Check service readiness for `new_apply_cfg` combinator
|
- Check service readiness for `new_apply_cfg` combinator
|
||||||
|
|
||||||
## 0.4.1 - 2019-06-06
|
## 0.4.1
|
||||||
|
|
||||||
- Add `new_apply_cfg` function
|
- Add `new_apply_cfg` function
|
||||||
|
|
||||||
## 0.4.0 - 2019-05-12
|
## 0.4.0
|
||||||
|
|
||||||
- Add `NewService::map_config` and `NewService::unit_config` combinators.
|
- Add `NewService::map_config` and `NewService::unit_config` combinators.
|
||||||
- Use associated type for `NewService` config.
|
- Use associated type for `NewService` config.
|
||||||
- Change `apply_cfg` function.
|
- Change `apply_cfg` function.
|
||||||
- Renamed helper functions.
|
- Renamed helper functions.
|
||||||
|
|
||||||
## 0.3.6 - 2019-04-07
|
## 0.3.6
|
||||||
|
|
||||||
- Poll boxed service call result immediately
|
- Poll boxed service call result immediately
|
||||||
|
|
||||||
## 0.3.5 - 2019-03-29
|
## 0.3.5
|
||||||
|
|
||||||
- Add `impl<S: Service> Service for Rc<RefCell<S>>`.
|
- Add `impl<S: Service> Service for Rc<RefCell<S>>`.
|
||||||
|
|
||||||
## 0.3.4 - 2019-03-12
|
## 0.3.4
|
||||||
|
|
||||||
- Add `Transform::from_err()` combinator
|
- Add `Transform::from_err()` combinator
|
||||||
- Add `apply_fn` helper
|
- Add `apply_fn` helper
|
||||||
|
@ -145,37 +147,37 @@
|
||||||
- Add `apply_transform` helper
|
- Add `apply_transform` helper
|
||||||
- Add `apply_cfg` helper
|
- Add `apply_cfg` helper
|
||||||
|
|
||||||
## 0.3.3 - 2019-03-09
|
## 0.3.3
|
||||||
|
|
||||||
- Add `ApplyTransform` new service for transform and new service.
|
- Add `ApplyTransform` new service for transform and new service.
|
||||||
- Add `NewService::apply_cfg()` combinator, allows to use nested `NewService` with different config parameter.
|
- Add `NewService::apply_cfg()` combinator, allows to use nested `NewService` with different config parameter.
|
||||||
- Revert IntoFuture change
|
- Revert IntoFuture change
|
||||||
|
|
||||||
## 0.3.2 - 2019-03-04
|
## 0.3.2
|
||||||
|
|
||||||
- Change `NewService::Future` and `Transform::Future` to the `IntoFuture` trait.
|
- Change `NewService::Future` and `Transform::Future` to the `IntoFuture` trait.
|
||||||
- Export `AndThenTransform` type
|
- Export `AndThenTransform` type
|
||||||
|
|
||||||
## 0.3.1 - 2019-03-04
|
## 0.3.1
|
||||||
|
|
||||||
- Simplify Transform trait
|
- Simplify Transform trait
|
||||||
|
|
||||||
## 0.3.0 - 2019-03-02
|
## 0.3.0
|
||||||
|
|
||||||
- Added boxed NewService and Service.
|
- Added boxed NewService and Service.
|
||||||
- Added `Config` parameter to `NewService` trait.
|
- Added `Config` parameter to `NewService` trait.
|
||||||
- Added `Config` parameter to `NewTransform` trait.
|
- Added `Config` parameter to `NewTransform` trait.
|
||||||
|
|
||||||
## 0.2.2 - 2019-02-19
|
## 0.2.2
|
||||||
|
|
||||||
- Added `NewService` impl for `Rc<S> where S: NewService`
|
- Added `NewService` impl for `Rc<S> where S: NewService`
|
||||||
- Added `NewService` impl for `Arc<S> where S: NewService`
|
- Added `NewService` impl for `Arc<S> where S: NewService`
|
||||||
|
|
||||||
## 0.2.1 - 2019-02-03
|
## 0.2.1
|
||||||
|
|
||||||
- Generalize `.apply` combinator with Transform trait
|
- Generalize `.apply` combinator with Transform trait
|
||||||
|
|
||||||
## 0.2.0 - 2019-02-01
|
## 0.2.0
|
||||||
|
|
||||||
- Use associated type instead of generic for Service definition.
|
- Use associated type instead of generic for Service definition.
|
||||||
- Before:
|
- Before:
|
||||||
|
@ -194,31 +196,31 @@
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 0.1.6 - 2019-01-24
|
## 0.1.6
|
||||||
|
|
||||||
- Use `FnMut` instead of `Fn` for .apply() and .map() combinators and `FnService` type
|
- 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>`
|
- Change `.apply()` error semantic, new service's error is `From<Self::Error>`
|
||||||
|
|
||||||
## 0.1.5 - 2019-01-13
|
## 0.1.5
|
||||||
|
|
||||||
- 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
|
## 0.1.4
|
||||||
|
|
||||||
- Use `FnMut` instead of `Fn` for `FnService`
|
- Use `FnMut` instead of `Fn` for `FnService`
|
||||||
|
|
||||||
## 0.1.3 - 2018-12-12
|
## 0.1.3
|
||||||
|
|
||||||
- Split service combinators to separate trait
|
- Split service combinators to separate trait
|
||||||
|
|
||||||
## 0.1.2 - 2018-12-12
|
## 0.1.2
|
||||||
|
|
||||||
- Release future early for `.and_then()` and `.then()` combinators
|
- Release future early for `.and_then()` and `.then()` combinators
|
||||||
|
|
||||||
## 0.1.1 - 2018-12-09
|
## 0.1.1
|
||||||
|
|
||||||
- Added Service impl for `Box<S: Service>`
|
- Added Service impl for `Box<S: Service>`
|
||||||
|
|
||||||
## 0.1.0 - 2018-12-09
|
## 0.1.0
|
||||||
|
|
||||||
- Initial import
|
- Initial import
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-service"
|
name = "actix-service"
|
||||||
version = "2.0.2"
|
version = "2.0.3"
|
||||||
authors = [
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
|
||||||
]
|
|
||||||
description = "Service trait and combinators for representing asynchronous request/response operations."
|
description = "Service trait and combinators for representing asynchronous request/response operations."
|
||||||
keywords = ["network", "framework", "async", "futures", "service"]
|
keywords = ["network", "framework", "async", "futures", "service"]
|
||||||
categories = ["network-programming", "asynchronous", "no-std"]
|
categories = ["network-programming", "asynchronous", "no-std"]
|
||||||
|
@ -15,10 +12,12 @@ rust-version.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures-core = { version = "0.3.17", default-features = false }
|
futures-core = { version = "0.3.17", default-features = false }
|
||||||
paste = "1"
|
|
||||||
pin-project-lite = "0.2"
|
pin-project-lite = "0.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2"
|
actix-rt = "2"
|
||||||
actix-utils = "3"
|
actix-utils = "3"
|
||||||
futures-util = { version = "0.3.17", default-features = false }
|
futures-util = { version = "0.3.17", default-features = false }
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
> Service trait and combinators for representing asynchronous request/response operations.
|
> Service trait and combinators for representing asynchronous request/response operations.
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-service)
|
[](https://crates.io/crates/actix-service)
|
||||||
[](https://docs.rs/actix-service/2.0.2)
|
[](https://docs.rs/actix-service/2.0.3)
|
||||||
[](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
|
[](https://blog.rust-lang.org/2020/03/12/Rust-1.46.html)
|
||||||

|

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

|

|
||||||
[](https://discord.gg/NWpN5mmg3x)
|
[](https://discord.gg/NWpN5mmg3x)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
|
|
||||||
use std::{future::Future, sync::mpsc, time::Duration};
|
use std::{future::Future, sync::mpsc, time::Duration};
|
||||||
|
|
||||||
async fn oracle<F, Fut>(f: F) -> (u32, u32)
|
async fn oracle<F, Fut>(f: F) -> (u32, u32)
|
||||||
|
|
|
@ -208,15 +208,13 @@ where
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use core::task::Poll;
|
|
||||||
|
|
||||||
use futures_util::future::lazy;
|
use futures_util::future::lazy;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
ok,
|
ok,
|
||||||
pipeline::{pipeline, pipeline_factory},
|
pipeline::{pipeline, pipeline_factory},
|
||||||
Ready, Service, ServiceFactory,
|
Ready,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -3,36 +3,38 @@
|
||||||
use alloc::{boxed::Box, rc::Rc};
|
use alloc::{boxed::Box, rc::Rc};
|
||||||
use core::{future::Future, pin::Pin};
|
use core::{future::Future, pin::Pin};
|
||||||
|
|
||||||
use paste::paste;
|
|
||||||
|
|
||||||
use crate::{Service, ServiceFactory};
|
use crate::{Service, ServiceFactory};
|
||||||
|
|
||||||
/// A boxed future with no send bound or lifetime parameters.
|
/// A boxed future with no send bound or lifetime parameters.
|
||||||
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
|
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T>>>;
|
||||||
|
|
||||||
macro_rules! service_object {
|
/// Type alias for service trait object using [`Box`].
|
||||||
($name: ident, $type: tt, $fn_name: ident) => {
|
pub type BoxService<Req, Res, Err> =
|
||||||
paste! {
|
Box<dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>>;
|
||||||
#[doc = "Type alias for service trait object using `" $type "`."]
|
|
||||||
pub type $name<Req, Res, Err> = $type<
|
|
||||||
dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
#[doc = "Wraps service as a trait object using [`" $name "`]."]
|
/// Wraps service as a trait object using [`BoxService`].
|
||||||
pub fn $fn_name<S, Req>(service: S) -> $name<Req, S::Response, S::Error>
|
pub fn service<S, Req>(service: S) -> BoxService<Req, S::Response, S::Error>
|
||||||
where
|
where
|
||||||
S: Service<Req> + 'static,
|
S: Service<Req> + 'static,
|
||||||
Req: 'static,
|
Req: 'static,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
{
|
{
|
||||||
$type::new(ServiceWrapper::new(service))
|
Box::new(ServiceWrapper::new(service))
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
service_object!(BoxService, Box, service);
|
/// Type alias for service trait object using [`Rc`].
|
||||||
service_object!(RcService, Rc, rc_service);
|
pub type RcService<Req, Res, Err> =
|
||||||
|
Rc<dyn Service<Req, Response = Res, Error = Err, Future = BoxFuture<Result<Res, Err>>>>;
|
||||||
|
|
||||||
|
/// Wraps service as a trait object using [`RcService`].
|
||||||
|
pub fn rc_service<S, Req>(service: S) -> RcService<Req, S::Response, S::Error>
|
||||||
|
where
|
||||||
|
S: Service<Req> + 'static,
|
||||||
|
Req: 'static,
|
||||||
|
S::Future: 'static,
|
||||||
|
{
|
||||||
|
Rc::new(ServiceWrapper::new(service))
|
||||||
|
}
|
||||||
|
|
||||||
struct ServiceWrapper<S> {
|
struct ServiceWrapper<S> {
|
||||||
inner: S,
|
inner: S,
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub trait ServiceExt<Req>: Service<Req> {
|
||||||
/// Call another service after call to this one has resolved successfully.
|
/// Call another service after call to this one has resolved successfully.
|
||||||
///
|
///
|
||||||
/// This function can be used to chain two services together and ensure that the second service
|
/// This function can be used to chain two services together and ensure that the second service
|
||||||
/// isn't called until call to the fist service have finished. Result of the call to the first
|
/// isn't called until call to the first service have finished. Result of the call to the first
|
||||||
/// service is used as an input parameter for the second service's call.
|
/// service is used as an input parameter for the second service's call.
|
||||||
///
|
///
|
||||||
/// Note that this function consumes the receiving service and returns a wrapped version of it.
|
/// Note that this function consumes the receiving service and returns a wrapped version of it.
|
||||||
|
|
|
@ -351,7 +351,6 @@ mod tests {
|
||||||
use futures_util::future::lazy;
|
use futures_util::future::lazy;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{ok, Service, ServiceFactory};
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_fn_service() {
|
async fn test_fn_service() {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
//! See [`Service`] docs for information on this crate's foundational trait.
|
//! See [`Service`] docs for information on this crate's foundational trait.
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
||||||
#![warn(future_incompatible, missing_docs)]
|
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
|
|
@ -202,9 +202,7 @@ mod tests {
|
||||||
use futures_util::future::lazy;
|
use futures_util::future::lazy;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{ok, IntoServiceFactory, Ready, ServiceExt, ServiceFactoryExt};
|
||||||
ok, IntoServiceFactory, Ready, Service, ServiceExt, ServiceFactory, ServiceFactoryExt,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Srv;
|
struct Srv;
|
||||||
|
|
||||||
|
|
|
@ -205,9 +205,7 @@ mod tests {
|
||||||
use futures_util::future::lazy;
|
use futures_util::future::lazy;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{err, ok, IntoServiceFactory, Ready, ServiceExt, ServiceFactoryExt};
|
||||||
err, ok, IntoServiceFactory, Ready, Service, ServiceExt, ServiceFactory, ServiceFactoryExt,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Srv;
|
struct Srv;
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ where
|
||||||
/// Call another service after call to this one has resolved successfully.
|
/// Call another service after call to this one has resolved successfully.
|
||||||
///
|
///
|
||||||
/// This function can be used to chain two services together and ensure that
|
/// This function can be used to chain two services together and ensure that
|
||||||
/// the second service isn't called until call to the fist service have
|
/// the second service isn't called until call to the first service have
|
||||||
/// finished. Result of the call to the first service is used as an
|
/// finished. Result of the call to the first service is used as an
|
||||||
/// input parameter for the second service's call.
|
/// input parameter for the second service's call.
|
||||||
///
|
///
|
||||||
|
|
|
@ -226,9 +226,9 @@ mod tests {
|
||||||
use actix_utils::future::{ready, Ready};
|
use actix_utils::future::{ready, Ready};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::Service;
|
|
||||||
|
|
||||||
// pseudo-doctest for Transform trait
|
// pseudo-doctest for Transform trait
|
||||||
|
#[allow(unused)]
|
||||||
pub struct TimeoutTransform {
|
pub struct TimeoutTransform {
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
}
|
}
|
||||||
|
@ -250,6 +250,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
// pseudo-doctest for Transform trait
|
// pseudo-doctest for Transform trait
|
||||||
|
#[allow(unused)]
|
||||||
pub struct Timeout<S> {
|
pub struct Timeout<S> {
|
||||||
service: S,
|
service: S,
|
||||||
_timeout: Duration,
|
_timeout: Duration,
|
||||||
|
|
|
@ -2,9 +2,33 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
|
## 3.4.0
|
||||||
|
|
||||||
|
- Add `rustls-0_23`, `rustls-0_23-webpki-roots`, and `rustls-0_23-native-roots` crate features.
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.70.
|
||||||
|
|
||||||
|
## 3.3.0
|
||||||
|
|
||||||
|
- Add `rustls-0_22` crate feature which excludes any root certificate methods or re-exports.
|
||||||
|
|
||||||
|
## 3.2.0
|
||||||
|
|
||||||
|
- Support Rustls v0.22.
|
||||||
|
- Add `{accept, connect}::rustls_0_22` modules.
|
||||||
|
- Add `rustls-0_21-native-roots` and `rustls-0_20-native-roots` crate features which utilize the `rustls-native-certs` crate to enable a `native_roots_cert_store()` functions in each rustls-based `connect` module.
|
||||||
|
- Implement `Host` for `http::Uri` (`http` crate version `1`).
|
||||||
|
|
||||||
|
## 3.1.1
|
||||||
|
|
||||||
|
- Fix `rustls` v0.21 version requirement.
|
||||||
|
|
||||||
|
## 3.1.0
|
||||||
|
|
||||||
- Support Rustls v0.21.
|
- Support Rustls v0.21.
|
||||||
- Added `{accept, connect}::rustls_0_21` modules.
|
- Add `{accept, connect}::rustls_0_21` modules.
|
||||||
- Added `{accept, connect}::rustls_0_20` alias for `{accept, connect}::rustls` modules.
|
- Add `{accept, connect}::rustls_0_20` alias for `{accept, connect}::rustls` modules.
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 3.0.4
|
## 3.0.4
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-tls"
|
name = "actix-tls"
|
||||||
version = "3.0.4"
|
version = "3.4.0"
|
||||||
authors = [
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
|
||||||
]
|
|
||||||
description = "TLS acceptor and connector services for Actix ecosystem"
|
description = "TLS acceptor and connector services for Actix ecosystem"
|
||||||
keywords = ["network", "tls", "ssl", "async", "transport"]
|
keywords = ["network", "tls", "ssl", "async", "transport"]
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net.git"
|
||||||
|
@ -17,6 +14,15 @@ rust-version.workspace = true
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = ["actix_service::*", "actix_utils::*", "futures_core::*", "tokio::*"]
|
||||||
|
|
||||||
|
[package.metadata.cargo-machete]
|
||||||
|
ignored = [
|
||||||
|
"rustls_021", # specified to force version with add_trust_anchors method
|
||||||
|
"rustls_webpki_0101", # specified to force secure version
|
||||||
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["accept", "connect"]
|
default = ["accept", "connect"]
|
||||||
|
|
||||||
|
@ -27,28 +33,41 @@ accept = []
|
||||||
connect = []
|
connect = []
|
||||||
|
|
||||||
# use openssl impls
|
# use openssl impls
|
||||||
openssl = ["tls-openssl", "tokio-openssl"]
|
openssl = ["dep:tls-openssl", "dep:tokio-openssl"]
|
||||||
|
|
||||||
# alias for backwards compat
|
# alias for backwards compat
|
||||||
rustls = ["rustls-0_20"]
|
rustls = ["rustls-0_20"]
|
||||||
|
|
||||||
# use rustls v0.20 impls
|
# use rustls v0.20 impls
|
||||||
rustls-0_20 = ["tokio-rustls-023", "webpki-roots-022"]
|
rustls-0_20 = ["rustls-0_20-webpki-roots"]
|
||||||
|
rustls-0_20-webpki-roots = ["tokio-rustls-023", "webpki-roots-022"]
|
||||||
|
rustls-0_20-native-roots = ["tokio-rustls-023", "dep:rustls-native-certs-06"]
|
||||||
|
|
||||||
# use rustls v0.21 impls
|
# use rustls v0.21 impls
|
||||||
rustls-0_21 = ["tokio-rustls-024", "webpki-roots-025"]
|
rustls-0_21 = ["rustls-0_21-webpki-roots"]
|
||||||
|
rustls-0_21-webpki-roots = ["tokio-rustls-024", "webpki-roots-025"]
|
||||||
|
rustls-0_21-native-roots = ["tokio-rustls-024", "dep:rustls-native-certs-06"]
|
||||||
|
|
||||||
|
# use rustls v0.22 impls
|
||||||
|
rustls-0_22 = ["dep:tokio-rustls-025", "dep:rustls-pki-types-1"]
|
||||||
|
rustls-0_22-webpki-roots = ["rustls-0_22", "dep:webpki-roots-026"]
|
||||||
|
rustls-0_22-native-roots = ["rustls-0_22", "dep:rustls-native-certs-07"]
|
||||||
|
|
||||||
|
# use rustls v0.23 impls
|
||||||
|
rustls-0_23 = ["dep:tokio-rustls-026", "dep:rustls-pki-types-1"]
|
||||||
|
rustls-0_23-webpki-roots = ["rustls-0_23", "dep:webpki-roots-026"]
|
||||||
|
rustls-0_23-native-roots = ["rustls-0_23", "dep:rustls-native-certs-07"]
|
||||||
|
|
||||||
# use native-tls impls
|
# use native-tls impls
|
||||||
native-tls = ["tokio-native-tls"]
|
native-tls = ["dep:tokio-native-tls"]
|
||||||
|
|
||||||
# support http::Uri as connect address
|
# support http::Uri as connect address
|
||||||
uri = ["http"]
|
uri = ["dep:http-0_2", "dep:http-1"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = { version = "2.2", default-features = false }
|
actix-rt = { version = "2.2", default-features = false }
|
||||||
actix-service = "2"
|
actix-service = "2"
|
||||||
actix-utils = "3"
|
actix-utils = "3"
|
||||||
|
|
||||||
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||||
impl-more = "0.1"
|
impl-more = "0.1"
|
||||||
pin-project-lite = "0.2.7"
|
pin-project-lite = "0.2.7"
|
||||||
|
@ -57,36 +76,60 @@ tokio-util = "0.7"
|
||||||
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
tracing = { version = "0.1.30", default-features = false, features = ["log"] }
|
||||||
|
|
||||||
# uri
|
# uri
|
||||||
http = { version = "0.2.3", optional = true }
|
http-0_2 = { package = "http", version = "0.2.3", optional = true }
|
||||||
|
http-1 = { package = "http", version = "1", optional = true }
|
||||||
|
|
||||||
# openssl
|
# openssl
|
||||||
tls-openssl = { package = "openssl", version = "0.10.48", optional = true }
|
tls-openssl = { package = "openssl", version = "0.10.55", optional = true }
|
||||||
tokio-openssl = { version = "0.6", optional = true }
|
tokio-openssl = { version = "0.6", optional = true }
|
||||||
|
|
||||||
|
# rustls PKI types
|
||||||
|
rustls-pki-types-1 = { package = "rustls-pki-types", version = "1", optional = true }
|
||||||
|
|
||||||
# rustls v0.20
|
# rustls v0.20
|
||||||
tokio-rustls-023 = { package = "tokio-rustls", version = "0.23", optional = true }
|
tokio-rustls-023 = { package = "tokio-rustls", version = "0.23", optional = true }
|
||||||
webpki-roots-022 = { package = "webpki-roots", version = "0.22", optional = true }
|
|
||||||
|
|
||||||
# rustls v0.21
|
# rustls v0.21
|
||||||
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", optional = true }
|
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", optional = true }
|
||||||
|
|
||||||
|
# rustls v0.22
|
||||||
|
tokio-rustls-025 = { package = "tokio-rustls", version = "0.25", optional = true }
|
||||||
|
|
||||||
|
# rustls v0.23
|
||||||
|
tokio-rustls-026 = { package = "tokio-rustls", version = "0.26", default-features = false, optional = true }
|
||||||
|
|
||||||
|
# webpki-roots used with rustls features
|
||||||
|
webpki-roots-022 = { package = "webpki-roots", version = "0.22", optional = true }
|
||||||
webpki-roots-025 = { package = "webpki-roots", version = "0.25", optional = true }
|
webpki-roots-025 = { package = "webpki-roots", version = "0.25", optional = true }
|
||||||
|
webpki-roots-026 = { package = "webpki-roots", version = "0.26", optional = true }
|
||||||
|
|
||||||
|
# native root certificates for rustls impls
|
||||||
|
rustls-native-certs-06 = { package = "rustls-native-certs", version = "0.6", optional = true }
|
||||||
|
rustls-native-certs-07 = { package = "rustls-native-certs", version = "0.7", optional = true }
|
||||||
|
|
||||||
# native-tls
|
# native-tls
|
||||||
tokio-native-tls = { version = "0.3", optional = true }
|
tokio-native-tls = { version = "0.3", optional = true }
|
||||||
|
|
||||||
|
[target.'cfg(any())'.dependencies]
|
||||||
|
rustls-021 = { package = "rustls", version = "0.21.6", optional = true } # force version with add_trust_anchors method
|
||||||
|
rustls-webpki-0101 = { package = "rustls-webpki", version = "0.101.4", optional = true } # force secure version
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-codec = "0.5"
|
actix-codec = "0.5"
|
||||||
actix-rt = "2.2"
|
actix-rt = "2.2"
|
||||||
actix-server = "2"
|
actix-server = "2"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
env_logger = "0.10"
|
|
||||||
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
|
futures-util = { version = "0.3.17", default-features = false, features = ["sink"] }
|
||||||
log = "0.4"
|
itertools = "0.14"
|
||||||
rcgen = "0.11"
|
pretty_env_logger = "0.5"
|
||||||
rustls-pemfile = "1"
|
rcgen = "0.13"
|
||||||
tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", features = ["dangerous_configuration"] }
|
rustls-pemfile = "2"
|
||||||
|
tokio-rustls-026 = { package = "tokio-rustls", version = "0.26" }
|
||||||
trust-dns-resolver = "0.23"
|
trust-dns-resolver = "0.23"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "accept-rustls"
|
name = "accept-rustls"
|
||||||
required-features = ["accept", "rustls-0_21"]
|
required-features = ["accept", "rustls-0_23"]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
# `actix-tls`
|
||||||
|
|
||||||
|
> TLS acceptor and connector services for the Actix ecosystem.
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
|
||||||
|
[](https://crates.io/crates/actix-tls)
|
||||||
|
[](https://docs.rs/actix-tls/3.4.0)
|
||||||
|
[](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
||||||
|

|
||||||
|
<br />
|
||||||
|
[](https://deps.rs/crate/actix-tls/3.4.0)
|
||||||
|

|
||||||
|
[](https://discord.gg/NWpN5mmg3x)
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Library Documentation](https://docs.rs/actix-tls)
|
||||||
|
- [Examples](/actix-tls/examples)
|
|
@ -15,11 +15,8 @@
|
||||||
//! http --verify=false https://127.0.0.1:8443
|
//! http --verify=false https://127.0.0.1:8443
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
// this `use` is only exists because of how we have organised the crate
|
// 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` normally
|
// it is not necessary for your actual code; you should import from `rustls` normally
|
||||||
use tokio_rustls_024::rustls;
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{self, BufReader},
|
io::{self, BufReader},
|
||||||
|
@ -33,15 +30,19 @@ use std::{
|
||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use actix_server::Server;
|
use actix_server::Server;
|
||||||
use actix_service::ServiceFactoryExt as _;
|
use actix_service::ServiceFactoryExt as _;
|
||||||
use actix_tls::accept::rustls_0_21::{Acceptor as RustlsAcceptor, TlsStream};
|
use actix_tls::accept::rustls_0_23::{Acceptor as RustlsAcceptor, TlsStream};
|
||||||
use futures_util::future::ok;
|
use futures_util::future::ok;
|
||||||
use rustls::{server::ServerConfig, Certificate, PrivateKey};
|
use itertools::Itertools as _;
|
||||||
|
use rustls::server::ServerConfig;
|
||||||
use rustls_pemfile::{certs, rsa_private_keys};
|
use rustls_pemfile::{certs, rsa_private_keys};
|
||||||
|
use rustls_pki_types_1::PrivateKeyDer;
|
||||||
|
use tokio_rustls_026::rustls;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> io::Result<()> {
|
async fn main() -> io::Result<()> {
|
||||||
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
|
pretty_env_logger::formatted_timed_builder()
|
||||||
|
.parse_env(pretty_env_logger::env_logger::Env::default().default_filter_or("info"));
|
||||||
|
|
||||||
let root_path = env!("CARGO_MANIFEST_DIR")
|
let root_path = env!("CARGO_MANIFEST_DIR")
|
||||||
.parse::<PathBuf>()
|
.parse::<PathBuf>()
|
||||||
|
@ -54,17 +55,15 @@ async fn main() -> io::Result<()> {
|
||||||
let cert_file = &mut BufReader::new(File::open(cert_path).unwrap());
|
let cert_file = &mut BufReader::new(File::open(cert_path).unwrap());
|
||||||
let key_file = &mut BufReader::new(File::open(key_path).unwrap());
|
let key_file = &mut BufReader::new(File::open(key_path).unwrap());
|
||||||
|
|
||||||
let cert_chain = certs(cert_file)
|
let cert_chain = certs(cert_file);
|
||||||
.unwrap()
|
let mut keys = rsa_private_keys(key_file);
|
||||||
.into_iter()
|
|
||||||
.map(Certificate)
|
|
||||||
.collect();
|
|
||||||
let mut keys = rsa_private_keys(key_file).unwrap();
|
|
||||||
|
|
||||||
let tls_config = ServerConfig::builder()
|
let tls_config = ServerConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_no_client_auth()
|
.with_no_client_auth()
|
||||||
.with_single_cert(cert_chain, PrivateKey(keys.remove(0)))
|
.with_single_cert(
|
||||||
|
cert_chain.try_collect::<_, Vec<_>, _>()?,
|
||||||
|
PrivateKeyDer::Pkcs1(keys.next().unwrap()?),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let tls_acceptor = RustlsAcceptor::new(tls_config);
|
let tls_acceptor = RustlsAcceptor::new(tls_config);
|
||||||
|
|
|
@ -22,6 +22,12 @@ pub use rustls_0_20 as rustls;
|
||||||
#[cfg(feature = "rustls-0_21")]
|
#[cfg(feature = "rustls-0_21")]
|
||||||
pub mod rustls_0_21;
|
pub mod rustls_0_21;
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-0_22")]
|
||||||
|
pub mod rustls_0_22;
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-0_23")]
|
||||||
|
pub mod rustls_0_23;
|
||||||
|
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
pub mod native_tls;
|
pub mod native_tls;
|
||||||
|
|
||||||
|
@ -31,6 +37,8 @@ pub(crate) static MAX_CONN: AtomicUsize = AtomicUsize::new(256);
|
||||||
feature = "openssl",
|
feature = "openssl",
|
||||||
feature = "rustls-0_20",
|
feature = "rustls-0_20",
|
||||||
feature = "rustls-0_21",
|
feature = "rustls-0_21",
|
||||||
|
feature = "rustls-0_22",
|
||||||
|
feature = "rustls-0_23",
|
||||||
feature = "native-tls",
|
feature = "native-tls",
|
||||||
))]
|
))]
|
||||||
pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
|
pub(crate) const DEFAULT_TLS_HANDSHAKE_TIMEOUT: std::time::Duration =
|
||||||
|
|
|
@ -23,7 +23,7 @@ use actix_utils::{
|
||||||
};
|
};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
|
use tokio_rustls::{Accept, TlsAcceptor};
|
||||||
use tokio_rustls_023 as tokio_rustls;
|
use tokio_rustls_023 as tokio_rustls;
|
||||||
|
|
||||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||||
|
@ -92,13 +92,13 @@ impl<IO: ActixStream> ActixStream for TlsStream<IO> {
|
||||||
|
|
||||||
/// Accept TLS connections via the `rustls` crate.
|
/// Accept TLS connections via the `rustls` crate.
|
||||||
pub struct Acceptor {
|
pub struct Acceptor {
|
||||||
config: Arc<ServerConfig>,
|
config: Arc<reexports::ServerConfig>,
|
||||||
handshake_timeout: Duration,
|
handshake_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Acceptor {
|
impl Acceptor {
|
||||||
/// Constructs `rustls` based acceptor service factory.
|
/// Constructs `rustls` based acceptor service factory.
|
||||||
pub fn new(config: ServerConfig) -> Self {
|
pub fn new(config: reexports::ServerConfig) -> Self {
|
||||||
Acceptor {
|
Acceptor {
|
||||||
config: Arc::new(config),
|
config: Arc::new(config),
|
||||||
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
||||||
|
|
|
@ -23,7 +23,7 @@ use actix_utils::{
|
||||||
};
|
};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio_rustls::{rustls::ServerConfig, Accept, TlsAcceptor};
|
use tokio_rustls::{Accept, TlsAcceptor};
|
||||||
use tokio_rustls_024 as tokio_rustls;
|
use tokio_rustls_024 as tokio_rustls;
|
||||||
|
|
||||||
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||||
|
@ -92,13 +92,13 @@ impl<IO: ActixStream> ActixStream for TlsStream<IO> {
|
||||||
|
|
||||||
/// Accept TLS connections via the `rustls` crate.
|
/// Accept TLS connections via the `rustls` crate.
|
||||||
pub struct Acceptor {
|
pub struct Acceptor {
|
||||||
config: Arc<ServerConfig>,
|
config: Arc<reexports::ServerConfig>,
|
||||||
handshake_timeout: Duration,
|
handshake_timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Acceptor {
|
impl Acceptor {
|
||||||
/// Constructs `rustls` based acceptor service factory.
|
/// Constructs `rustls` based acceptor service factory.
|
||||||
pub fn new(config: ServerConfig) -> Self {
|
pub fn new(config: reexports::ServerConfig) -> Self {
|
||||||
Acceptor {
|
Acceptor {
|
||||||
config: Arc::new(config),
|
config: Arc::new(config),
|
||||||
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
//! `rustls` v0.22 based TLS connection acceptor service.
|
||||||
|
//!
|
||||||
|
//! See [`Acceptor`] for main service factory docs.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
convert::Infallible,
|
||||||
|
future::Future,
|
||||||
|
io::{self, IoSlice},
|
||||||
|
pin::Pin,
|
||||||
|
sync::Arc,
|
||||||
|
task::{Context, Poll},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use actix_rt::{
|
||||||
|
net::{ActixStream, Ready},
|
||||||
|
time::{sleep, Sleep},
|
||||||
|
};
|
||||||
|
use actix_service::{Service, ServiceFactory};
|
||||||
|
use actix_utils::{
|
||||||
|
counter::{Counter, CounterGuard},
|
||||||
|
future::{ready, Ready as FutReady},
|
||||||
|
};
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
|
use tokio_rustls::{Accept, TlsAcceptor};
|
||||||
|
use tokio_rustls_025 as tokio_rustls;
|
||||||
|
|
||||||
|
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||||
|
|
||||||
|
pub mod reexports {
|
||||||
|
//! Re-exports from `rustls` that are useful for acceptors.
|
||||||
|
|
||||||
|
pub use tokio_rustls_025::rustls::ServerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
|
||||||
|
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>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &mut ReadBuf<'_>,
|
||||||
|
) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
|
||||||
|
fn poll_write(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_flush(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_write_vectored(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
bufs: &[IoSlice<'_>],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_write_vectored(&self) -> bool {
|
||||||
|
(**self).is_write_vectored()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> ActixStream for TlsStream<IO> {
|
||||||
|
fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
|
||||||
|
IO::poll_read_ready((**self).get_ref().0, cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
|
||||||
|
IO::poll_write_ready((**self).get_ref().0, cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accept TLS connections via the `rustls` crate.
|
||||||
|
pub struct Acceptor {
|
||||||
|
config: Arc<reexports::ServerConfig>,
|
||||||
|
handshake_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Acceptor {
|
||||||
|
/// Constructs `rustls` based acceptor service factory.
|
||||||
|
pub fn new(config: reexports::ServerConfig) -> Self {
|
||||||
|
Acceptor {
|
||||||
|
config: Arc::new(config),
|
||||||
|
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
|
||||||
|
///
|
||||||
|
/// Default timeout is 3 seconds.
|
||||||
|
pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
|
||||||
|
self.handshake_timeout = handshake_timeout;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Acceptor {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
config: self.config.clone(),
|
||||||
|
handshake_timeout: self.handshake_timeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
|
||||||
|
type Response = TlsStream<IO>;
|
||||||
|
type Error = TlsError<io::Error, Infallible>;
|
||||||
|
type Config = ();
|
||||||
|
type Service = AcceptorService;
|
||||||
|
type InitError = ();
|
||||||
|
type Future = FutReady<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
let res = MAX_CONN_COUNTER.with(|conns| {
|
||||||
|
Ok(AcceptorService {
|
||||||
|
acceptor: self.config.clone().into(),
|
||||||
|
conns: conns.clone(),
|
||||||
|
handshake_timeout: self.handshake_timeout,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
ready(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rustls based acceptor service.
|
||||||
|
pub struct AcceptorService {
|
||||||
|
acceptor: TlsAcceptor,
|
||||||
|
conns: Counter,
|
||||||
|
handshake_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> Service<IO> for AcceptorService {
|
||||||
|
type Response = TlsStream<IO>;
|
||||||
|
type Error = TlsError<io::Error, Infallible>;
|
||||||
|
type Future = AcceptFut<IO>;
|
||||||
|
|
||||||
|
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
if self.conns.available(cx) {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, req: IO) -> Self::Future {
|
||||||
|
AcceptFut {
|
||||||
|
fut: self.acceptor.accept(req),
|
||||||
|
timeout: sleep(self.handshake_timeout),
|
||||||
|
_guard: self.conns.get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// Accept future for Rustls service.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct AcceptFut<IO: ActixStream> {
|
||||||
|
fut: Accept<IO>,
|
||||||
|
#[pin]
|
||||||
|
timeout: Sleep,
|
||||||
|
_guard: CounterGuard,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> Future for AcceptFut<IO> {
|
||||||
|
type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let mut this = self.project();
|
||||||
|
match Pin::new(&mut this.fut).poll(cx) {
|
||||||
|
Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
|
||||||
|
Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
|
||||||
|
Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
//! `rustls` v0.23 based TLS connection acceptor service.
|
||||||
|
//!
|
||||||
|
//! See [`Acceptor`] for main service factory docs.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
convert::Infallible,
|
||||||
|
future::Future,
|
||||||
|
io::{self, IoSlice},
|
||||||
|
pin::Pin,
|
||||||
|
sync::Arc,
|
||||||
|
task::{Context, Poll},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use actix_rt::{
|
||||||
|
net::{ActixStream, Ready},
|
||||||
|
time::{sleep, Sleep},
|
||||||
|
};
|
||||||
|
use actix_service::{Service, ServiceFactory};
|
||||||
|
use actix_utils::{
|
||||||
|
counter::{Counter, CounterGuard},
|
||||||
|
future::{ready, Ready as FutReady},
|
||||||
|
};
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
|
use tokio_rustls::{Accept, TlsAcceptor};
|
||||||
|
use tokio_rustls_026 as tokio_rustls;
|
||||||
|
|
||||||
|
use super::{TlsError, DEFAULT_TLS_HANDSHAKE_TIMEOUT, MAX_CONN_COUNTER};
|
||||||
|
|
||||||
|
pub mod reexports {
|
||||||
|
//! Re-exports from `rustls` that are useful for acceptors.
|
||||||
|
|
||||||
|
pub use tokio_rustls_026::rustls::ServerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps a `rustls` based async TLS stream in order to implement [`ActixStream`].
|
||||||
|
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>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &mut ReadBuf<'_>,
|
||||||
|
) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_read(cx, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> AsyncWrite for TlsStream<IO> {
|
||||||
|
fn poll_write(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
buf: &[u8],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_write(cx, buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_flush(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_shutdown(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_write_vectored(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context<'_>,
|
||||||
|
bufs: &[IoSlice<'_>],
|
||||||
|
) -> Poll<io::Result<usize>> {
|
||||||
|
Pin::new(&mut **self.get_mut()).poll_write_vectored(cx, bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_write_vectored(&self) -> bool {
|
||||||
|
(**self).is_write_vectored()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> ActixStream for TlsStream<IO> {
|
||||||
|
fn poll_read_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
|
||||||
|
IO::poll_read_ready((**self).get_ref().0, cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_write_ready(&self, cx: &mut Context<'_>) -> Poll<io::Result<Ready>> {
|
||||||
|
IO::poll_write_ready((**self).get_ref().0, cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accept TLS connections via the `rustls` crate.
|
||||||
|
pub struct Acceptor {
|
||||||
|
config: Arc<reexports::ServerConfig>,
|
||||||
|
handshake_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Acceptor {
|
||||||
|
/// Constructs `rustls` based acceptor service factory.
|
||||||
|
pub fn new(config: reexports::ServerConfig) -> Self {
|
||||||
|
Acceptor {
|
||||||
|
config: Arc::new(config),
|
||||||
|
handshake_timeout: DEFAULT_TLS_HANDSHAKE_TIMEOUT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Limit the amount of time that the acceptor will wait for a TLS handshake to complete.
|
||||||
|
///
|
||||||
|
/// Default timeout is 3 seconds.
|
||||||
|
pub fn set_handshake_timeout(&mut self, handshake_timeout: Duration) -> &mut Self {
|
||||||
|
self.handshake_timeout = handshake_timeout;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Acceptor {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
config: self.config.clone(),
|
||||||
|
handshake_timeout: self.handshake_timeout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> ServiceFactory<IO> for Acceptor {
|
||||||
|
type Response = TlsStream<IO>;
|
||||||
|
type Error = TlsError<io::Error, Infallible>;
|
||||||
|
type Config = ();
|
||||||
|
type Service = AcceptorService;
|
||||||
|
type InitError = ();
|
||||||
|
type Future = FutReady<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
let res = MAX_CONN_COUNTER.with(|conns| {
|
||||||
|
Ok(AcceptorService {
|
||||||
|
acceptor: self.config.clone().into(),
|
||||||
|
conns: conns.clone(),
|
||||||
|
handshake_timeout: self.handshake_timeout,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
ready(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rustls based acceptor service.
|
||||||
|
pub struct AcceptorService {
|
||||||
|
acceptor: TlsAcceptor,
|
||||||
|
conns: Counter,
|
||||||
|
handshake_timeout: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> Service<IO> for AcceptorService {
|
||||||
|
type Response = TlsStream<IO>;
|
||||||
|
type Error = TlsError<io::Error, Infallible>;
|
||||||
|
type Future = AcceptFut<IO>;
|
||||||
|
|
||||||
|
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
|
if self.conns.available(cx) {
|
||||||
|
Poll::Ready(Ok(()))
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&self, req: IO) -> Self::Future {
|
||||||
|
AcceptFut {
|
||||||
|
fut: self.acceptor.accept(req),
|
||||||
|
timeout: sleep(self.handshake_timeout),
|
||||||
|
_guard: self.conns.get(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pin_project! {
|
||||||
|
/// Accept future for Rustls service.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct AcceptFut<IO: ActixStream> {
|
||||||
|
fut: Accept<IO>,
|
||||||
|
#[pin]
|
||||||
|
timeout: Sleep,
|
||||||
|
_guard: CounterGuard,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<IO: ActixStream> Future for AcceptFut<IO> {
|
||||||
|
type Output = Result<TlsStream<IO>, TlsError<io::Error, Infallible>>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
let mut this = self.project();
|
||||||
|
match Pin::new(&mut this.fut).poll(cx) {
|
||||||
|
Poll::Ready(Ok(stream)) => Poll::Ready(Ok(TlsStream(stream))),
|
||||||
|
Poll::Ready(Err(err)) => Poll::Ready(Err(TlsError::Tls(err))),
|
||||||
|
Poll::Pending => this.timeout.poll(cx).map(|_| Err(TlsError::Timeout)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -118,6 +118,7 @@ impl<R: Host> ConnectInfo<R> {
|
||||||
/// let mut addrs = conn.addrs();
|
/// let mut addrs = conn.addrs();
|
||||||
/// assert_eq!(addrs.next().unwrap(), addr);
|
/// assert_eq!(addrs.next().unwrap(), addr);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[allow(clippy::implied_bounds_in_impls)]
|
||||||
pub fn addrs(
|
pub fn addrs(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = SocketAddr>
|
) -> impl Iterator<Item = SocketAddr>
|
||||||
|
@ -149,6 +150,7 @@ impl<R: Host> ConnectInfo<R> {
|
||||||
/// let mut addrs = conn.take_addrs();
|
/// let mut addrs = conn.take_addrs();
|
||||||
/// assert_eq!(addrs.next().unwrap(), addr);
|
/// assert_eq!(addrs.next().unwrap(), addr);
|
||||||
/// ```
|
/// ```
|
||||||
|
#[allow(clippy::implied_bounds_in_impls)]
|
||||||
pub fn take_addrs(
|
pub fn take_addrs(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> impl Iterator<Item = SocketAddr>
|
) -> impl Iterator<Item = SocketAddr>
|
||||||
|
|
|
@ -27,16 +27,31 @@ mod uri;
|
||||||
#[cfg(feature = "openssl")]
|
#[cfg(feature = "openssl")]
|
||||||
pub mod openssl;
|
pub mod openssl;
|
||||||
|
|
||||||
#[cfg(feature = "rustls-0_20")]
|
#[cfg(any(
|
||||||
|
feature = "rustls-0_20-webpki-roots",
|
||||||
|
feature = "rustls-0_20-native-roots",
|
||||||
|
))]
|
||||||
pub mod rustls_0_20;
|
pub mod rustls_0_20;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(feature = "rustls-0_20")]
|
#[cfg(any(
|
||||||
|
feature = "rustls-0_20-webpki-roots",
|
||||||
|
feature = "rustls-0_20-native-roots",
|
||||||
|
))]
|
||||||
pub use rustls_0_20 as rustls;
|
pub use rustls_0_20 as rustls;
|
||||||
|
|
||||||
#[cfg(feature = "rustls-0_21")]
|
#[cfg(any(
|
||||||
|
feature = "rustls-0_21-webpki-roots",
|
||||||
|
feature = "rustls-0_21-native-roots",
|
||||||
|
))]
|
||||||
pub mod rustls_0_21;
|
pub mod rustls_0_21;
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-0_22")]
|
||||||
|
pub mod rustls_0_22;
|
||||||
|
|
||||||
|
#[cfg(feature = "rustls-0_23")]
|
||||||
|
pub mod rustls_0_23;
|
||||||
|
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
pub mod native_tls;
|
pub mod native_tls;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
//! See [`TlsConnector`] for main connector service factory docs.
|
//! See [`TlsConnector`] for main connector service factory docs.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
|
||||||
future::Future,
|
future::Future,
|
||||||
io,
|
io,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
|
@ -17,7 +16,7 @@ use actix_utils::future::{ok, Ready};
|
||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
use tokio_rustls::{
|
use tokio_rustls::{
|
||||||
client::TlsStream as AsyncTlsStream,
|
client::TlsStream as AsyncTlsStream,
|
||||||
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
|
rustls::{client::ServerName, ClientConfig, RootCertStore},
|
||||||
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
||||||
};
|
};
|
||||||
use tokio_rustls_023 as tokio_rustls;
|
use tokio_rustls_023 as tokio_rustls;
|
||||||
|
@ -25,17 +24,40 @@ use tokio_rustls_023 as tokio_rustls;
|
||||||
use crate::connect::{Connection, Host};
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
pub mod reexports {
|
pub mod reexports {
|
||||||
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
|
//! Re-exports from the `rustls` v0.20 ecosystem that are useful for connectors.
|
||||||
|
|
||||||
pub use tokio_rustls_023::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
pub use tokio_rustls_023::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
|
#[cfg(feature = "rustls-0_20-webpki-roots")]
|
||||||
pub use webpki_roots_022::TLS_SERVER_ROOTS;
|
pub use webpki_roots_022::TLS_SERVER_ROOTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||||
pub fn webpki_roots_cert_store() -> RootCertStore {
|
///
|
||||||
|
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||||
|
///
|
||||||
|
/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_06::load_native_certs()
|
||||||
|
#[cfg(feature = "rustls-0_20-native-roots")]
|
||||||
|
pub fn native_roots_cert_store() -> io::Result<RootCertStore> {
|
||||||
let mut root_certs = RootCertStore::empty();
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
|
for cert in rustls_native_certs_06::load_native_certs()? {
|
||||||
|
root_certs
|
||||||
|
.add(&tokio_rustls_023::rustls::Certificate(cert.0))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(root_certs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
|
#[cfg(feature = "rustls-0_20-webpki-roots")]
|
||||||
|
pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
|
use tokio_rustls_023::rustls;
|
||||||
|
|
||||||
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
for cert in webpki_roots_022::TLS_SERVER_ROOTS.0 {
|
for cert in webpki_roots_022::TLS_SERVER_ROOTS.0 {
|
||||||
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
|
let cert = rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
cert.subject,
|
cert.subject,
|
||||||
cert.spki,
|
cert.spki,
|
||||||
cert.name_constraints,
|
cert.name_constraints,
|
||||||
|
@ -43,6 +65,7 @@ pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
let certs = vec![cert].into_iter();
|
let certs = vec![cert].into_iter();
|
||||||
root_certs.add_server_trust_anchors(certs);
|
root_certs.add_server_trust_anchors(certs);
|
||||||
}
|
}
|
||||||
|
|
||||||
root_certs
|
root_certs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
//! See [`TlsConnector`] for main connector service factory docs.
|
//! See [`TlsConnector`] for main connector service factory docs.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryFrom,
|
|
||||||
future::Future,
|
future::Future,
|
||||||
io,
|
io,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
|
@ -17,7 +16,7 @@ use actix_utils::future::{ok, Ready};
|
||||||
use futures_core::ready;
|
use futures_core::ready;
|
||||||
use tokio_rustls::{
|
use tokio_rustls::{
|
||||||
client::TlsStream as AsyncTlsStream,
|
client::TlsStream as AsyncTlsStream,
|
||||||
rustls::{client::ServerName, ClientConfig, OwnedTrustAnchor, RootCertStore},
|
rustls::{client::ServerName, ClientConfig, RootCertStore},
|
||||||
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
Connect as RustlsConnect, TlsConnector as RustlsTlsConnector,
|
||||||
};
|
};
|
||||||
use tokio_rustls_024 as tokio_rustls;
|
use tokio_rustls_024 as tokio_rustls;
|
||||||
|
@ -25,17 +24,40 @@ use tokio_rustls_024 as tokio_rustls;
|
||||||
use crate::connect::{Connection, Host};
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
pub mod reexports {
|
pub mod reexports {
|
||||||
//! Re-exports from `rustls` and `webpki_roots` that are useful for connectors.
|
//! Re-exports from the `rustls` v0.21 ecosystem that are useful for connectors.
|
||||||
|
|
||||||
pub use tokio_rustls_024::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
pub use tokio_rustls_024::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
|
#[cfg(feature = "rustls-0_21-webpki-roots")]
|
||||||
pub use webpki_roots_025::TLS_SERVER_ROOTS;
|
pub use webpki_roots_025::TLS_SERVER_ROOTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||||
pub fn webpki_roots_cert_store() -> RootCertStore {
|
///
|
||||||
|
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||||
|
///
|
||||||
|
/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_06::load_native_certs()
|
||||||
|
#[cfg(feature = "rustls-0_21-native-roots")]
|
||||||
|
pub fn native_roots_cert_store() -> io::Result<RootCertStore> {
|
||||||
let mut root_certs = RootCertStore::empty();
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
|
for cert in rustls_native_certs_06::load_native_certs()? {
|
||||||
|
root_certs
|
||||||
|
.add(&tokio_rustls_024::rustls::Certificate(cert.0))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(root_certs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
|
#[cfg(feature = "rustls-0_21-webpki-roots")]
|
||||||
|
pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
|
use tokio_rustls_024::rustls;
|
||||||
|
|
||||||
|
let mut root_certs = RootCertStore::empty();
|
||||||
|
|
||||||
for cert in webpki_roots_025::TLS_SERVER_ROOTS {
|
for cert in webpki_roots_025::TLS_SERVER_ROOTS {
|
||||||
let cert = OwnedTrustAnchor::from_subject_spki_name_constraints(
|
let cert = rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
cert.subject,
|
cert.subject,
|
||||||
cert.spki,
|
cert.spki,
|
||||||
cert.name_constraints,
|
cert.name_constraints,
|
||||||
|
@ -43,6 +65,7 @@ pub fn webpki_roots_cert_store() -> RootCertStore {
|
||||||
let certs = vec![cert].into_iter();
|
let certs = vec![cert].into_iter();
|
||||||
root_certs.add_trust_anchors(certs);
|
root_certs.add_trust_anchors(certs);
|
||||||
}
|
}
|
||||||
|
|
||||||
root_certs
|
root_certs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
//! Rustls based connector service.
|
||||||
|
//!
|
||||||
|
//! See [`TlsConnector`] for main connector service factory docs.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
future::Future,
|
||||||
|
io,
|
||||||
|
pin::Pin,
|
||||||
|
sync::Arc,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
use actix_rt::net::ActixStream;
|
||||||
|
use actix_service::{Service, ServiceFactory};
|
||||||
|
use actix_utils::future::{ok, Ready};
|
||||||
|
use futures_core::ready;
|
||||||
|
use rustls_pki_types_1::ServerName;
|
||||||
|
use tokio_rustls::{
|
||||||
|
client::TlsStream as AsyncTlsStream, rustls::ClientConfig, Connect as RustlsConnect,
|
||||||
|
TlsConnector as RustlsTlsConnector,
|
||||||
|
};
|
||||||
|
use tokio_rustls_025 as tokio_rustls;
|
||||||
|
|
||||||
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
|
pub mod reexports {
|
||||||
|
//! Re-exports from the `rustls` v0.22 ecosystem that are useful for connectors.
|
||||||
|
|
||||||
|
pub use tokio_rustls_025::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
|
#[cfg(feature = "rustls-0_22-webpki-roots")]
|
||||||
|
pub use webpki_roots_026::TLS_SERVER_ROOTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||||
|
///
|
||||||
|
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||||
|
///
|
||||||
|
/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_07::load_native_certs()
|
||||||
|
#[cfg(feature = "rustls-0_22-native-roots")]
|
||||||
|
pub fn native_roots_cert_store() -> io::Result<tokio_rustls::rustls::RootCertStore> {
|
||||||
|
let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
|
||||||
|
|
||||||
|
for cert in rustls_native_certs_07::load_native_certs()? {
|
||||||
|
root_certs.add(cert).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(root_certs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
|
#[cfg(feature = "rustls-0_22-webpki-roots")]
|
||||||
|
pub fn webpki_roots_cert_store() -> tokio_rustls::rustls::RootCertStore {
|
||||||
|
let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
|
||||||
|
root_certs.extend(webpki_roots_026::TLS_SERVER_ROOTS.to_owned());
|
||||||
|
root_certs
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connector service factory using `rustls`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TlsConnector {
|
||||||
|
connector: Arc<ClientConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlsConnector {
|
||||||
|
/// Constructs new connector service factory from a `rustls` client configuration.
|
||||||
|
pub fn new(connector: Arc<ClientConfig>) -> Self {
|
||||||
|
TlsConnector { connector }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs new connector service from a `rustls` client configuration.
|
||||||
|
pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
|
||||||
|
TlsConnectorService { connector }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream + 'static,
|
||||||
|
{
|
||||||
|
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||||
|
type Error = io::Error;
|
||||||
|
type Config = ();
|
||||||
|
type Service = TlsConnectorService;
|
||||||
|
type InitError = ();
|
||||||
|
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
ok(TlsConnectorService {
|
||||||
|
connector: self.connector.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connector service using `rustls`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TlsConnectorService {
|
||||||
|
connector: Arc<ClientConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream,
|
||||||
|
{
|
||||||
|
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||||
|
type Error = io::Error;
|
||||||
|
type Future = ConnectFut<R, IO>;
|
||||||
|
|
||||||
|
actix_service::always_ready!();
|
||||||
|
|
||||||
|
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
||||||
|
tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
|
||||||
|
let (stream, conn) = connection.replace_io(());
|
||||||
|
|
||||||
|
match ServerName::try_from(conn.hostname()) {
|
||||||
|
Ok(host) => ConnectFut::Future {
|
||||||
|
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
|
||||||
|
.connect(host.to_owned(), stream),
|
||||||
|
connection: Some(conn),
|
||||||
|
},
|
||||||
|
Err(_) => ConnectFut::InvalidServerName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect future for Rustls service.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum ConnectFut<R, IO> {
|
||||||
|
InvalidServerName,
|
||||||
|
Future {
|
||||||
|
connect: RustlsConnect<IO>,
|
||||||
|
connection: Option<Connection<R, ()>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> Future for ConnectFut<R, IO>
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream,
|
||||||
|
{
|
||||||
|
type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
match self.get_mut() {
|
||||||
|
Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"connection parameters specified invalid server name",
|
||||||
|
))),
|
||||||
|
|
||||||
|
Self::Future {
|
||||||
|
connect,
|
||||||
|
connection,
|
||||||
|
} => {
|
||||||
|
let stream = ready!(Pin::new(connect).poll(cx))?;
|
||||||
|
let connection = connection.take().unwrap();
|
||||||
|
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
|
||||||
|
Poll::Ready(Ok(connection.replace_io(stream).1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
//! Rustls based connector service.
|
||||||
|
//!
|
||||||
|
//! See [`TlsConnector`] for main connector service factory docs.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
future::Future,
|
||||||
|
io,
|
||||||
|
pin::Pin,
|
||||||
|
sync::Arc,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
|
|
||||||
|
use actix_rt::net::ActixStream;
|
||||||
|
use actix_service::{Service, ServiceFactory};
|
||||||
|
use actix_utils::future::{ok, Ready};
|
||||||
|
use futures_core::ready;
|
||||||
|
use rustls_pki_types_1::ServerName;
|
||||||
|
use tokio_rustls::{
|
||||||
|
client::TlsStream as AsyncTlsStream, rustls::ClientConfig, Connect as RustlsConnect,
|
||||||
|
TlsConnector as RustlsTlsConnector,
|
||||||
|
};
|
||||||
|
use tokio_rustls_026 as tokio_rustls;
|
||||||
|
|
||||||
|
use crate::connect::{Connection, Host};
|
||||||
|
|
||||||
|
pub mod reexports {
|
||||||
|
//! Re-exports from the `rustls` v0.23 ecosystem that are useful for connectors.
|
||||||
|
|
||||||
|
pub use tokio_rustls_026::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||||
|
#[cfg(feature = "rustls-0_23-webpki-roots")]
|
||||||
|
pub use webpki_roots_026::TLS_SERVER_ROOTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||||
|
///
|
||||||
|
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||||
|
///
|
||||||
|
/// [`rustls_native_certs::load_native_certs()`]: rustls_native_certs_07::load_native_certs()
|
||||||
|
#[cfg(feature = "rustls-0_23-native-roots")]
|
||||||
|
pub fn native_roots_cert_store() -> io::Result<tokio_rustls::rustls::RootCertStore> {
|
||||||
|
let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
|
||||||
|
|
||||||
|
for cert in rustls_native_certs_07::load_native_certs()? {
|
||||||
|
root_certs.add(cert).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(root_certs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||||
|
#[cfg(feature = "rustls-0_23-webpki-roots")]
|
||||||
|
pub fn webpki_roots_cert_store() -> tokio_rustls::rustls::RootCertStore {
|
||||||
|
let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
|
||||||
|
root_certs.extend(webpki_roots_026::TLS_SERVER_ROOTS.to_owned());
|
||||||
|
root_certs
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connector service factory using `rustls`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TlsConnector {
|
||||||
|
connector: Arc<ClientConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TlsConnector {
|
||||||
|
/// Constructs new connector service factory from a `rustls` client configuration.
|
||||||
|
pub fn new(connector: Arc<ClientConfig>) -> Self {
|
||||||
|
TlsConnector { connector }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs new connector service from a `rustls` client configuration.
|
||||||
|
pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
|
||||||
|
TlsConnectorService { connector }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream + 'static,
|
||||||
|
{
|
||||||
|
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||||
|
type Error = io::Error;
|
||||||
|
type Config = ();
|
||||||
|
type Service = TlsConnectorService;
|
||||||
|
type InitError = ();
|
||||||
|
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
ok(TlsConnectorService {
|
||||||
|
connector: self.connector.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connector service using `rustls`.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TlsConnectorService {
|
||||||
|
connector: Arc<ClientConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream,
|
||||||
|
{
|
||||||
|
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||||
|
type Error = io::Error;
|
||||||
|
type Future = ConnectFut<R, IO>;
|
||||||
|
|
||||||
|
actix_service::always_ready!();
|
||||||
|
|
||||||
|
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
||||||
|
tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
|
||||||
|
let (stream, conn) = connection.replace_io(());
|
||||||
|
|
||||||
|
match ServerName::try_from(conn.hostname()) {
|
||||||
|
Ok(host) => ConnectFut::Future {
|
||||||
|
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
|
||||||
|
.connect(host.to_owned(), stream),
|
||||||
|
connection: Some(conn),
|
||||||
|
},
|
||||||
|
Err(_) => ConnectFut::InvalidServerName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect future for Rustls service.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub enum ConnectFut<R, IO> {
|
||||||
|
InvalidServerName,
|
||||||
|
Future {
|
||||||
|
connect: RustlsConnect<IO>,
|
||||||
|
connection: Option<Connection<R, ()>>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, IO> Future for ConnectFut<R, IO>
|
||||||
|
where
|
||||||
|
R: Host,
|
||||||
|
IO: ActixStream,
|
||||||
|
{
|
||||||
|
type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
|
match self.get_mut() {
|
||||||
|
Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"connection parameters specified invalid server name",
|
||||||
|
))),
|
||||||
|
|
||||||
|
Self::Future {
|
||||||
|
connect,
|
||||||
|
connection,
|
||||||
|
} => {
|
||||||
|
let stream = ready!(Pin::new(connect).poll(cx))?;
|
||||||
|
let connection = connection.take().unwrap();
|
||||||
|
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
|
||||||
|
Poll::Ready(Ok(connection.replace_io(stream).1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,19 @@
|
||||||
use http::Uri;
|
|
||||||
|
|
||||||
use super::Host;
|
use super::Host;
|
||||||
|
|
||||||
impl Host for Uri {
|
impl Host for http_0_2::Uri {
|
||||||
|
fn hostname(&self) -> &str {
|
||||||
|
self.host().unwrap_or("")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn port(&self) -> Option<u16> {
|
||||||
|
match self.port_u16() {
|
||||||
|
Some(port) => Some(port),
|
||||||
|
None => scheme_to_port(self.scheme_str()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Host for http_1::Uri {
|
||||||
fn hostname(&self) -> &str {
|
fn hostname(&self) -> &str {
|
||||||
self.host().unwrap_or("")
|
self.host().unwrap_or("")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
//! TLS acceptor and connector services for the Actix ecosystem.
|
//! TLS acceptor and connector services for the Actix ecosystem.
|
||||||
|
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
||||||
#![warn(future_incompatible, missing_docs)]
|
|
||||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
|
|
@ -3,27 +3,30 @@
|
||||||
#![cfg(all(
|
#![cfg(all(
|
||||||
feature = "accept",
|
feature = "accept",
|
||||||
feature = "connect",
|
feature = "connect",
|
||||||
feature = "rustls-0_21",
|
feature = "rustls-0_23",
|
||||||
feature = "openssl"
|
feature = "openssl"
|
||||||
))]
|
))]
|
||||||
|
|
||||||
use std::{convert::TryFrom, io::Write, sync::Arc};
|
use std::{io::Write as _, sync::Arc};
|
||||||
|
|
||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use actix_server::TestServer;
|
use actix_server::TestServer;
|
||||||
use actix_service::ServiceFactoryExt as _;
|
use actix_service::ServiceFactoryExt as _;
|
||||||
use actix_tls::accept::openssl::{Acceptor, TlsStream};
|
use actix_tls::{
|
||||||
|
accept::openssl::{Acceptor, TlsStream},
|
||||||
|
connect::rustls_0_23::reexports::ClientConfig,
|
||||||
|
};
|
||||||
use actix_utils::future::ok;
|
use actix_utils::future::ok;
|
||||||
use tokio_rustls::rustls::{Certificate, ClientConfig, RootCertStore, ServerName};
|
use rustls_pki_types_1::ServerName;
|
||||||
use tokio_rustls_024 as tokio_rustls;
|
use tokio_rustls_026::rustls::RootCertStore;
|
||||||
|
|
||||||
fn new_cert_and_key() -> (String, String) {
|
fn new_cert_and_key() -> (String, String) {
|
||||||
let cert =
|
let rcgen::CertifiedKey { cert, key_pair } =
|
||||||
rcgen::generate_simple_self_signed(vec!["127.0.0.1".to_owned(), "localhost".to_owned()])
|
rcgen::generate_simple_self_signed(vec!["127.0.0.1".to_owned(), "localhost".to_owned()])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let key = cert.serialize_private_key_pem();
|
let key = key_pair.serialize_pem();
|
||||||
let cert = cert.serialize_pem().unwrap();
|
let cert = cert.pem();
|
||||||
|
|
||||||
(cert, key)
|
(cert, key)
|
||||||
}
|
}
|
||||||
|
@ -46,30 +49,48 @@ fn openssl_acceptor(cert: String, key: String) -> tls_openssl::ssl::SslAcceptor
|
||||||
builder.build()
|
builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
mod danger {
|
mod danger {
|
||||||
use std::time::SystemTime;
|
use rustls_pki_types_1::{CertificateDer, ServerName, UnixTime};
|
||||||
|
use tokio_rustls_026::rustls;
|
||||||
use tokio_rustls_024::rustls::{
|
|
||||||
self,
|
|
||||||
client::{ServerCertVerified, ServerCertVerifier},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
|
/// Disables certificate verification to allow self-signed certs from rcgen.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct NoCertificateVerification;
|
pub struct NoCertificateVerification;
|
||||||
|
|
||||||
impl ServerCertVerifier for NoCertificateVerification {
|
impl rustls::client::danger::ServerCertVerifier for NoCertificateVerification {
|
||||||
fn verify_server_cert(
|
fn verify_server_cert(
|
||||||
&self,
|
&self,
|
||||||
_end_entity: &Certificate,
|
_end_entity: &CertificateDer<'_>,
|
||||||
_intermediates: &[Certificate],
|
_intermediates: &[CertificateDer<'_>],
|
||||||
_server_name: &ServerName,
|
_server_name: &ServerName<'_>,
|
||||||
_scts: &mut dyn Iterator<Item = &[u8]>,
|
_ocsp: &[u8],
|
||||||
_ocsp_response: &[u8],
|
_now: UnixTime,
|
||||||
_now: SystemTime,
|
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
|
||||||
) -> Result<ServerCertVerified, rustls::Error> {
|
Ok(rustls::client::danger::ServerCertVerified::assertion())
|
||||||
Ok(ServerCertVerified::assertion())
|
}
|
||||||
|
|
||||||
|
fn verify_tls12_signature(
|
||||||
|
&self,
|
||||||
|
_message: &[u8],
|
||||||
|
_cert: &rustls_pki_types_1::CertificateDer<'_>,
|
||||||
|
_dss: &rustls::DigitallySignedStruct,
|
||||||
|
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||||
|
Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn verify_tls13_signature(
|
||||||
|
&self,
|
||||||
|
_message: &[u8],
|
||||||
|
_cert: &rustls_pki_types_1::CertificateDer<'_>,
|
||||||
|
_dss: &rustls::DigitallySignedStruct,
|
||||||
|
) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
|
||||||
|
Ok(rustls::client::danger::HandshakeSignatureValid::assertion())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
|
||||||
|
rustls::crypto::aws_lc_rs::default_provider()
|
||||||
|
.signature_verification_algorithms
|
||||||
|
.supported_schemes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +98,6 @@ mod danger {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
|
fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
|
||||||
let mut config = ClientConfig::builder()
|
let mut config = ClientConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_root_certificates(RootCertStore::empty())
|
.with_root_certificates(RootCertStore::empty())
|
||||||
.with_no_client_auth();
|
.with_no_client_auth();
|
||||||
|
|
||||||
|
@ -91,6 +111,10 @@ fn rustls_connector(_cert: String, _key: String) -> ClientConfig {
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn accepts_connections() {
|
async fn accepts_connections() {
|
||||||
|
tokio_rustls_026::rustls::crypto::aws_lc_rs::default_provider()
|
||||||
|
.install_default()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let (cert, key) = new_cert_and_key();
|
let (cert, key) = new_cert_and_key();
|
||||||
|
|
||||||
let srv = TestServer::start({
|
let srv = TestServer::start({
|
||||||
|
@ -117,13 +141,13 @@ async fn accepts_connections() {
|
||||||
let config = rustls_connector(cert, key);
|
let config = rustls_connector(cert, key);
|
||||||
let config = Arc::new(config);
|
let config = Arc::new(config);
|
||||||
|
|
||||||
let mut conn = tokio_rustls::rustls::ClientConnection::new(
|
let mut conn = tokio_rustls_026::rustls::ClientConnection::new(
|
||||||
config,
|
config,
|
||||||
ServerName::try_from("localhost").unwrap(),
|
ServerName::try_from("localhost").unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut stream = tokio_rustls::rustls::Stream::new(&mut conn, &mut sock);
|
let mut stream = tokio_rustls_026::rustls::Stream::new(&mut conn, &mut sock);
|
||||||
|
|
||||||
stream.flush().expect("TLS handshake failed");
|
stream.flush().expect("TLS handshake failed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#![cfg(all(
|
#![cfg(all(
|
||||||
feature = "accept",
|
feature = "accept",
|
||||||
feature = "connect",
|
feature = "connect",
|
||||||
feature = "rustls-0_21",
|
feature = "rustls-0_23",
|
||||||
feature = "openssl"
|
feature = "openssl"
|
||||||
))]
|
))]
|
||||||
|
|
||||||
|
@ -15,39 +15,39 @@ use actix_rt::net::TcpStream;
|
||||||
use actix_server::TestServer;
|
use actix_server::TestServer;
|
||||||
use actix_service::ServiceFactoryExt as _;
|
use actix_service::ServiceFactoryExt as _;
|
||||||
use actix_tls::{
|
use actix_tls::{
|
||||||
accept::rustls_0_21::{Acceptor, TlsStream},
|
accept::rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream},
|
||||||
connect::openssl::reexports::SslConnector,
|
connect::openssl::reexports::SslConnector,
|
||||||
};
|
};
|
||||||
use actix_utils::future::ok;
|
use actix_utils::future::ok;
|
||||||
use rustls_pemfile::{certs, pkcs8_private_keys};
|
use rustls_pemfile::{certs, pkcs8_private_keys};
|
||||||
|
use rustls_pki_types_1::PrivateKeyDer;
|
||||||
use tls_openssl::ssl::SslVerifyMode;
|
use tls_openssl::ssl::SslVerifyMode;
|
||||||
use tokio_rustls::rustls::{self, Certificate, PrivateKey, ServerConfig};
|
|
||||||
use tokio_rustls_024 as tokio_rustls;
|
|
||||||
|
|
||||||
fn new_cert_and_key() -> (String, String) {
|
fn new_cert_and_key() -> (String, String) {
|
||||||
let cert =
|
let rcgen::CertifiedKey { cert, key_pair } =
|
||||||
rcgen::generate_simple_self_signed(vec!["127.0.0.1".to_owned(), "localhost".to_owned()])
|
rcgen::generate_simple_self_signed(vec!["127.0.0.1".to_owned(), "localhost".to_owned()])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let key = cert.serialize_private_key_pem();
|
let key = key_pair.serialize_pem();
|
||||||
let cert = cert.serialize_pem().unwrap();
|
let cert = cert.pem();
|
||||||
|
|
||||||
(cert, key)
|
(cert, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rustls_server_config(cert: String, key: String) -> rustls::ServerConfig {
|
fn rustls_server_config(cert: String, key: String) -> ServerConfig {
|
||||||
// Load TLS key and cert files
|
// Load TLS key and cert files
|
||||||
|
|
||||||
let cert = &mut BufReader::new(cert.as_bytes());
|
let cert = &mut BufReader::new(cert.as_bytes());
|
||||||
let key = &mut BufReader::new(key.as_bytes());
|
let key = &mut BufReader::new(key.as_bytes());
|
||||||
|
|
||||||
let cert_chain = certs(cert).unwrap().into_iter().map(Certificate).collect();
|
let cert_chain = certs(cert).collect::<Result<Vec<_>, _>>().unwrap();
|
||||||
let mut keys = pkcs8_private_keys(key).unwrap();
|
let mut keys = pkcs8_private_keys(key)
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut config = ServerConfig::builder()
|
let mut config = ServerConfig::builder()
|
||||||
.with_safe_defaults()
|
|
||||||
.with_no_client_auth()
|
.with_no_client_auth()
|
||||||
.with_single_cert(cert_chain, PrivateKey(keys.remove(0)))
|
.with_single_cert(cert_chain, PrivateKeyDer::Pkcs8(keys.remove(0)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
config.alpn_protocols = vec![b"http/1.1".to_vec()];
|
config.alpn_protocols = vec![b"http/1.1".to_vec()];
|
||||||
|
@ -73,6 +73,10 @@ fn openssl_connector(cert: String, key: String) -> SslConnector {
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn accepts_connections() {
|
async fn accepts_connections() {
|
||||||
|
tokio_rustls_026::rustls::crypto::aws_lc_rs::default_provider()
|
||||||
|
.install_default()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let (cert, key) = new_cert_and_key();
|
let (cert, key) = new_cert_and_key();
|
||||||
|
|
||||||
let srv = TestServer::start({
|
let srv = TestServer::start({
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
#![cfg(feature = "connect")]
|
#![cfg(feature = "connect")]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -11,7 +12,7 @@ use actix_server::TestServer;
|
||||||
use actix_service::{fn_service, Service, ServiceFactory};
|
use actix_service::{fn_service, Service, ServiceFactory};
|
||||||
use actix_tls::connect::{ConnectError, ConnectInfo, Connection, Connector, Host};
|
use actix_tls::connect::{ConnectError, ConnectInfo, Connection, Connector, Host};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_util::sink::SinkExt;
|
use futures_util::sink::SinkExt as _;
|
||||||
|
|
||||||
#[cfg(feature = "openssl")]
|
#[cfg(feature = "openssl")]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
|
@ -30,7 +31,7 @@ async fn test_string() {
|
||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "rustls-0_21")]
|
#[cfg(feature = "rustls-0_23")]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_rustls_string() {
|
async fn test_rustls_string() {
|
||||||
let srv = TestServer::start(|| {
|
let srv = TestServer::start(|| {
|
||||||
|
@ -98,8 +99,6 @@ async fn service_factory() {
|
||||||
#[cfg(all(feature = "openssl", feature = "uri"))]
|
#[cfg(all(feature = "openssl", feature = "uri"))]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_openssl_uri() {
|
async fn test_openssl_uri() {
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
let srv = TestServer::start(|| {
|
let srv = TestServer::start(|| {
|
||||||
fn_service(|io: TcpStream| async {
|
fn_service(|io: TcpStream| async {
|
||||||
let mut framed = Framed::new(io, BytesCodec);
|
let mut framed = Framed::new(io, BytesCodec);
|
||||||
|
@ -109,16 +108,14 @@ async fn test_openssl_uri() {
|
||||||
});
|
});
|
||||||
|
|
||||||
let connector = Connector::default().service();
|
let connector = Connector::default().service();
|
||||||
let addr = http::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
let addr = http_0_2::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
||||||
let con = connector.call(addr.into()).await.unwrap();
|
let con = connector.call(addr.into()).await.unwrap();
|
||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "rustls-0_21", feature = "uri"))]
|
#[cfg(all(feature = "rustls-0_23", feature = "uri"))]
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_rustls_uri() {
|
async fn test_rustls_uri_http1() {
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
let srv = TestServer::start(|| {
|
let srv = TestServer::start(|| {
|
||||||
fn_service(|io: TcpStream| async {
|
fn_service(|io: TcpStream| async {
|
||||||
let mut framed = Framed::new(io, BytesCodec);
|
let mut framed = Framed::new(io, BytesCodec);
|
||||||
|
@ -128,7 +125,24 @@ async fn test_rustls_uri() {
|
||||||
});
|
});
|
||||||
|
|
||||||
let conn = Connector::default().service();
|
let conn = Connector::default().service();
|
||||||
let addr = http::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
let addr = http_1::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
||||||
|
let con = conn.call(addr.into()).await.unwrap();
|
||||||
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rustls-0_23", feature = "uri"))]
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_rustls_uri() {
|
||||||
|
let srv = TestServer::start(|| {
|
||||||
|
fn_service(|io: TcpStream| async {
|
||||||
|
let mut framed = Framed::new(io, BytesCodec);
|
||||||
|
framed.send(Bytes::from_static(b"test")).await?;
|
||||||
|
Ok::<_, io::Error>(())
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let conn = Connector::default().service();
|
||||||
|
let addr = http_1::Uri::try_from(format!("https://localhost:{}", srv.port())).unwrap();
|
||||||
let con = conn.call(addr.into()).await.unwrap();
|
let con = conn.call(addr.into()).await.unwrap();
|
||||||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(missing_docs)]
|
||||||
#![cfg(feature = "connect")]
|
#![cfg(feature = "connect")]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
## 0.1.0 - 2020-01-15
|
## 0.1.0
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
|
@ -5,20 +5,25 @@ authors = ["Rajasekharan Vengalil <avranju@gmail.com>"]
|
||||||
description = "Support for tokio tracing with Actix services"
|
description = "Support for tokio tracing with Actix services"
|
||||||
keywords = ["network", "framework", "tracing"]
|
keywords = ["network", "framework", "tracing"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net/tree/master/actix-tracing"
|
||||||
documentation = "https://docs.rs/actix-tracing"
|
documentation = "https://docs.rs/actix-tracing"
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = ["actix_service::*", "actix_utils::*", "tracing::*", "tracing_futures::*"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-service = "2"
|
actix-service = "2"
|
||||||
actix-utils = "3"
|
actix-utils = "3"
|
||||||
|
|
||||||
tracing = "0.1.35"
|
tracing = "0.1.35"
|
||||||
tracing-futures = "0.2"
|
tracing-futures = "0.2"
|
||||||
|
|
||||||
[dev_dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2"
|
actix-rt = "2"
|
||||||
slab = "0.4"
|
slab = "0.4"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
//! Actix tracing - support for tokio tracing with Actix services.
|
//! 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_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
|
||||||
|
@ -22,6 +20,7 @@ pub struct TracingService<S, F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, F> TracingService<S, F> {
|
impl<S, F> TracingService<S, F> {
|
||||||
|
/// Constructs new tracing middleware.
|
||||||
pub fn new(inner: S, make_span: F) -> Self {
|
pub fn new(inner: S, make_span: F) -> Self {
|
||||||
TracingService { inner, make_span }
|
TracingService { inner, make_span }
|
||||||
}
|
}
|
||||||
|
@ -63,6 +62,7 @@ pub struct TracingTransform<S, U, F> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S, U, F> TracingTransform<S, U, F> {
|
impl<S, U, F> TracingTransform<S, U, F> {
|
||||||
|
/// Constructs new tracing middleware.
|
||||||
pub fn new(make_span: F) -> Self {
|
pub fn new(make_span: F) -> Self {
|
||||||
TracingTransform {
|
TracingTransform {
|
||||||
make_span,
|
make_span,
|
||||||
|
@ -131,7 +131,7 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static SPAN: RefCell<Vec<span::Id>> = RefCell::new(Vec::new());
|
static SPAN: RefCell<Vec<span::Id>> = const { RefCell::new(Vec::new()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
## 3.0.1 - 2022-10-21
|
## 3.0.1
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||||
|
|
||||||
## 3.0.0 - 2021-04-16
|
## 3.0.0
|
||||||
|
|
||||||
- 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
|
## 3.0.0-beta.4
|
||||||
|
|
||||||
- Add `future::Either` type. [#305]
|
- Add `future::Either` type. [#305]
|
||||||
|
|
||||||
[#305]: https://github.com/actix/actix-net/pull/305
|
[#305]: https://github.com/actix/actix-net/pull/305
|
||||||
|
|
||||||
## 3.0.0-beta.3 - 2021-04-01
|
## 3.0.0-beta.3
|
||||||
|
|
||||||
- Moved `mpsc` to own crate `local-channel`. [#301]
|
- Moved `mpsc` to own crate `local-channel`. [#301]
|
||||||
- Moved `task::LocalWaker` to own crate `local-waker`. [#301]
|
- Moved `task::LocalWaker` to own crate `local-waker`. [#301]
|
||||||
|
@ -28,13 +28,13 @@
|
||||||
|
|
||||||
[#301]: https://github.com/actix/actix-net/pull/301
|
[#301]: https://github.com/actix/actix-net/pull/301
|
||||||
|
|
||||||
## 3.0.0-beta.2 - 2021-02-06
|
## 3.0.0-beta.2
|
||||||
|
|
||||||
- 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
|
[#273]: https://github.com/actix/actix-net/pull/273
|
||||||
|
|
||||||
## 3.0.0-beta.1 - 2020-12-28
|
## 3.0.0-beta.1
|
||||||
|
|
||||||
- Update `bytes` dependency to `1`. [#237]
|
- Update `bytes` dependency to `1`. [#237]
|
||||||
- Use `pin-project-lite` to replace `pin-project`. [#229]
|
- Use `pin-project-lite` to replace `pin-project`. [#229]
|
||||||
|
@ -43,139 +43,139 @@
|
||||||
[#229]: https://github.com/actix/actix-net/pull/229
|
[#229]: https://github.com/actix/actix-net/pull/229
|
||||||
[#237]: https://github.com/actix/actix-net/pull/237
|
[#237]: https://github.com/actix/actix-net/pull/237
|
||||||
|
|
||||||
## 2.0.0 - 2020-08-23
|
## 2.0.0
|
||||||
|
|
||||||
- No changes from beta 1.
|
- No changes from beta 1.
|
||||||
|
|
||||||
## 2.0.0-beta.1 - 2020-08-19
|
## 2.0.0-beta.1
|
||||||
|
|
||||||
- Upgrade `tokio-util` to `0.3`.
|
- Upgrade `tokio-util` to `0.3`.
|
||||||
- Remove unsound custom Cell and use `std::cell::RefCell` instead, as well as `actix-service`.
|
- Remove unsound custom Cell and use `std::cell::RefCell` instead, as well as `actix-service`.
|
||||||
- Rename method to correctly spelled `LocalWaker::is_registered`.
|
- Rename method to correctly spelled `LocalWaker::is_registered`.
|
||||||
|
|
||||||
## 1.0.6 - 2020-01-08
|
## 1.0.6
|
||||||
|
|
||||||
- Add `Clone` impl for `condition::Waiter`.
|
- Add `Clone` impl for `condition::Waiter`.
|
||||||
|
|
||||||
## 1.0.5 - 2020-01-08
|
## 1.0.5
|
||||||
|
|
||||||
- Add `Condition` type.
|
- Add `Condition` type.
|
||||||
- Add `Pool` of one-shot's.
|
- Add `Pool` of one-shot's.
|
||||||
|
|
||||||
## 1.0.4 - 2019-12-20
|
## 1.0.4
|
||||||
|
|
||||||
- Add methods to check `LocalWaker` registration state.
|
- Add methods to check `LocalWaker` registration state.
|
||||||
|
|
||||||
## 1.0.3 - 2019-12-11
|
## 1.0.3
|
||||||
|
|
||||||
- Revert InOrder service changes
|
- Revert InOrder service changes
|
||||||
|
|
||||||
## 1.0.2 - 2019-12-11
|
## 1.0.2
|
||||||
|
|
||||||
- Allow to create `framed::Dispatcher` with custom `mpsc::Receiver`.
|
- Allow to create `framed::Dispatcher` with custom `mpsc::Receiver`.
|
||||||
- Add `oneshot::Sender::is_canceled()` method.
|
- Add `oneshot::Sender::is_canceled()` method.
|
||||||
|
|
||||||
## 1.0.1 - 2019-12-11
|
## 1.0.1
|
||||||
|
|
||||||
- Optimize InOrder service.
|
- Optimize InOrder service.
|
||||||
|
|
||||||
## 1.0.0 - 2019-12-11
|
## 1.0.0
|
||||||
|
|
||||||
- Simplify oneshot and mpsc implementations.
|
- Simplify oneshot and mpsc implementations.
|
||||||
|
|
||||||
## 1.0.0-alpha.3 - 2019-12-07
|
## 1.0.0-alpha.3
|
||||||
|
|
||||||
- Migrate to tokio 0.2.
|
- Migrate to tokio 0.2.
|
||||||
- Fix oneshot.
|
- Fix oneshot.
|
||||||
|
|
||||||
## 1.0.0-alpha.2 - 2019-12-02
|
## 1.0.0-alpha.2
|
||||||
|
|
||||||
- Migrate to `std::future`.
|
- Migrate to `std::future`.
|
||||||
|
|
||||||
## 0.4.7 - 2019-10-14
|
## 0.4.7
|
||||||
|
|
||||||
- Re-register task on every framed transport poll.
|
- Re-register task on every framed transport poll.
|
||||||
|
|
||||||
## 0.4.6 - 2019-10-08
|
## 0.4.6
|
||||||
|
|
||||||
- Refactor `Counter` type. register current task in available method.
|
- Refactor `Counter` type. register current task in available method.
|
||||||
|
|
||||||
## 0.4.5 - 2019-07-19
|
## 0.4.5
|
||||||
|
|
||||||
- Deprecated `CloneableService` as it is not safe.
|
- Deprecated `CloneableService` as it is not safe.
|
||||||
|
|
||||||
## 0.4.4 - 2019-07-17
|
## 0.4.4
|
||||||
|
|
||||||
- Undeprecate `FramedTransport` as it is actually useful.
|
- Undeprecate `FramedTransport` as it is actually useful.
|
||||||
|
|
||||||
## 0.4.3 - 2019-07-17
|
## 0.4.3
|
||||||
|
|
||||||
- Deprecate `CloneableService` as it is not safe and in general not very useful.
|
- Deprecate `CloneableService` as it is not safe and in general not very useful.
|
||||||
- Deprecate `FramedTransport` in favor of `actix-ioframe`.
|
- Deprecate `FramedTransport` in favor of `actix-ioframe`.
|
||||||
|
|
||||||
## 0.4.2 - 2019-06-26
|
## 0.4.2
|
||||||
|
|
||||||
- Do not block on sink drop for FramedTransport.
|
- Do not block on sink drop for FramedTransport.
|
||||||
|
|
||||||
## 0.4.1 - 2019-05-15
|
## 0.4.1
|
||||||
|
|
||||||
- Change `Either` constructor.
|
- Change `Either` constructor.
|
||||||
|
|
||||||
## 0.4.0 - 2019-05-11
|
## 0.4.0
|
||||||
|
|
||||||
- Change `Either` to handle two nexted services.
|
- Change `Either` to handle two nexted services.
|
||||||
- Upgrade actix-service 0.4.
|
- Upgrade actix-service 0.4.
|
||||||
- Removed framed related services.
|
- Removed framed related services.
|
||||||
- Removed stream related services.
|
- Removed stream related services.
|
||||||
|
|
||||||
## 0.3.5 - 2019-04-04
|
## 0.3.5
|
||||||
|
|
||||||
- Allow to send messages to `FramedTransport` via mpsc channel.
|
- Allow to send messages to `FramedTransport` via mpsc channel.
|
||||||
- Remove `'static` constraint from Clonable service.
|
- Remove `'static` constraint from Clonable service.
|
||||||
|
|
||||||
## 0.3.4 - 2019-03-12
|
## 0.3.4
|
||||||
|
|
||||||
- `TimeoutService`, `InOrderService`, `InFlightService` accepts generic IntoService services.
|
- `TimeoutService`, `InOrderService`, `InFlightService` accepts generic IntoService services.
|
||||||
- Fix `InFlightService::poll_ready()` nested service readiness check.
|
- Fix `InFlightService::poll_ready()` nested service readiness check.
|
||||||
- Fix `InOrderService::poll_ready()` nested service readiness check.
|
- Fix `InOrderService::poll_ready()` nested service readiness check.
|
||||||
|
|
||||||
## 0.3.3 - 2019-03-09
|
## 0.3.3
|
||||||
|
|
||||||
- Revert IntoFuture change.
|
- Revert IntoFuture change.
|
||||||
- Add generic config param for IntoFramed and TakeOne new services.
|
- Add generic config param for IntoFramed and TakeOne new services.
|
||||||
|
|
||||||
## 0.3.2 - 2019-03-04
|
## 0.3.2
|
||||||
|
|
||||||
- Use IntoFuture for new services.
|
- Use IntoFuture for new services.
|
||||||
|
|
||||||
## 0.3.1 - 2019-03-04
|
## 0.3.1
|
||||||
|
|
||||||
- Use new type of transform trait.
|
- Use new type of transform trait.
|
||||||
|
|
||||||
## 0.3.0 - 2019-03-02
|
## 0.3.0
|
||||||
|
|
||||||
- Use new `NewService` trait
|
- Use new `NewService` trait
|
||||||
- BoxedNewService`and`BoxedService` types moved to actix-service crate.
|
- BoxedNewService`and`BoxedService` types moved to actix-service crate.
|
||||||
|
|
||||||
## 0.2.4 - 2019-02-21
|
## 0.2.4
|
||||||
|
|
||||||
- Custom `BoxedNewService` implementation.
|
- Custom `BoxedNewService` implementation.
|
||||||
|
|
||||||
## 0.2.3 - 2019-02-21
|
## 0.2.3
|
||||||
|
|
||||||
- Add `BoxedNewService` and `BoxedService`.
|
- Add `BoxedNewService` and `BoxedService`.
|
||||||
|
|
||||||
## 0.2.2 - 2019-02-11
|
## 0.2.2
|
||||||
|
|
||||||
- Add `Display` impl for `TimeoutError`.
|
- Add `Display` impl for `TimeoutError`.
|
||||||
- Add `Display` impl for `InOrderError`.
|
- Add `Display` impl for `InOrderError`.
|
||||||
|
|
||||||
## 0.2.1 - 2019-02-06
|
## 0.2.1
|
||||||
|
|
||||||
- Add `InOrder` service. the service yields responses as they become available, in the order that their originating requests were submitted to the service.
|
- 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
|
## 0.2.0
|
||||||
|
|
||||||
- Fix framed transport error handling.
|
- Fix framed transport error handling.
|
||||||
- Added Clone impl for Either service.
|
- Added Clone impl for Either service.
|
||||||
|
@ -183,6 +183,6 @@
|
||||||
- Added Service and NewService for Stream dispatcher.
|
- Added Service and NewService for Stream dispatcher.
|
||||||
- Switch to actix-service 0.2.
|
- Switch to actix-service 0.2.
|
||||||
|
|
||||||
## 0.1.0 - 2018-12-09
|
## 0.1.0
|
||||||
|
|
||||||
- Move utils services to separate crate.
|
- Move utils services to separate crate.
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-utils"
|
name = "actix-utils"
|
||||||
version = "3.0.1"
|
version = "3.0.1"
|
||||||
authors = [
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
|
||||||
]
|
|
||||||
description = "Various utilities used in the Actix ecosystem"
|
description = "Various utilities used in the Actix ecosystem"
|
||||||
keywords = ["network", "framework", "async", "futures"]
|
keywords = ["network", "framework", "async", "futures"]
|
||||||
categories = ["network-programming", "asynchronous"]
|
categories = ["network-programming", "asynchronous"]
|
||||||
|
@ -14,10 +11,13 @@ edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pin-project-lite = "0.2"
|
|
||||||
local-waker = "0.1"
|
local-waker = "0.1"
|
||||||
|
pin-project-lite = "0.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2"
|
actix-rt = "2"
|
||||||
futures-util = { version = "0.3.17", default-features = false }
|
futures-util = { version = "0.3.17", default-features = false }
|
||||||
static_assertions = "1.1"
|
static_assertions = "1.1"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -103,6 +103,7 @@ mod tests {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn require_sync<T: Sync>(_t: &T) {}
|
fn require_sync<T: Sync>(_t: &T) {}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
trait AmbiguousIfUnpin<A> {
|
trait AmbiguousIfUnpin<A> {
|
||||||
fn some_item(&self) {}
|
fn some_item(&self) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
//! Various utilities used in the Actix ecosystem.
|
//! Various utilities used in the Actix ecosystem.
|
||||||
|
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
||||||
#![warn(future_incompatible, missing_docs)]
|
|
||||||
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
|
||||||
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,34 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
## 1.3.0 - 2023-03-03
|
## 1.4.0
|
||||||
|
|
||||||
|
- Add `ByteString::split_at()` method.
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
|
## 1.3.1
|
||||||
|
|
||||||
|
- No significant changes since `1.3.0`.
|
||||||
|
|
||||||
|
## 1.3.0
|
||||||
|
|
||||||
- Implement `AsRef<ByteString>` for `ByteString`.
|
- Implement `AsRef<ByteString>` for `ByteString`.
|
||||||
|
|
||||||
## 1.2.1 - 2022-11-12
|
## 1.2.1
|
||||||
|
|
||||||
- Fix `#[no_std]` compatibility. [#471]
|
- Fix `#[no_std]` compatibility. [#471]
|
||||||
|
|
||||||
[#471]: https://github.com/actix/actix-net/pull/471
|
[#471]: https://github.com/actix/actix-net/pull/471
|
||||||
|
|
||||||
## 1.2.0 - 2022-11-07
|
## 1.2.0
|
||||||
|
|
||||||
- Add `ByteString::slice_ref` which can safely slice a `ByteString` into a new one with zero copy. [#470]
|
- Add `ByteString::slice_ref` which can safely slice a `ByteString` into a new one with zero copy. [#470]
|
||||||
- Minimum supported Rust version (MSRV) is now 1.57.
|
- Minimum supported Rust version (MSRV) is now 1.57.
|
||||||
|
|
||||||
[#470]: https://github.com/actix/actix-net/pull/470
|
[#470]: https://github.com/actix/actix-net/pull/470
|
||||||
|
|
||||||
## 1.1.0 - 2022-06-11
|
## 1.1.0
|
||||||
|
|
||||||
- Implement `From<Box<str>>` for `ByteString`. [#458]
|
- Implement `From<Box<str>>` for `ByteString`. [#458]
|
||||||
- Implement `Into<String>` for `ByteString`. [#458]
|
- Implement `Into<String>` for `ByteString`. [#458]
|
||||||
|
@ -27,7 +36,7 @@
|
||||||
|
|
||||||
[#458]: https://github.com/actix/actix-net/pull/458
|
[#458]: https://github.com/actix/actix-net/pull/458
|
||||||
|
|
||||||
## 1.0.0 - 2020-12-31
|
## 1.0.0
|
||||||
|
|
||||||
- Update `bytes` dependency to `1`.
|
- Update `bytes` dependency to `1`.
|
||||||
- Add array and slice of `u8` impls of `TryFrom` up to 32 in length.
|
- Add array and slice of `u8` impls of `TryFrom` up to 32 in length.
|
||||||
|
@ -35,27 +44,27 @@
|
||||||
- `ByteString::new` is now a `const fn`.
|
- `ByteString::new` is now a `const fn`.
|
||||||
- Crate is now `#[no_std]` compatible.
|
- Crate is now `#[no_std]` compatible.
|
||||||
|
|
||||||
## 0.1.5 - 2020-03-30
|
## 0.1.5
|
||||||
|
|
||||||
- Serde support
|
- Serde support
|
||||||
|
|
||||||
## 0.1.4 - 2020-01-14
|
## 0.1.4
|
||||||
|
|
||||||
- Fix `AsRef<str>` impl
|
- Fix `AsRef<str>` impl
|
||||||
|
|
||||||
## 0.1.3 - 2020-01-13
|
## 0.1.3
|
||||||
|
|
||||||
- Add `PartialEq<T: AsRef<str>>`, `AsRef<[u8]>` impls
|
- Add `PartialEq<T: AsRef<str>>`, `AsRef<[u8]>` impls
|
||||||
|
|
||||||
## 0.1.2 - 2019-12-22
|
## 0.1.2
|
||||||
|
|
||||||
- Fix `new()` method
|
- Fix `new()` method
|
||||||
- Make `ByteString::from_static()` and `ByteString::from_bytes_unchecked()` methods const.
|
- Make `ByteString::from_static()` and `ByteString::from_bytes_unchecked()` methods const.
|
||||||
|
|
||||||
## 0.1.1 - 2019-12-07
|
## 0.1.1
|
||||||
|
|
||||||
- Fix hash impl
|
- Fix hash impl
|
||||||
|
|
||||||
## 0.1.0 - 2019-12-07
|
## 0.1.0
|
||||||
|
|
||||||
- Initial release
|
- Initial release
|
||||||
|
|
|
@ -1,25 +1,27 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bytestring"
|
name = "bytestring"
|
||||||
version = "1.3.0"
|
version = "1.4.0"
|
||||||
authors = [
|
description = "A UTF-8 encoded read-only string using `Bytes` as storage"
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
keywords = ["string", "bytes", "utf8", "web", "bytestring"]
|
||||||
]
|
|
||||||
description = "An immutable UTF-8 encoded string using Bytes as storage"
|
|
||||||
keywords = ["string", "bytes", "utf8", "web", "actix"]
|
|
||||||
categories = ["no-std", "web-programming"]
|
categories = ["no-std", "web-programming"]
|
||||||
homepage = "https://actix.rs"
|
homepage = "https://actix.rs"
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
repository = "https://github.com/actix/actix-net"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = ["bytes::*", "serde::*"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bytes = { version = "1.2", default-features = false }
|
bytes = { version = "1.2", default-features = false }
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
ahash = { version = "0.8", default-features = false }
|
ahash = { version = "0.8", default-features = false }
|
||||||
serde_json = "1.0"
|
serde_json = "1"
|
||||||
static_assertions = "1.1"
|
static_assertions = "1.1"
|
||||||
rustversion = "1"
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
# `bytestring`
|
||||||
|
|
||||||
|
> A UTF-8 encoded read-only string using `Bytes` as storage.
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
|
||||||
|
[](https://crates.io/crates/bytestring)
|
||||||
|
[](https://docs.rs/bytestring/1.4.0)
|
||||||
|
[](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
||||||
|

|
||||||
|
<br />
|
||||||
|
[](https://deps.rs/crate/bytestring/1.4.0)
|
||||||
|

|
||||||
|
[](https://discord.gg/NWpN5mmg3x)
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
|
@ -1,8 +1,8 @@
|
||||||
//! A UTF-8 encoded read-only string using Bytes as storage.
|
//! A UTF-8 encoded read-only string using `Bytes` as storage.
|
||||||
|
//!
|
||||||
|
//! See docs for [`ByteString`].
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
|
||||||
#![warn(future_incompatible, missing_docs)]
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
@ -11,11 +11,11 @@ use alloc::{
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::{borrow::Borrow, convert::TryFrom, fmt, hash, ops, str};
|
use core::{borrow::Borrow, fmt, hash, ops, str};
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
/// An immutable UTF-8 encoded string with [`Bytes`] as a storage.
|
/// An immutable UTF-8 encoded string using [`Bytes`] as the storage.
|
||||||
#[derive(Clone, Default, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Default, Eq, PartialOrd, Ord)]
|
||||||
pub struct ByteString(Bytes);
|
pub struct ByteString(Bytes);
|
||||||
|
|
||||||
|
@ -51,7 +51,29 @@ impl ByteString {
|
||||||
Self(src)
|
Self(src)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new byte string that is equivalent to the given `subset`.
|
/// Divides one bytestring into two at an index, returning both parts.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `mid` is not on a UTF-8 code point boundary, or if it is past the end of the last
|
||||||
|
/// code point of the bytestring.
|
||||||
|
pub fn split_at(&self, mid: usize) -> (ByteString, ByteString) {
|
||||||
|
let this: &str = self.as_ref();
|
||||||
|
let _valid_midpoint_check = this.split_at(mid);
|
||||||
|
|
||||||
|
let mut bytes = self.0.clone();
|
||||||
|
let first = bytes.split_to(mid);
|
||||||
|
let last = bytes;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(
|
||||||
|
ByteString::from_bytes_unchecked(first),
|
||||||
|
ByteString::from_bytes_unchecked(last),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new `ByteString` that is equivalent to the given `subset`.
|
||||||
///
|
///
|
||||||
/// When processing a `ByteString` buffer with other tools, one often gets a `&str` which is in
|
/// When processing a `ByteString` buffer with other tools, one often gets a `&str` which is in
|
||||||
/// fact a slice of the original `ByteString`; i.e., a subset of it. This function turns that
|
/// fact a slice of the original `ByteString`; i.e., a subset of it. This function turns that
|
||||||
|
@ -463,4 +485,33 @@ mod test {
|
||||||
// being a logical subset of the string
|
// being a logical subset of the string
|
||||||
ByteString::from_static("foo bar").slice_ref("foo");
|
ByteString::from_static("foo bar").slice_ref("foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn split_at() {
|
||||||
|
let buf = ByteString::from_static("foo bar");
|
||||||
|
|
||||||
|
let (first, last) = buf.split_at(0);
|
||||||
|
assert_eq!(ByteString::from_static(""), first);
|
||||||
|
assert_eq!(ByteString::from_static("foo bar"), last);
|
||||||
|
|
||||||
|
let (first, last) = buf.split_at(4);
|
||||||
|
assert_eq!(ByteString::from_static("foo "), first);
|
||||||
|
assert_eq!(ByteString::from_static("bar"), last);
|
||||||
|
|
||||||
|
let (first, last) = buf.split_at(7);
|
||||||
|
assert_eq!(ByteString::from_static("foo bar"), first);
|
||||||
|
assert_eq!(ByteString::from_static(""), last);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic = "byte index 1 is not a char boundary;"]
|
||||||
|
fn split_at_invalid_code_point() {
|
||||||
|
ByteString::from_static("µ").split_at(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic = "byte index 9 is out of bounds"]
|
||||||
|
fn split_at_outside_string() {
|
||||||
|
ByteString::from_static("foo").split_at(9);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ coverage:
|
||||||
default:
|
default:
|
||||||
threshold: 10% # make CI green
|
threshold: 10% # make CI green
|
||||||
|
|
||||||
ignore: # ignore codecoverage on following paths
|
ignore: # ignore code coverage on following paths
|
||||||
- "examples"
|
- "examples"
|
||||||
- ".github"
|
- ".github"
|
||||||
- "**/*.md"
|
- "**/*.md"
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1715865404,
|
||||||
|
"narHash": "sha256-/GJvTdTpuDjNn84j82cU6bXztE0MSkdnTWClUCRub78=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "8dc45382d5206bd292f9c2768b8058a8fd8311d9",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1722651103,
|
||||||
|
"narHash": "sha256-IRiJA0NVAoyaZeKZluwfb2DoTpBAj+FLI0KfybBeDU0=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "a633d89c6dc9a2a8aae11813a62d7c58b2c0cc51",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-24.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs-lib": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1714640452,
|
||||||
|
"narHash": "sha256-QBx10+k6JWz6u7VsohfSw8g8hjdBZEf8CFzXH1/1Z94=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/NixOS/nixpkgs/archive/50eb7ecf4cd0a5756d7275c8ba36790e5bd53e33.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
|
||||||
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = inputs@{ flake-parts, ... }:
|
||||||
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
|
systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
||||||
|
perSystem = { pkgs, config, inputs', system, lib, ... }: {
|
||||||
|
formatter = pkgs.nixpkgs-fmt;
|
||||||
|
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
packages = [
|
||||||
|
config.formatter
|
||||||
|
pkgs.fd
|
||||||
|
pkgs.just
|
||||||
|
pkgs.nodePackages.prettier
|
||||||
|
pkgs.taplo
|
||||||
|
pkgs.watchexec
|
||||||
|
] ++ lib.optional pkgs.stdenv.isDarwin [
|
||||||
|
pkgs.pkgsBuildHost.darwin.apple_sdk.frameworks.Security
|
||||||
|
pkgs.pkgsBuildHost.darwin.apple_sdk.frameworks.CoreFoundation
|
||||||
|
pkgs.pkgsBuildHost.darwin.apple_sdk.frameworks.SystemConfiguration
|
||||||
|
pkgs.pkgsBuildHost.libiconv
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,122 @@
|
||||||
|
_list:
|
||||||
|
@just --list
|
||||||
|
|
||||||
|
# Check project.
|
||||||
|
check: && clippy
|
||||||
|
just --unstable --fmt --check
|
||||||
|
# nixpkgs-fmt --check .
|
||||||
|
fd --hidden --type=file -e=md -e=yml --exec-batch prettier --check
|
||||||
|
fd --hidden -e=toml --exec-batch taplo format --check
|
||||||
|
fd --hidden -e=toml --exec-batch taplo lint
|
||||||
|
cargo +nightly fmt -- --check
|
||||||
|
|
||||||
|
# Format project.
|
||||||
|
fmt:
|
||||||
|
just --unstable --fmt
|
||||||
|
# nixpkgs-fmt .
|
||||||
|
fd --hidden --type=file -e=md -e=yml --exec-batch prettier --write
|
||||||
|
fd --type=file --hidden -e=toml --exec-batch taplo format
|
||||||
|
cargo +nightly fmt
|
||||||
|
|
||||||
|
# Downgrade dependencies necessary to run MSRV checks/tests.
|
||||||
|
[private]
|
||||||
|
downgrade-for-msrv:
|
||||||
|
cargo update -p=clap --precise=4.4.18 # next ver: 1.74.0
|
||||||
|
cargo update -p=native-tls --precise=0.2.13 # next ver: 1.80.0
|
||||||
|
cargo update -p=litemap --precise=0.7.4 # next ver: 1.81.0
|
||||||
|
cargo update -p=zerofrom --precise=0.1.5 # next ver: 1.81.0
|
||||||
|
cargo update -p=half --precise=2.4.1 # next ver: 1.81.0
|
||||||
|
|
||||||
|
msrv := ```
|
||||||
|
cargo metadata --format-version=1 \
|
||||||
|
| jq -r 'first(.packages[] | select(.source == null and .rust_version)) | .rust_version' \
|
||||||
|
| sed -E 's/^1\.([0-9]{2})$/1\.\1\.0/'
|
||||||
|
```
|
||||||
|
msrv_rustup := "+" + msrv
|
||||||
|
non_linux_all_features_list := ```
|
||||||
|
cargo metadata --format-version=1 \
|
||||||
|
| jq '.packages[] | select(.source == null) | .features | keys' \
|
||||||
|
| jq -r --slurp \
|
||||||
|
--arg exclusions "tokio-uring,io-uring" \
|
||||||
|
'add | unique | . - ($exclusions | split(",")) | join(",")'
|
||||||
|
```
|
||||||
|
all_crate_features := if os() == "linux" { "--all-features" } else { "--features='" + non_linux_all_features_list + "'" }
|
||||||
|
|
||||||
|
# Run Clippy over workspace.
|
||||||
|
clippy toolchain="":
|
||||||
|
cargo {{ toolchain }} clippy --workspace --all-targets {{ all_crate_features }}
|
||||||
|
|
||||||
|
# Run Clippy using MSRV.
|
||||||
|
clippy-msrv: downgrade-for-msrv (clippy msrv_rustup)
|
||||||
|
|
||||||
|
# Test workspace code.
|
||||||
|
[macos]
|
||||||
|
[windows]
|
||||||
|
test toolchain="":
|
||||||
|
cargo {{ toolchain }} test --lib --tests --package=actix-macros
|
||||||
|
cargo {{ toolchain }} nextest run --no-tests=warn --workspace --exclude=actix-macros --no-default-features
|
||||||
|
cargo {{ toolchain }} nextest run --no-tests=warn --workspace --exclude=actix-macros {{ all_crate_features }}
|
||||||
|
|
||||||
|
# Test workspace code.
|
||||||
|
[linux]
|
||||||
|
test toolchain="":
|
||||||
|
cargo {{ toolchain }} test --lib --tests --package=actix-macros
|
||||||
|
cargo {{ toolchain }} nextest run --no-tests=warn --workspace --exclude=actix-macros --no-default-features
|
||||||
|
cargo {{ toolchain }} nextest run --no-tests=warn --workspace --exclude=actix-macros {{ non_linux_all_features_list }}
|
||||||
|
cargo {{ toolchain }} nextest run --no-tests=warn --workspace --exclude=actix-macros {{ all_crate_features }}
|
||||||
|
|
||||||
|
# Test workspace using MSRV.
|
||||||
|
test-msrv: downgrade-for-msrv (test msrv_rustup)
|
||||||
|
|
||||||
|
# Test workspace docs.
|
||||||
|
test-docs toolchain="": && doc
|
||||||
|
cargo {{ toolchain }} test --doc --workspace {{ all_crate_features }} --no-fail-fast -- --nocapture
|
||||||
|
|
||||||
|
# Test workspace.
|
||||||
|
test-all toolchain="": (test toolchain) (test-docs toolchain)
|
||||||
|
|
||||||
|
# Document crates in workspace.
|
||||||
|
doc *args: && doc-set-workspace-crates
|
||||||
|
rm -f "$(cargo metadata --format-version=1 | jq -r '.target_directory')/doc/crates.js"
|
||||||
|
RUSTDOCFLAGS="--cfg=docsrs -Dwarnings" cargo +nightly doc --no-deps --workspace {{ all_crate_features }} {{ args }}
|
||||||
|
|
||||||
|
[private]
|
||||||
|
doc-set-workspace-crates:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
(
|
||||||
|
echo "window.ALL_CRATES ="
|
||||||
|
cargo metadata --format-version=1 \
|
||||||
|
| jq '[.packages[] | select(.source == null) | .targets | map(select(.doc) | .name)] | flatten'
|
||||||
|
echo ";"
|
||||||
|
) > "$(cargo metadata --format-version=1 | jq -r '.target_directory')/doc/crates.js"
|
||||||
|
|
||||||
|
# Document crates in workspace and watch for changes.
|
||||||
|
doc-watch:
|
||||||
|
@just doc --open
|
||||||
|
cargo watch -- just doc
|
||||||
|
|
||||||
|
# Check for unintentional external type exposure on all crates in workspace.
|
||||||
|
check-external-types-all toolchain="+nightly":
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
exit=0
|
||||||
|
for f in $(find . -mindepth 2 -maxdepth 2 -name Cargo.toml | grep -vE "\-codegen/|\-derive/|\-macros/"); do
|
||||||
|
if ! just check-external-types-manifest "$f" {{ toolchain }}; then exit=1; fi
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
done
|
||||||
|
exit $exit
|
||||||
|
|
||||||
|
# Check for unintentional external type exposure on all crates in workspace.
|
||||||
|
check-external-types-all-table toolchain="+nightly":
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
for f in $(find . -mindepth 2 -maxdepth 2 -name Cargo.toml | grep -vE "\-codegen/|\-derive/|\-macros/"); do
|
||||||
|
echo
|
||||||
|
echo "Checking for $f"
|
||||||
|
just check-external-types-manifest "$f" {{ toolchain }} --output-format=markdown-table
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check for unintentional external type exposure on a crate.
|
||||||
|
check-external-types-manifest manifest_path toolchain="+nightly" *extra_args="":
|
||||||
|
cargo {{ toolchain }} check-external-types --manifest-path "{{ manifest_path }}" {{ extra_args }}
|
|
@ -1,17 +1,25 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
|
## 0.1.5
|
||||||
|
|
||||||
|
- No significant changes since `0.1.4`.
|
||||||
|
|
||||||
|
## 0.1.4
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 0.1.3 - 2022-05-03
|
## 0.1.3
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||||
|
|
||||||
## 0.1.2 - 2021-04-01
|
## 0.1.2
|
||||||
|
|
||||||
- No significant changes from `0.1.1`.
|
- No significant changes from `0.1.1`.
|
||||||
|
|
||||||
## 0.1.1 - 2021-03-29
|
## 0.1.1
|
||||||
|
|
||||||
- Move local mpsc channel to it's own crate.
|
- Move local MPSC channel to it's own crate.
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
[package]
|
[package]
|
||||||
name = "local-channel"
|
name = "local-channel"
|
||||||
version = "0.1.3"
|
version = "0.1.5"
|
||||||
description = "A non-threadsafe multi-producer, single-consumer, futures-aware, FIFO queue"
|
description = "A non-threadsafe multi-producer, single-consumer, futures-aware, FIFO queue"
|
||||||
authors = [
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
repository = "https://github.com/actix/actix-net"
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
|
||||||
]
|
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
|
||||||
keywords = ["channel", "local", "futures"]
|
keywords = ["channel", "local", "futures"]
|
||||||
license = "MIT OR Apache-2.0"
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.cargo_check_external_types]
|
||||||
|
allowed_external_types = ["futures_core::*", "futures_sink::*"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures-core = "0.3.17"
|
futures-core = "0.3.17"
|
||||||
futures-sink = "0.3.17"
|
futures-sink = "0.3.17"
|
||||||
futures-util = { version = "0.3.17", default-features = false }
|
|
||||||
local-waker = "0.1"
|
local-waker = "0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
futures-util = { version = "0.3.17", default-features = false }
|
||||||
tokio = { version = "1.23.1", features = ["rt", "macros"] }
|
tokio = { version = "1.23.1", features = ["rt", "macros"] }
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
# `local-channel`
|
||||||
|
|
||||||
|
> A non-threadsafe multi-producer, single-consumer, futures-aware, FIFO queue.
|
||||||
|
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
|
||||||
|
[](https://crates.io/crates/local-channel)
|
||||||
|
[](https://docs.rs/local-channel/0.1.5)
|
||||||
|
[](https://blog.rust-lang.org/2021/05/06/Rust-1.52.0.html)
|
||||||
|

|
||||||
|
<br />
|
||||||
|
[](https://deps.rs/crate/local-channel/0.1.5)
|
||||||
|

|
||||||
|
[](https://discord.gg/NWpN5mmg3x)
|
||||||
|
|
||||||
|
<!-- prettier-ignore-end -->
|
|
@ -1,4 +1,6 @@
|
||||||
//! Non-thread-safe channels.
|
//! Non-thread-safe channels.
|
||||||
|
//!
|
||||||
|
//! See docs for [`mpsc::channel()`].
|
||||||
|
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||||
#![warn(future_incompatible, missing_docs)]
|
#![warn(future_incompatible, missing_docs)]
|
||||||
|
|
|
@ -4,6 +4,7 @@ use alloc::{collections::VecDeque, rc::Rc};
|
||||||
use core::{
|
use core::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
fmt,
|
fmt,
|
||||||
|
future::poll_fn,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
};
|
};
|
||||||
|
@ -11,7 +12,6 @@ use std::error::Error;
|
||||||
|
|
||||||
use futures_core::stream::Stream;
|
use futures_core::stream::Stream;
|
||||||
use futures_sink::Sink;
|
use futures_sink::Sink;
|
||||||
use futures_util::future::poll_fn;
|
|
||||||
use local_waker::LocalWaker;
|
use local_waker::LocalWaker;
|
||||||
|
|
||||||
/// Creates a unbounded in-memory channel with buffered storage.
|
/// Creates a unbounded in-memory channel with buffered storage.
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2023-xx-xx
|
## Unreleased
|
||||||
|
|
||||||
|
- Minimum supported Rust version (MSRV) is now 1.71.
|
||||||
|
|
||||||
|
## 0.1.4
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.65.
|
- Minimum supported Rust version (MSRV) is now 1.65.
|
||||||
|
|
||||||
## 0.1.3 - 2022-05-03
|
## 0.1.3
|
||||||
|
|
||||||
- Minimum supported Rust version (MSRV) is now 1.49.
|
- Minimum supported Rust version (MSRV) is now 1.49.
|
||||||
|
|
||||||
## 0.1.2 - 2021-12-18
|
## 0.1.2
|
||||||
|
|
||||||
- Fix crate metadata.
|
- Fix crate metadata.
|
||||||
|
|
||||||
## 0.1.1 - 2021-03-29
|
## 0.1.1
|
||||||
|
|
||||||
- Move `LocalWaker` to it's own crate.
|
- Move `LocalWaker` to it's own crate.
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
[package]
|
[package]
|
||||||
name = "local-waker"
|
name = "local-waker"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
description = "A synchronization primitive for thread-local task wakeup"
|
description = "A synchronization primitive for thread-local task wakeup"
|
||||||
authors = [
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
"Nikolay Kim <fafhrd91@gmail.com>",
|
repository = "https://github.com/actix/actix-net"
|
||||||
"Rob Ede <robjtede@icloud.com>",
|
|
||||||
]
|
|
||||||
repository = "https://github.com/actix/actix-net.git"
|
|
||||||
keywords = ["waker", "local", "futures", "no-std"]
|
keywords = ["waker", "local", "futures", "no-std"]
|
||||||
categories = ["asynchronous", "no-std"]
|
categories = ["asynchronous", "no-std"]
|
||||||
license = "MIT OR Apache-2.0"
|
license.workspace = true
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
rust-version.workspace = true
|
rust-version.workspace = true
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue