Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lx9FNLG2CqeBbVGGd9bFsP
35 lines
1.1 KiB
Go
35 lines
1.1 KiB
Go
package netpolicy
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// HTTPClient returns a client whose every connection goes through the policy.
|
|
// It follows at most MaxRedirects redirects, only to http/https, and each
|
|
// target is checked again (literal IPs here, names by the dialer). Environment
|
|
// proxies are not used.
|
|
func (p *Policy) HTTPClient(timeout time.Duration) *http.Client {
|
|
tr := &http.Transport{
|
|
Proxy: nil,
|
|
DialContext: p.DialContext,
|
|
ForceAttemptHTTP2: true,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ResponseHeaderTimeout: timeout,
|
|
MaxIdleConns: 10,
|
|
IdleConnTimeout: 30 * time.Second,
|
|
}
|
|
return &http.Client{Transport: tr, Timeout: timeout, CheckRedirect: p.checkRedirect}
|
|
}
|
|
|
|
func (p *Policy) checkRedirect(req *http.Request, via []*http.Request) error {
|
|
if len(via) > MaxRedirects {
|
|
return fmt.Errorf("%w (limit %d)", ErrTooManyRedirects, MaxRedirects)
|
|
}
|
|
if s := req.URL.Scheme; s != "http" && s != "https" {
|
|
return fmt.Errorf("netpolicy: redirect to unsupported scheme %q", s)
|
|
}
|
|
return p.CheckContext(req.Context(), req.URL.Hostname())
|
|
}
|