MCPcopy Create free account
hub / github.com/PostHog/duckgres / handleConnect

Method handleConnect

cmd/cache-proxy/proxy.go:160–240  ·  view source on GitHub ↗

handleConnect tunnels an HTTPS CONNECT request. We don't cache — just copy bytes between client and origin. Required because SET GLOBAL http_proxy makes DuckDB tunnel all HTTPS through us, including external sources. What we CAN log: tunnel open (Info), dial / hijack errors (Warn / Error), final by

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

158
159func NewCacheProxy(store *DiskCache, peers *PeerManager, cacheHostSuffixes []string) *CacheProxy {
160 return &CacheProxy{
161 store: store,
162 peers: peers,
163 client: &http.Client{Timeout: defaultOriginTimeout},
164 connectDial: net.DialTimeout,
165 originTimeout: defaultOriginTimeout,
166 originRetryMaxAttempts: defaultOriginRetryMaxAttempts,
167 originRetryInitialBackoff: defaultOriginRetryInitialBackoff,
168 originRetryMaxBackoff: defaultOriginRetryMaxBackoff,
169 cacheHostSuffixes: cacheHostSuffixes,
170 }
171}
172
173// How long a peer's /cache/get (or a local wait on a peer's in-flight fill)
174// may block waiting for that peer's fill to land before giving up to origin.
175// Long enough for a healthy multi-block fill, short enough that a wedged peer
176// can't hold request latency hostage once the origin would have answered.
177const peerFillWait = 10 * time.Second
178
179// shouldCache returns true if the request targets a host we want to cache.
180// When no suffixes are configured, all GETs are cached (legacy behavior).
181func (p *CacheProxy) shouldCache(r *http.Request) bool {
182 if len(p.cacheHostSuffixes) == 0 {
183 return true
184 }
185 host := r.URL.Host
186 if host == "" {
187 host = r.Host
188 }
189 for _, s := range p.cacheHostSuffixes {
190 if strings.Contains(host, s) {
191 return true
192 }
193 }
194 return false
195}
196
197// handleConnect tunnels an HTTPS CONNECT request. We don't cache — just copy
198// bytes between client and origin. Required because SET GLOBAL http_proxy
199// makes DuckDB tunnel all HTTPS through us, including external sources.
200//
201// What we CAN log: tunnel open (Info), dial / hijack errors (Warn / Error),
202// final byte counts and duration on close (Info). What we CANNOT log: the
203// actual HTTP request / response inside the tunnel — TLS terminates between
204// the worker and the origin, so the encrypted bytes flowing past us are
205// opaque. An S3 501 with an XML error envelope going through CONNECT is
206// invisible to us at the body level; only "CONNECT to s3:443 → N bytes
207// in / M bytes out / closed in T ms" is recoverable.
208//
209// We log this anyway because a black hole is worse than a partial trail —
210// at least we can confirm a request was attempted, see the target host,
211// and spot dial failures. For full request/response visibility on writes,
212// DuckDB has to actually use plain HTTP via forwardUncached (s3_use_ssl =
213// false), which httpfs has been observed ignoring for some PUT paths.
214//
215// The proxy binds a hostPort and is reachable cluster-wide without
216// authentication, so the tunnel target is restricted (connectRefusalReason):
217// port 443 only, no local IP literals, optionally a hostname suffix list.

Callers 1

HandleProxyMethod · 0.95

Calls 7

NowMethod · 0.80
CloseMethod · 0.65
StartMethod · 0.45
ContextMethod · 0.45
StringMethod · 0.45
ErrorMethod · 0.45
WriteMethod · 0.45

Tested by

no test coverage detected