commit
cb2099fe77
20 changed files with 120 additions and 43 deletions
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
|
|
@ -19,6 +19,16 @@ updates:
|
|||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/rpxy-certs"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/rpxy-acme"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
# Enable version updates for Docker
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/docker"
|
||||
|
|
|
|||
12
.github/workflows/release_docker.yml
vendored
12
.github/workflows/release_docker.yml
vendored
|
|
@ -16,7 +16,7 @@ env:
|
|||
|
||||
jobs:
|
||||
build_and_push:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ github.event_name == 'push' }} || ${{ github.event_name == 'pull_request' && github.event.pull_request.merged == true }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
|
@ -170,6 +170,14 @@ jobs:
|
|||
platforms: ${{ matrix.platforms }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
- name: check pull_request title
|
||||
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref == 'develop' && github.event.pull_request.base.ref == 'main' && github.event.pull_request.merged == true }}
|
||||
uses: kaisugi/action-regex-match@v1.0.1
|
||||
id: regex-match
|
||||
with:
|
||||
text: ${{ github.event.pull_request.title }}
|
||||
regex: "^(\\d+\\.\\d+\\.\\d+)$"
|
||||
|
||||
- name: Release build and push from main branch
|
||||
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref == 'develop' && github.event.pull_request.base.ref == 'main' && github.event.pull_request.merged == true }}
|
||||
uses: docker/build-push-action@v6
|
||||
|
|
@ -181,6 +189,8 @@ jobs:
|
|||
${{ env.GHCR }}/${{ env.GHCR_IMAGE_NAME }}:latest${{ matrix.tags-suffix }}
|
||||
${{ env.DH_REGISTRY_NAME }}:latest${{ matrix.tags-suffix }}
|
||||
${{ matrix.aliases }}
|
||||
${{ env.GHCR }}/${{ env.GHCR_IMAGE_NAME }}:${{ github.event.pull_request.title }}${{ matrix.tags-suffix }}
|
||||
${{ env.DH_REGISTRY_NAME }}:${{ github.event.pull_request.title }}${{ matrix.tags-suffix }}
|
||||
build-contexts: ${{ matrix.build-contexts }}
|
||||
file: ${{ matrix.dockerfile }}
|
||||
cache-from: type=gha,scope=rpxy-latest-${{ matrix.target }}
|
||||
|
|
|
|||
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -1,6 +1,22 @@
|
|||
# CHANGELOG
|
||||
|
||||
## 0.9.7 or 0.10.0 (Unreleased)
|
||||
## 0.9.8 or 0.10.0 (Unreleased)
|
||||
|
||||
## 0.9.7
|
||||
|
||||
### Improvement
|
||||
|
||||
- Feat: add version tag for docker images via github actions
|
||||
- Feat: support gRPC: This makes rpxy to serve gRPC requests on the same port as HTTP and HTTPS, i.e., listen_port and listen_port_tls. This means that by using the different subdomain for HTTP(S) and gRPC, we can multiplex them on same ports without opening another port dedicated to gRPC. To this end, this update made the forwarder to force HTTP/2 for gRPC requests towards backend (gRPC) app.
|
||||
- Deps and refactor
|
||||
|
||||
### Bugfix
|
||||
|
||||
- Fixed bug for the upstream option "force_http2_upstream"
|
||||
|
||||
### Other
|
||||
|
||||
- Tentative downgrade of github actions `runs-on` from ubuntu-latest to ubuntu-22.04.
|
||||
|
||||
## 0.9.6
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[workspace.package]
|
||||
version = "0.9.6"
|
||||
version = "0.9.7"
|
||||
authors = ["Jun Kurihara"]
|
||||
homepage = "https://github.com/junkurihara/rust-rpxy"
|
||||
repository = "https://github.com/junkurihara/rust-rpxy"
|
||||
|
|
|
|||
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Jun Kurihara
|
||||
Copyright (c) 2025 Jun Kurihara
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
|||
33
README.md
33
README.md
|
|
@ -14,15 +14,28 @@
|
|||
|
||||
[^pure_rust]: Doubtfully can be claimed to be written in pure Rust since current `rpxy` is based on `aws-lc-rs` for cryptographic operations.
|
||||
|
||||
By default, `rpxy` provides the *TLS connection sanitization* by correctly binding a certificate used to establish a secure channel with the backend application. Specifically, it always keeps the consistency between the given SNI (server name indication) in `ClientHello` of the underlying TLS and the domain name given by the overlaid HTTP HOST header (or URL in Request line) [^1]. Additionally, as a somewhat unstable feature, our `rpxy` can handle the brand-new HTTP/3 connection thanks to [`quinn`](https://github.com/quinn-rs/quinn), [`s2n-quic`](https://github.com/aws/s2n-quic) and [`hyperium/h3`](https://github.com/hyperium/h3).[^h3lib] Furthermore, `rpxy` supports the automatic issuance and renewal of certificates via [TLS-ALPN-01 (RFC8737)](https://www.rfc-editor.org/rfc/rfc8737) of [ACME protocol (RFC8555)](https://www.rfc-editor.org/rfc/rfc8555) thanks to [`rustls-acme`](https://github.com/FlorianUekermann/rustls-acme), and the hybridized post-quantum key exchange [`X25519MLKEM768`](https://www.ietf.org/archive/id/draft-kwiatkowski-tls-ecdhe-mlkem-02.html)[^kyber] for TLS/QUIC incoming and outgoing initiation thanks to [`rustls-post-quantum`](https://docs.rs/rustls-post-quantum/latest/rustls_post_quantum/).
|
||||
Supported features are summarized as follows:
|
||||
|
||||
[^h3lib]: HTTP/3 libraries are mutually exclusive. You need to explicitly specify `s2n-quic` with `--no-default-features` flag. Also note that if you build `rpxy` with `s2n-quic`, then it requires `openssl` just for building the package.
|
||||
- Supported HTTP(S) protocols: HTTP/1.1, HTTP/2 and brand-new HTTP/3 [^h3lib]
|
||||
- gRPC is also supported
|
||||
- Serving multiple domain names with TLS termination
|
||||
- Mutual TLS authentication with client certificates
|
||||
- Automated certificate issuance and renewal via TLS-ALPN-01 ACME protocol [^acme]
|
||||
- Post-quantum key exchange for TLS/QUIC [^kyber]
|
||||
- TLS connection sanitization to avoid the domain fronting [^sanitization]
|
||||
- Load balancing with round-robin, random, and sticky session
|
||||
- and more...
|
||||
|
||||
[^kyber]: This is already a default feature. Also note that `X25519MLKEM768` is still a draft version yet this is widely used on the Internet.
|
||||
[^h3lib]: HTTP/3 is enabled thanks to [`quinn`](https://github.com/quinn-rs/quinn), [`s2n-quic`](https://github.com/aws/s2n-quic) and [`hyperium/h3`](https://github.com/hyperium/h3). HTTP/3 libraries are mutually exclusive. You need to explicitly specify `s2n-quic` with `--no-default-features` flag. Also note that if you build `rpxy` with `s2n-quic`, then it requires `openssl` just for building the package.
|
||||
|
||||
[^acme]: `rpxy` supports the automatic issuance and renewal of certificates via [TLS-ALPN-01 (RFC8737)](https://www.rfc-editor.org/rfc/rfc8737) of [ACME protocol (RFC8555)](https://www.rfc-editor.org/rfc/rfc8555) thanks to [`rustls-acme`](https://github.com/FlorianUekermann/rustls-acme).
|
||||
|
||||
[^kyber]: `rpxy` supports the hybridized post-quantum key exchange [`X25519MLKEM768`](https://www.ietf.org/archive/id/draft-kwiatkowski-tls-ecdhe-mlkem-02.html)[^kyber] for TLS/QUIC incoming and outgoing initiation thanks to [`rustls-post-quantum`](https://docs.rs/rustls-post-quantum/latest/rustls_post_quantum/). This is already a default feature. Also note that `X25519MLKEM768` is still a draft version yet this is widely used on the Internet.
|
||||
|
||||
[^sanitization]: By default, `rpxy` provides the *TLS connection sanitization* by correctly binding a certificate used to establish a secure channel with the backend application. Specifically, it always keeps the consistency between the given SNI (server name indication) in `ClientHello` of the underlying TLS and the domain name given by the overlaid HTTP HOST header (or URL in Request line). We should note that NGINX doesn't guarantee such a consistency by default. To this end, you have to add `if` statement in the configuration file in NGINX.
|
||||
|
||||
This project is still *work-in-progress*. But it is already working in some production environments and serves a number of domain names. Furthermore it *significantly outperforms* NGINX and Caddy, e.g., *1.5x faster than NGINX*, in the setting of a very simple HTTP reverse-proxy scenario (See [`bench`](./bench/) directory).
|
||||
|
||||
[^1]: We should note that NGINX doesn't guarantee such a consistency by default. To this end, you have to add `if` statement in the configuration file in NGINX.
|
||||
|
||||
## Installing/Building an Executable Binary of `rpxy`
|
||||
|
||||
|
|
@ -422,6 +435,18 @@ Check a third party project [`Gamerboy59/rpxy-webui`](https://github.com/Gamerbo
|
|||
|
||||
todo!
|
||||
|
||||
## Credits
|
||||
|
||||
`rpxy` cannot be built without the following projects and inspirations:
|
||||
|
||||
- [`hyper`](https://github.com/hyperium/hyper) and [`hyperium/h3`](https://github.com/hyperium/h3)
|
||||
- [`rustls`](https://github.com/rustls/rustls)
|
||||
- [`tokio`](https://github.com/tokio-rs/tokio)
|
||||
- [`quinn`](https://github.com/quinn-rs/quinn)
|
||||
- [`s2n-quic`](https://github.com/aws/s2n-quic)
|
||||
- [`rustls-acme`](https://github.com/FlorianUekermann/rustls-acme)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
`rpxy` is free, open-source software licensed under MIT License.
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ RUN apt-get update && apt-get install -qy --no-install-recommends $BUILD_DEPS ${
|
|||
echo "Install toolchain" && \
|
||||
rustup target add $(cat /arch)-${TARGET_SUFFIX} && \
|
||||
echo "Building rpxy from source" && \
|
||||
cargo update &&\
|
||||
cargo build --release --target=$(cat /arch)-${TARGET_SUFFIX} ${CARGO_FEATURES} && \
|
||||
strip --strip-all /tmp/target/$(cat /arch)-${TARGET_SUFFIX}/release/rpxy &&\
|
||||
cp /tmp/target/$(cat /arch)-${TARGET_SUFFIX}/release/rpxy /tmp/target/release/rpxy
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ COPY . /tmp/
|
|||
ENV RUSTFLAGS "-C link-arg=-s"
|
||||
|
||||
RUN echo "Building rpxy from source" && \
|
||||
cargo update && \
|
||||
cargo build --release --target $(cat /arch)-unknown-linux-musl ${CARGO_FEATURES} && \
|
||||
musl-strip --strip-all /tmp/target/$(cat /arch)-unknown-linux-musl/release/rpxy && \
|
||||
cp /tmp/target/$(cat /arch)-unknown-linux-musl/release/rpxy /tmp/target/release/rpxy
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@ post-quantum = ["rustls-post-quantum"]
|
|||
[dependencies]
|
||||
url = { version = "2.5.4" }
|
||||
ahash = "0.8.11"
|
||||
thiserror = "2.0.9"
|
||||
thiserror = "2.0.11"
|
||||
tracing = "0.1.41"
|
||||
async-trait = "0.1.84"
|
||||
async-trait = "0.1.85"
|
||||
base64 = "0.22.1"
|
||||
aws-lc-rs = { version = "1.12.0", default-features = false, features = [
|
||||
aws-lc-rs = { version = "1.12.2", default-features = false, features = [
|
||||
"aws-lc-sys",
|
||||
] }
|
||||
blocking = "1.6.1"
|
||||
rustls = { version = "0.23.20", default-features = false, features = [
|
||||
rustls = { version = "0.23.22", default-features = false, features = [
|
||||
"std",
|
||||
"aws_lc_rs",
|
||||
] }
|
||||
|
|
@ -32,7 +32,7 @@ rustls-platform-verifier = { version = "0.5.0" }
|
|||
rustls-acme = { path = "../submodules/rustls-acme/", default-features = false, features = [
|
||||
"aws-lc-rs",
|
||||
] }
|
||||
rustls-post-quantum = { version = "0.2.1", optional = true }
|
||||
tokio = { version = "1.42.0", default-features = false }
|
||||
rustls-post-quantum = { version = "0.2.2", optional = true }
|
||||
tokio = { version = "1.43.0", default-features = false }
|
||||
tokio-util = { version = "0.7.13", default-features = false }
|
||||
tokio-stream = { version = "0.1.17", default-features = false }
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ mimalloc = { version = "*", default-features = false }
|
|||
anyhow = "1.0.95"
|
||||
ahash = "0.8.11"
|
||||
serde = { version = "1.0.217", default-features = false, features = ["derive"] }
|
||||
tokio = { version = "1.42.0", default-features = false, features = [
|
||||
tokio = { version = "1.43.0", default-features = false, features = [
|
||||
"net",
|
||||
"rt-multi-thread",
|
||||
"time",
|
||||
|
|
@ -41,11 +41,11 @@ tokio = { version = "1.42.0", default-features = false, features = [
|
|||
"macros",
|
||||
] }
|
||||
tokio-util = { version = "0.7.13", default-features = false }
|
||||
async-trait = "0.1.84"
|
||||
async-trait = "0.1.85"
|
||||
futures-util = { version = "0.3.31", default-features = false }
|
||||
|
||||
# config
|
||||
clap = { version = "4.5.23", features = ["std", "cargo", "wrap_help"] }
|
||||
clap = { version = "4.5.27", features = ["std", "cargo", "wrap_help"] }
|
||||
toml = { version = "0.8.19", default-features = false, features = ["parse"] }
|
||||
hot_reload = "0.1.8"
|
||||
serde_ignored = "0.1.10"
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ http3 = []
|
|||
ahash = { version = "0.8.11" }
|
||||
tracing = { version = "0.1.41" }
|
||||
derive_builder = { version = "0.20.2" }
|
||||
thiserror = { version = "2.0.9" }
|
||||
thiserror = { version = "2.0.11" }
|
||||
hot_reload = { version = "0.1.8" }
|
||||
async-trait = { version = "0.1.84" }
|
||||
rustls = { version = "0.23.20", default-features = false, features = [
|
||||
async-trait = { version = "0.1.85" }
|
||||
rustls = { version = "0.23.22", default-features = false, features = [
|
||||
"std",
|
||||
"aws_lc_rs",
|
||||
] }
|
||||
|
|
@ -31,11 +31,11 @@ rustls-webpki = { version = "0.102.8", default-features = false, features = [
|
|||
"std",
|
||||
"aws_lc_rs",
|
||||
] }
|
||||
rustls-post-quantum = { version = "0.2.1", optional = true }
|
||||
x509-parser = { version = "0.16.0" }
|
||||
rustls-post-quantum = { version = "0.2.2", optional = true }
|
||||
x509-parser = { version = "0.17.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.42.0", default-features = false, features = [
|
||||
tokio = { version = "1.43.0", default-features = false, features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
] }
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ post-quantum = [
|
|||
]
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.5"
|
||||
rand = "0.9.0"
|
||||
ahash = "0.8.11"
|
||||
bytes = "1.9.0"
|
||||
derive_builder = "0.20.2"
|
||||
futures = { version = "0.3.31", features = ["alloc", "async-await"] }
|
||||
tokio = { version = "1.42.0", default-features = false, features = [
|
||||
tokio = { version = "1.43.0", default-features = false, features = [
|
||||
"net",
|
||||
"rt-multi-thread",
|
||||
"time",
|
||||
|
|
@ -50,17 +50,17 @@ tokio = { version = "1.42.0", default-features = false, features = [
|
|||
"fs",
|
||||
] }
|
||||
tokio-util = { version = "0.7.13", default-features = false }
|
||||
pin-project-lite = "0.2.15"
|
||||
async-trait = "0.1.84"
|
||||
pin-project-lite = "0.2.16"
|
||||
async-trait = "0.1.85"
|
||||
|
||||
# Error handling
|
||||
anyhow = "1.0.95"
|
||||
thiserror = "2.0.9"
|
||||
thiserror = "2.0.11"
|
||||
|
||||
# http for both server and client
|
||||
http = "1.2.0"
|
||||
http-body-util = "0.1.2"
|
||||
hyper = { version = "1.5.2", default-features = false }
|
||||
hyper = { version = "1.6.0", default-features = false }
|
||||
hyper-util = { version = "0.1.10", features = ["full"] }
|
||||
futures-util = { version = "0.3.31", default-features = false }
|
||||
futures-channel = { version = "0.3.31", default-features = false }
|
||||
|
|
@ -80,8 +80,8 @@ hyper-rustls = { version = "0.27.5", default-features = false, features = [
|
|||
# tls and cert management for server
|
||||
rpxy-certs = { path = "../rpxy-certs/", default-features = false }
|
||||
hot_reload = "0.1.8"
|
||||
rustls = { version = "0.23.20", default-features = false }
|
||||
rustls-post-quantum = { version = "0.2.1", optional = true }
|
||||
rustls = { version = "0.23.22", default-features = false }
|
||||
rustls-post-quantum = { version = "0.2.2", optional = true }
|
||||
tokio-rustls = { version = "0.26.1", features = ["early-data"] }
|
||||
|
||||
# acme
|
||||
|
|
@ -94,11 +94,11 @@ tracing = { version = "0.1.41" }
|
|||
quinn = { version = "0.11.6", optional = true }
|
||||
h3 = { version = "0.0.6", features = ["tracing"], optional = true }
|
||||
h3-quinn = { version = "0.0.7", optional = true }
|
||||
s2n-quic = { version = "1.51.0", path = "../submodules/s2n-quic/quic/s2n-quic/", default-features = false, features = [
|
||||
s2n-quic = { version = "1.52.1", path = "../submodules/s2n-quic/quic/s2n-quic/", default-features = false, features = [
|
||||
"provider-tls-rustls",
|
||||
], optional = true }
|
||||
s2n-quic-core = { version = "0.51.0", path = "../submodules/s2n-quic/quic/s2n-quic-core", default-features = false, optional = true }
|
||||
s2n-quic-rustls = { version = "0.51.0", path = "../submodules/s2n-quic/quic/s2n-quic-rustls", optional = true }
|
||||
s2n-quic-core = { version = "0.52.1", path = "../submodules/s2n-quic/quic/s2n-quic-core", default-features = false, optional = true }
|
||||
s2n-quic-rustls = { version = "0.52.1", path = "../submodules/s2n-quic/quic/s2n-quic-rustls", optional = true }
|
||||
s2n-quic-h3 = { path = "../submodules/s2n-quic/quic/s2n-quic-h3/", features = [
|
||||
"tracing",
|
||||
], optional = true }
|
||||
|
|
@ -108,7 +108,7 @@ socket2 = { version = "0.5.8", features = ["all"], optional = true }
|
|||
|
||||
# cache
|
||||
http-cache-semantics = { path = "../submodules/rusty-http-cache-semantics", default-features = false, optional = true }
|
||||
lru = { version = "0.12.5", optional = true }
|
||||
lru = { version = "0.13.0", optional = true }
|
||||
sha2 = { version = "0.10.8", default-features = false, optional = true }
|
||||
|
||||
# cookie handling for sticky cookie
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ impl LoadBalanceRandomBuilder {
|
|||
impl LoadBalanceWithPointer for LoadBalanceRandom {
|
||||
/// Returns the random index within the range
|
||||
fn get_ptr(&self, _info: Option<&LoadBalanceContext>) -> PointerToUpstream {
|
||||
let mut rng = rand::thread_rng();
|
||||
let ptr = rng.gen_range(0..self.num_upstreams);
|
||||
let mut rng = rand::rng();
|
||||
let ptr = rng.random_range(0..self.num_upstreams);
|
||||
PointerToUpstream { ptr, context: None }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,7 +226,9 @@ where
|
|||
let connector = builder.https_or_http().enable_all_versions().wrap_connector(http.clone());
|
||||
let connector_h2 = builder_h2.https_or_http().enable_http2().wrap_connector(http);
|
||||
let inner = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone())).build::<_, B1>(connector);
|
||||
let inner_h2 = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone())).build::<_, B1>(connector_h2);
|
||||
let inner_h2 = Client::builder(LocalExecutor::new(_globals.runtime_handle.clone()))
|
||||
.http2_only(true)
|
||||
.build::<_, B1>(connector_h2);
|
||||
|
||||
Ok(Self {
|
||||
inner,
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ where
|
|||
// Handle StatusCode::SWITCHING_PROTOCOLS in response
|
||||
let upgrade_in_response = extract_upgrade(res_backend.headers());
|
||||
let should_upgrade = match (upgrade_in_request.as_ref(), upgrade_in_response.as_ref()) {
|
||||
(Some(u_req), Some(u_res)) => u_req.to_ascii_lowercase() == u_res.to_ascii_lowercase(),
|
||||
(Some(u_req), Some(u_res)) => u_req.eq_ignore_ascii_case(u_res),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ pub(super) fn extract_upgrade(headers: &HeaderMap) -> Option<String> {
|
|||
.to_str()
|
||||
.unwrap_or("")
|
||||
.split(',')
|
||||
.any(|w| w.trim().to_ascii_lowercase() == header::UPGRADE.as_str().to_ascii_lowercase())
|
||||
.any(|w| w.trim().eq_ignore_ascii_case(header::UPGRADE.as_str()))
|
||||
{
|
||||
if let Some(u) = headers.get(header::UPGRADE) {
|
||||
if let Ok(m) = u.to_str() {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,18 @@ pub(super) fn update_request_line<B>(
|
|||
upstream_chosen: &Upstream,
|
||||
upstream_candidates: &UpstreamCandidates,
|
||||
) -> anyhow::Result<()> {
|
||||
// If request is grpc, HTTP/2 is required
|
||||
if req
|
||||
.headers()
|
||||
.get(header::CONTENT_TYPE)
|
||||
.map(|v| v.as_bytes().starts_with(b"application/grpc"))
|
||||
== Some(true)
|
||||
{
|
||||
debug!("Must be http/2 for gRPC request.");
|
||||
*req.version_mut() = Version::HTTP_2;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// If not specified (force_httpXX_upstream) and https, version is preserved except for http/3
|
||||
if upstream_chosen.uri.scheme() == Some(&Scheme::HTTP) {
|
||||
// Change version to http/1.1 when destination scheme is http
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit af2d016b6aa4e09586253a0459efc4af6635c79b
|
||||
Subproject commit a65d7e7000b49e6e1e14daf32baee094f4d8dacd
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit d5b5efd9de4dab3c958c50be5380652d801cc65f
|
||||
Subproject commit 2500716b70bd6e548cdf690188ded7afe6726330
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit b49cb517d0256864a9382f04fedd0e9f71531d85
|
||||
Subproject commit 78524172f54af5e3d5a0404b230d265c82eaf446
|
||||
Loading…
Add table
Add a link
Reference in a new issue