mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2025-10-26 11:27:18 +00:00
Squashed commit of the following:
commit 056fd6f64b2eb883154e9806e9c71bdf28cd9883
Merge: bd505ab68 cd79a4ac7
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Sep 2 19:45:17 2025 +0300
Merge branch 'master' into 7979-custom-user-agent
commit bd505ab68591a771d33205a45460f58b38110c9e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Sep 2 19:23:55 2025 +0300
all: imp code
commit ee53f1d625eac3c2cd7310adf97e35ec81d73a3a
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Sep 2 13:08:53 2025 +0300
all: custom user agent
87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package home
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
|
"github.com/AdguardTeam/golibs/httphdr"
|
|
)
|
|
|
|
// customUserAgentTransport sets the User-Agent on requests when it is missing
|
|
// to prevent Go from adding its default User-Agent.
|
|
type customUserAgentTransport struct {
|
|
// transport is the underlying HTTP transport being wrapped. It must not be
|
|
// nil.
|
|
transport http.RoundTripper
|
|
|
|
// userAgent is the custom User-Agent string for requests. It must not be
|
|
// empty.
|
|
userAgent string
|
|
}
|
|
|
|
// newCustomUserAgentTransport returns a properly initialized
|
|
// *customUserAgentTransport. rt must not be nil. ua must not be empty.
|
|
func newCustomUserAgentTransport(rt http.RoundTripper, ua string) (t *customUserAgentTransport) {
|
|
return &customUserAgentTransport{
|
|
transport: rt,
|
|
userAgent: ua,
|
|
}
|
|
}
|
|
|
|
// type check
|
|
var _ http.RoundTripper = (*customUserAgentTransport)(nil)
|
|
|
|
// RoundTrip implements the [http.RoundTripper] interface for
|
|
// *customUserAgentTransport.
|
|
func (t *customUserAgentTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
|
|
if req.Header.Get(httphdr.UserAgent) == "" {
|
|
req = req.Clone(req.Context())
|
|
req.Header.Set(httphdr.UserAgent, t.userAgent)
|
|
}
|
|
|
|
return t.transport.RoundTrip(req)
|
|
}
|
|
|
|
// httpClient returns a new HTTP client that uses the AdGuard Home's own DNS
|
|
// server for resolving hostnames. The resulting client should not be used
|
|
// until [Context.dnsServer] is initialized. tlsMgr must not be nil.
|
|
//
|
|
// TODO(a.garipov, e.burkov): This is rather messy. Refactor.
|
|
func httpClient(tlsMgr *tlsManager) (c *http.Client) {
|
|
// Do not use Context.dnsServer.DialContext directly in the struct literal
|
|
// below, since Context.dnsServer may be nil when this function is called.
|
|
dialContext := func(ctx context.Context, network, addr string) (conn net.Conn, err error) {
|
|
return globalContext.dnsServer.DialContext(ctx, network, addr)
|
|
}
|
|
|
|
tr := newCustomUserAgentTransport(&http.Transport{
|
|
DialContext: dialContext,
|
|
Proxy: httpProxy,
|
|
TLSClientConfig: &tls.Config{
|
|
RootCAs: tlsMgr.rootCerts,
|
|
CipherSuites: tlsMgr.customCipherIDs,
|
|
MinVersion: tls.VersionTLS12,
|
|
},
|
|
}, aghhttp.UserAgent())
|
|
|
|
return &http.Client{
|
|
// TODO(a.garipov): Make configurable.
|
|
Timeout: writeTimeout,
|
|
Transport: tr,
|
|
}
|
|
}
|
|
|
|
// httpProxy returns parses and returns an HTTP proxy URL from the config, if
|
|
// any.
|
|
func httpProxy(_ *http.Request) (u *url.URL, err error) {
|
|
if config.ProxyURL == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
return url.Parse(config.ProxyURL)
|
|
}
|