Skip to content

Commit c4ce94d

Browse files
authored
fix(web): preserve origin encoding and H3 overload semantics (#48)
* fix(web): preserve origin encoding and H3 overload semantics * docs(web): clarify custom transport policy wording
1 parent 556f994 commit c4ce94d

7 files changed

Lines changed: 950 additions & 2 deletions

File tree

‎docs/WEB_COVER.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ HTTP/2 CONNECT presented to the public origin is always treated as cover,
4040
including when it carries an otherwise valid ticket: the handler removes
4141
`Proxy-Authorization` before delegation and never dials its authority.
4242

43+
Public physical-connection limits are separate from authenticated tunnel-stream
44+
limits, and the combined TCP/UDP server shares its global and per-source
45+
connection allowance. Source builds after v1.0.1 reject an excess H3 connection
46+
with `H3_EXCESSIVE_LOAD` (`0x107`), rather than reusing the native relay's code,
47+
which means `H3_INTERNAL_ERROR` in [HTTP/3](https://www.rfc-editor.org/rfc/rfc9114.html#section-8.1).
48+
Rejection happens before HTTP dispatch;
49+
the existing admitted connection remains usable and closing it releases capacity.
50+
This is overload handling, not a tunnel authentication response.
51+
4352
### Website WebSocket support in source builds
4453

4554
Source builds after v1.0.1 also forward valid HTTP/1.1 WebSocket upgrades to
@@ -202,6 +211,17 @@ the upstream cannot be reached. Consequently, an upstream that requires an
202211
`Authorization` request header is not suitable without a separate authorized
203212
front end.
204213

214+
Source builds after v1.0.1 disable automatic compression negotiation and response
215+
decompression on the proxy's private default upstream transport. The visitor's
216+
`Accept-Encoding` remains unchanged: explicitly requested gzip still works, and
217+
the origin's encoded bytes, `Content-Encoding`, length, digest and ETag remain
218+
together. This avoids rewriting `no-transform` content while retaining metadata
219+
for the old bytes; see [HTTP message transformations](https://www.rfc-editor.org/rfc/rfc9110.html#section-7.7).
220+
It does not verify the website's digest or establish browser-like fingerprints.
221+
Applications supplying a custom RoundTripper retain their own negotiation/decoding
222+
policy and must configure transparent forwarding themselves. Static cover,
223+
authenticated tunnel payloads and the published v1.0.1 binary are unchanged.
224+
205225
#### Optional fixed public origin in source builds
206226

207227
Source builds after v1.0.1 can separate the website's public HTTP identity

‎internal/cover/handler.go‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ var hopByHopHeaders = [...]string{
3131
// NewReverseProxyHandler returns a reverse proxy that can dial only origin.
3232
// The requester controls the path, query, and ordinary end-to-end headers, but
3333
// never the upstream scheme, authority, or Host header.
34+
// A nil transport does not add compression negotiation or decode responses.
35+
// Supplied transports retain their own compression policy.
3436
func NewReverseProxyHandler(origin *url.URL, transport http.RoundTripper) (http.Handler, error) {
3537
target, err := normalizeOrigin(origin)
3638
if err != nil {
@@ -43,6 +45,9 @@ func newReverseProxyHandler(target *url.URL, transport http.RoundTripper, public
4345
if transport == nil {
4446
defaultTransport := http.DefaultTransport.(*http.Transport).Clone()
4547
defaultTransport.Proxy = nil
48+
// Forward the visitor's encoding preferences and the origin's encoded
49+
// bytes together with their metadata, including no-transform/digests.
50+
defaultTransport.DisableCompression = true
4651
transport = defaultTransport
4752
}
4853

‎internal/cover/public_origin.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import (
1414
// and TLS still use upstream; public supplies only the outbound Host and the
1515
// trusted X-Forwarded-Host/Proto values. Both URLs must be root origins.
1616
//
17-
// Origin, Referer, cookies, redirects, and content are never rewritten. The
17+
// Origin, Referer, cookies, redirects, and content are not rewritten by the
18+
// handler. Supplied transports retain their own compression policy. The
1819
// upstream must generate its own public URLs and retain its CSRF/Origin checks;
1920
// an absent Origin is not evidence that a request is safe. Its trusted-header
2021
// whitelist must use only the proxy-owned forwarding fields, not arbitrary

0 commit comments

Comments
 (0)