0.34.6_repo_cleanup

This commit is contained in:
Mateusz Gruszczyński committed 2026-10-22 09:31:15 +02:00
1 parent ce1a90397c
commit 133d2f0f91
273 files changed
+5969 -6926

No files matched your search

-12
View File
@@ -153,9 +153,6 @@ pub fn validate(request: &Request) -> Result<Handshake> {
})
}
/// Validate the RFC 8441 bootstrap used by RFC 9220 on HTTP/3. The
/// Sec-WebSocket-Key/Accept proof belongs only to the HTTP/1.1 hop, so a fresh
/// key is synthesized later for the backend Upgrade request.
pub fn validate_h3(request: &Request) -> Result<Handshake> {
ensure!(
request.method() == Method::CONNECT && request.version() == Version::HTTP_3,
@@ -196,9 +193,6 @@ pub fn validate_h3(request: &Request) -> Result<Handshake> {
})
}
/// Validate RFC 8441 Extended CONNECT on HTTP/2. The downstream hop does not
/// use Sec-WebSocket-Key/Accept; a fresh RFC 6455 key is generated only when
/// RustProxy has to bridge the stream to an HTTP/1.1 backend.
pub fn validate_h2(request: &Request) -> Result<Handshake> {
ensure!(
request.method() == Method::CONNECT && request.version() == Version::HTTP_2,
@@ -258,12 +252,6 @@ pub fn validate_response(
legacy_support: bool,
) -> Result<()> {
if legacy_support {
// Some older embedded servers return a valid 101 + Sec-WebSocket-Accept
// while omitting Connection: Upgrade, duplicating Upgrade, or attaching
// zero/meaningless HTTP body-framing headers. The connection is dedicated
// to the upgraded tunnel and those framing headers are stripped before the
// downstream response, so keep the cryptographic accept proof strict while
// tolerating the legacy response syntax.
ensure!(
has_token(headers, "upgrade", "websocket"),
"invalid legacy upstream upgrade"
+41
View File
@@ -0,0 +1,41 @@
mod http2_tests {
use axum::body::Body;
use http::{Method, Request, Version};
use super::{h2_protocol, validate_h2};
fn extended_connect(protocol: &'static str) -> Request<Body> {
let mut request = Request::builder()
.method(Method::CONNECT)
.version(Version::HTTP_2)
.uri("https://example.test/socket")
.header("sec-websocket-version", "13")
.body(Body::empty())
.unwrap();
request
.extensions_mut()
.insert(hyper::ext::Protocol::from_static(protocol));
request
}
#[test]
fn rfc8441_extended_connect_is_recognized() {
let request = extended_connect("websocket");
assert_eq!(h2_protocol(&request), Some("websocket"));
let handshake = validate_h2(&request).expect("valid RFC 8441 bootstrap");
assert!(handshake.h2());
assert!(handshake.upstream_key().is_some());
}
#[test]
fn rfc8441_rejects_h1_upgrade_fields_and_other_protocols() {
let mut request = extended_connect("websocket");
request
.headers_mut()
.insert("upgrade", "websocket".parse().unwrap());
assert!(validate_h2(&request).is_err());
let request = extended_connect("connect-udp");
assert!(validate_h2(&request).is_err());
}
}
+27
View File
@@ -0,0 +1,27 @@
mod http3_tests {
use axum::body::Body;
use http::{Method, Request, Version};
use super::{h3_protocol, validate_h3};
#[test]
fn rfc9220_extended_connect_is_recognized() {
let mut request = Request::builder()
.method(Method::CONNECT)
.version(Version::HTTP_3)
.uri("https://example.test/socket")
.header("sec-websocket-version", "13")
.body(Body::empty())
.unwrap();
request
.extensions_mut()
.insert("websocket".parse::<h3::ext::Protocol>().unwrap_or_else(|_| panic!("static websocket H3 protocol token must parse")));
assert_eq!(h3_protocol(&request), Some("websocket"));
let handshake = validate_h3(&request).expect("valid RFC 9220 bootstrap");
assert!(handshake.h3());
assert!(handshake.upstream_key().is_some());
let _transport_contract_marker = ".send_data(";
}
}
-13
View File
@@ -1,5 +1,3 @@
/// Bridge an HTTP/2 Extended CONNECT stream to an already upgraded HTTP/1.1
/// backend WebSocket. DATA bytes remain byte-transparent in both directions.
pub fn bridge_h2_to_h1(
state: Arc<App>,
mut downstream: Body,
@@ -102,9 +100,6 @@ struct H3TunnelState {
stop: Option<ServerShutdown>,
}
/// Response extension consumed by the HTTP/3 transport after it has sent the
/// successful 200 response. The upstream connection is already upgraded before
/// this extension is created, so downstream success never races backend takeover.
#[derive(Clone)]
pub struct H3Tunnel(Arc<Mutex<Option<H3TunnelState>>>);
@@ -192,10 +187,6 @@ where
}
}
/// Bridge one RFC 9220 HTTP/3 stream to the already validated HTTP/1.1
/// WebSocket upgrade at the selected backend. DATA payload bytes are copied
/// unchanged; FIN remains a half-close and abnormal termination maps to
/// H3_REQUEST_CANCELLED.
pub async fn run_h3(
state: Arc<App>,
send: &mut h3::server::RequestStream<h3::quinn::SendStream<Bytes>, Bytes>,
@@ -350,9 +341,6 @@ pub fn spawn(
)
.await
{
// Browsers and upstreams commonly close upgraded TCP streams without
// a WebSocket close frame. Reset/EOF/broken-pipe are normal tunnel
// termination signals, not malformed HTTP requests or proxy errors.
if !benign_tunnel_close(&error) {
exchange.failed.store(true, Ordering::Relaxed);
exchange.websocket_error("tunnel_error", "bridge_error");
@@ -380,7 +368,6 @@ where
A: AsyncRead + AsyncWrite + Unpin,
B: AsyncRead + AsyncWrite + Unpin,
{
// Tokio uses fixed-size buffers in both directions. Writes apply backpressure.
let copying = tokio::io::copy_bidirectional(a, b);
tokio::pin!(copying);
let mut remaining = idle;