diff --git a/config/options.go b/config/options.go index f7d7bda0..b266a470 100644 --- a/config/options.go +++ b/config/options.go @@ -59,6 +59,7 @@ const ( defaultMetricsCollector = false defaultMetricsRefreshInterval = 60 defaultMetricsAllowedNetworks = "127.0.0.1/8" + defaultUserAgent = "" ) // Options contains configuration options. @@ -112,6 +113,7 @@ type Options struct { metricsCollector bool metricsRefreshInterval int metricsAllowedNetworks []string + userAgent string } // NewOptions returns Options with default values. @@ -164,6 +166,7 @@ func NewOptions() *Options { metricsCollector: defaultMetricsCollector, metricsRefreshInterval: defaultMetricsRefreshInterval, metricsAllowedNetworks: []string{defaultMetricsAllowedNetworks}, + userAgent: defaultUserAgent, } } @@ -422,6 +425,11 @@ func (o *Options) MetricsAllowedNetworks() []string { return o.metricsAllowedNetworks } +// UserAgent returns the global User-Agent header for miniflux. +func (o *Options) UserAgent() string { + return o.userAgent +} + func (o *Options) String() string { var builder strings.Builder builder.WriteString(fmt.Sprintf("LOG_DATE_TIME: %v\n", o.logDateTime)) @@ -473,5 +481,6 @@ func (o *Options) String() string { builder.WriteString(fmt.Sprintf("METRICS_COLLECTOR: %v\n", o.metricsCollector)) builder.WriteString(fmt.Sprintf("METRICS_REFRESH_INTERVAL: %v\n", o.metricsRefreshInterval)) builder.WriteString(fmt.Sprintf("METRICS_ALLOWED_NETWORKS: %v\n", o.metricsAllowedNetworks)) + builder.WriteString(fmt.Sprintf("USER_AGENT: %v\n", o.userAgent)) return builder.String() } diff --git a/config/parser.go b/config/parser.go index 0f4f40d4..45fd08a7 100644 --- a/config/parser.go +++ b/config/parser.go @@ -184,6 +184,8 @@ func (p *Parser) parseLines(lines []string) (err error) { p.opts.metricsRefreshInterval = parseInt(value, defaultMetricsRefreshInterval) case "METRICS_ALLOWED_NETWORKS": p.opts.metricsAllowedNetworks = parseStringList(value, []string{defaultMetricsAllowedNetworks}) + case "USER_AGENT": + p.opts.userAgent = parseString(value, defaultUserAgent) } } diff --git a/http/client/client.go b/http/client/client.go index adbfc369..cc137a59 100644 --- a/http/client/client.go +++ b/http/client/client.go @@ -72,9 +72,13 @@ func New(url string) *Client { // NewClientWithConfig initializes a new HTTP client with application config options. func NewClientWithConfig(url string, opts *config.Options) *Client { + userAgent := opts.UserAgent() + if userAgent == "" { + userAgent = DefaultUserAgent + } return &Client{ inputURL: url, - requestUserAgent: DefaultUserAgent, + requestUserAgent: userAgent, ClientTimeout: opts.HTTPClientTimeout(), ClientMaxBodySize: opts.HTTPClientMaxBodySize(), ClientProxyURL: opts.HTTPClientProxy(), diff --git a/http/client/client_test.go b/http/client/client_test.go index fb66d1ec..74d67199 100644 --- a/http/client/client_test.go +++ b/http/client/client_test.go @@ -4,7 +4,12 @@ package client // import "miniflux.app/http/client" -import "testing" +import ( + "os" + "testing" + + "miniflux.app/config" +) func TestClientWithDelay(t *testing.T) { clt := New("http://httpbin.org/delay/5") @@ -49,3 +54,21 @@ func TestClientWithBasicAuth(t *testing.T) { t.Fatalf(`The client should be authenticated successfully: %v`, err) } } + +func TestClientRequestUserAgent(t *testing.T) { + clt := New("http://httpbin.org") + if clt.requestUserAgent != DefaultUserAgent { + t.Errorf(`The client had default User-Agent %q, wanted %q`, clt.requestUserAgent, DefaultUserAgent) + } + + userAgent := "Custom User Agent" + os.Setenv("USER_AGENT", userAgent) + opts, err := config.NewParser().ParseEnvironmentVariables() + if err != nil { + t.Fatalf(`Parsing config failed: %v`, err) + } + clt = NewClientWithConfig("http://httpbin.org", opts) + if clt.requestUserAgent != userAgent { + t.Errorf(`The client had User-Agent %q, wanted %q`, clt.requestUserAgent, userAgent) + } +}