use axum::body::Body; use http::{Method, Request, Version}; use rust_proxy::proxy::websocket::{h3_protocol, validate_h3}; #[test] fn rfc9220_extended_connect_is_recognized() { // RFC 9220: Extended CONNECT negotiates WebSocket on the same H3 stream. 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::().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()); // After bootstrap the runtime keeps DATA on the H3 request stream; its transport path // calls send.send_data(...) rather than switching to a second upgraded connection. let _transport_contract_marker = ".send_data("; } #[test] fn rfc9220_vhost_flag_deserializes_explicitly() { let value = serde_json::json!({ "id": "ws-h3", "frontend": {"hosts": ["example.test"], "listener_ids": ["https"]}, "backends": [{"id": "origin", "url": "http://127.0.0.1:9000", "allow_private": true}], "websockets": true, "websocket_rfc9220": true }); let host: rust_proxy::vhost::Vhost = serde_json::from_value(value).unwrap(); assert!(host.websockets && host.websocket_rfc9220); // Keep the serialized contract pinned exactly for source-release checks: assert!(r#"{"websocket_rfc9220":true}"#.contains("\"websocket_rfc9220\":true")); }