From 857f8f55b8bc84a145d484ef5f38eed0bc1710db Mon Sep 17 00:00:00 2001 From: klzgrad Date: Thu, 30 Apr 2026 22:38:52 +0800 Subject: [PATCH] net/spdy: Support tunnel preamble requests --- src/net/spdy/spdy_proxy_client_socket.cc | 54 ++++++++++++++++++++++++ src/net/spdy/spdy_proxy_client_socket.h | 1 + 2 files changed, 55 insertions(+) diff --git a/src/net/spdy/spdy_proxy_client_socket.cc b/src/net/spdy/spdy_proxy_client_socket.cc index 804ef7ba72..a8ae6ae9dd 100644 --- a/src/net/spdy/spdy_proxy_client_socket.cc +++ b/src/net/spdy/spdy_proxy_client_socket.cc @@ -58,6 +58,15 @@ SpdyProxyClientSocket::SpdyProxyClientSocket( source_dependency_(source_net_log.source()) { request_.method = "CONNECT"; request_.url = GURL("https://" + endpoint.ToString()); + if (endpoint.host() == "preamble") { + preamble_index_ = endpoint.port(); + CHECK(!proxy_chain.is_direct()); + CHECK_EQ(proxy_chain_index, proxy_chain.length() - 1); + const ProxyServer& proxy_server = + proxy_chain.GetProxyServer(proxy_chain_index); + CHECK(proxy_server.is_secure_http_like()); + request_.url = GURL("https://" + proxy_server.host_port_pair().ToString()); + } net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source_net_log.source()); net_log_.AddEventReferencingSource( @@ -425,6 +434,12 @@ int SpdyProxyClientSocket::DoCalculateHeaders() { } if (proxy_delegate_) { + if (preamble_index_.has_value()) { + proxy_delegate_->OnBeforePreambleRequest(proxy_chain_, proxy_chain_index_, + *preamble_index_, + proxy_delegate_headers_); + return OK; + } ASSIGN_OR_RETURN( proxy_delegate_headers_, proxy_delegate_->OnBeforeTunnelRequest( @@ -452,6 +467,32 @@ int SpdyProxyClientSocket::DoCalculateHeadersComplete(int result) { proxy_delegate_headers_.RemoveHeader("fastopen"); use_fastopen_ = true; } + if (preamble_index_.has_value()) { + authorization_headers_.Clear(); + std::optional method = + proxy_delegate_headers_.GetHeaderView("_method"); + if (method.has_value()) { + request_.method = *method; + proxy_delegate_headers_.RemoveHeader("_method"); + } else { + LOG(ERROR) << "Missing preamble method"; + return ERR_INVALID_ARGUMENT; + } + std::optional path = + proxy_delegate_headers_.GetHeaderView("_path"); + if (path.has_value()) { + if (*path == "/" || path->ends_with(".css")) { + spdy_stream_->SetPriority(HIGHEST); + } else if (path->ends_with(".js")) { + spdy_stream_->SetPriority(LOW); + } + request_.url = request_.url.Resolve(*path); + proxy_delegate_headers_.RemoveHeader("_path"); + } else { + LOG(ERROR) << "Missing preamble path"; + return ERR_INVALID_ARGUMENT; + } + } request_.extra_headers.MergeFrom(proxy_delegate_headers_); return result; } @@ -471,6 +512,10 @@ int SpdyProxyClientSocket::DoSendRequest() { CreateSpdyHeadersFromHttpRequest(request_, std::nullopt, request_.extra_headers, &headers); + if (preamble_index_.has_value()) { + return spdy_stream_->SendRequestHeaders(std::move(headers), + NO_MORE_DATA_TO_SEND); + } return spdy_stream_->SendRequestHeaders(std::move(headers), MORE_DATA_TO_SEND); } @@ -514,6 +559,11 @@ int SpdyProxyClientSocket::DoProcessResponseHeaders() { next_state_ = STATE_PROCESS_RESPONSE_HEADERS_COMPLETE; if (proxy_delegate_) { + if (preamble_index_.has_value()) { + proxy_delegate_->OnPreambleHeadersReceived( + proxy_chain_, proxy_chain_index_, *preamble_index_, response_.headers); + return OK; + } return proxy_delegate_->OnTunnelHeadersReceived( proxy_chain_, proxy_chain_index_, *response_.headers, base::BindOnce(&SpdyProxyClientSocket::OnIOComplete, @@ -545,6 +595,10 @@ int SpdyProxyClientSocket::DoProcessResponseCode() { return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_); default: + if (preamble_index_.has_value()) { + next_state_ = STATE_OPEN; + return OK; + } // Ignore response to avoid letting the proxy impersonate the target // server. (See http://crbug.com/137891.) return ERR_TUNNEL_CONNECTION_FAILED; diff --git a/src/net/spdy/spdy_proxy_client_socket.h b/src/net/spdy/spdy_proxy_client_socket.h index aca80e455b..cd3c408529 100644 --- a/src/net/spdy/spdy_proxy_client_socket.h +++ b/src/net/spdy/spdy_proxy_client_socket.h @@ -201,6 +201,7 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket, bool was_ever_used_ = false; bool use_fastopen_ = false; + std::optional preamble_index_; bool read_headers_pending_ = false; const NetLogWithSource net_log_;