fix(server_https): use http.LocalAddrContextKey for DoH local address and avoid blocking accept loop under PROXY protocol#8149
Merged
yongtang merged 1 commit intoJun 6, 2026
Conversation
7f7373d to
8bf74af
Compare
The DoH server resolved the per-connection local address in a custom http.Server.ConnContext callback. ConnContext runs synchronously in the http.Server accept loop, so calling c.LocalAddr() there is a problem when the listener is proxyproto-wrapped: LocalAddr() triggers the PROXY-header read, which blocks the accept loop until the header arrives and head-of-line-blocks acceptance of every other connection. net/http and http2 already populate http.LocalAddrContextKey from the connection in the per-connection serving goroutine (net/http server.go, http2 server_common.go / h2_bundle.go), resolved through the same tls.Conn -> proxyproto.Conn chain. For a proxyproto connection that value is the PROXY header's destination address -- byte-identical to what the custom callback produced -- and it is set off the accept loop on both the HTTP/1.1 and HTTP/2 paths. Drop the custom ConnContext callback and the connKey type, and read http.LocalAddrContextKey in localAddr() instead. The client address is unaffected: it arrives via r.RemoteAddr, which the framework populates natively. Signed-off-by: zongqi-wang <wangzongqi@msn.com>
8bf74af to
6352d19
Compare
yongtang
approved these changes
Jun 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
This fixes my original PR #8005
NewServerHTTPSresolved the per-connection local address in a customhttp.Server.ConnContextcallback:ConnContextruns synchronously in thehttp.Serveraccept loop, before the per-connection serving goroutine starts. For a plain socketc.LocalAddr()is cheap, but when the listener is wrapped bygo-proxyproto,Conn.LocalAddr()callsensureHeaderProcessed(), which reads the PROXY header off the connection (sync.Once). If the header has not arrived yet, that read blocks inside the accept loop and head-of-line-blocks acceptance of every other connection, so connections last longer than they should.The fix
net/httpandhttp2already populatehttp.LocalAddrContextKeyfrom the connection in the per-connection serving goroutine, not the accept loop:c.serve()goroutinenet/httpserver.go:1901net/httph2_bundle.go:4552serverConnBaseContextgolang.org/x/net/http2server_common.go:216All resolve
c.LocalAddr()on the sametls.Conn → … → proxyproto.Connchain, so the value underhttp.LocalAddrContextKeyis byte-identical to what the custom callback produced — the PPv2 destination address — and it is set off the accept loop on both the HTTP/1.1 and HTTP/2 paths.So this drops the custom
ConnContextcallback and theconnKeytype and reads the framework key directly:The client address is unaffected: it arrives via
r.RemoteAddr, which the framework populates natively fromc.RemoteAddr()on both paths.Testing
go build ./core/dnsserver/— okgo vet ./core/dnsserver/— cleangofmt— cleango test ./core/dnsserver/— okgo test -race ./core/dnsserver/— okTestDoHWriterLaddrFromConnContext/TestDoHWriterLaddrFallbackstash the address underhttp.LocalAddrContextKeyinstead of the removed custom key.