mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-19 04:59:56 +00:00
The MultiTransport's job is per-request dispatch between the embedded NetBird transport and the stdlib transport based on the direct_upstream context flag — about 25 lines of code. The header/body debug logging that was bundled in pulls in: - io.ReadAll on every request body, even when log level is above debug. Forces buffering of streaming POSTs (LLM completions, file uploads) before they reach the upstream transport. - A header redaction list and a body-snippet cap that duplicate concerns already covered by netbird.go's per-roundtrip log. netbird.go already emits method/host/url/account/duration/status/err at debug level on every roundtrip; nothing in the private-service feature needs the extra header+body dump. - Drop logUpstreamRequest, formatHeaders, redactHeaderValue, snapshotRequestBody, and the upstreamLogBodyMax constant. - Drop the logger field and the trailing nil arg from NewMultiTransport; proxy/server.go and the tests updated accordingly.
69 lines
2.5 KiB
Go
69 lines
2.5 KiB
Go
package roundtrip
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// MultiTransport dispatches each request to either the embedded NetBird
|
|
// http.RoundTripper or a stdlib http.Transport based on a per-request
|
|
// context flag set by the reverse-proxy rewrite step. When the flag is
|
|
// absent (the default for every existing target), requests follow the
|
|
// embedded NetBird path — current behaviour, preserved.
|
|
//
|
|
// The stdlib branch is used when a target was configured with
|
|
// direct_upstream=true. It dials via the host's network stack, which is
|
|
// what private (`netbird proxy`) deployments and centralised proxies
|
|
// fronting host-reachable upstreams (public APIs, LAN services,
|
|
// localhost sidecars) want.
|
|
type MultiTransport struct {
|
|
embedded http.RoundTripper
|
|
direct *http.Transport
|
|
insecure *http.Transport
|
|
}
|
|
|
|
// NewMultiTransport wires both branches. embedded is the existing NetBird
|
|
// roundtripper; the direct branches are constructed here with sensible
|
|
// defaults that mirror Go's stdlib defaults plus a dial-timeout wrapper
|
|
// honouring the per-request value attached via types.WithDialTimeout.
|
|
// Pass embedded=nil to disable the WG branch entirely (every request
|
|
// will route direct, regardless of the context flag).
|
|
func NewMultiTransport(embedded http.RoundTripper) *MultiTransport {
|
|
dialer := &net.Dialer{
|
|
Timeout: 30 * time.Second,
|
|
KeepAlive: 30 * time.Second,
|
|
}
|
|
direct := &http.Transport{
|
|
DialContext: dialWithTimeout(dialer.DialContext),
|
|
ForceAttemptHTTP2: true,
|
|
MaxIdleConns: 100,
|
|
IdleConnTimeout: 90 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
}
|
|
insecure := direct.Clone()
|
|
insecure.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec // matches the embedded NetBird transport's per-target opt-in
|
|
|
|
return &MultiTransport{
|
|
embedded: embedded,
|
|
direct: direct,
|
|
insecure: insecure,
|
|
}
|
|
}
|
|
|
|
// RoundTrip dispatches by reading the direct-upstream flag from the request
|
|
// context. When set, the request is forwarded via the stdlib transport,
|
|
// honouring the existing per-request skip-TLS-verify flag. Otherwise it
|
|
// goes through the embedded NetBird roundtripper.
|
|
func (m *MultiTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
if DirectUpstreamFromContext(req.Context()) || m.embedded == nil {
|
|
if skipTLSVerifyFromContext(req.Context()) {
|
|
return m.insecure.RoundTrip(req)
|
|
}
|
|
return m.direct.RoundTrip(req)
|
|
}
|
|
return m.embedded.RoundTrip(req)
|
|
}
|