Support custom headers when fetching configuration through HTTP
This commit is contained in:
parent
188ef84c4f
commit
33f0aed5ea
7 changed files with 86 additions and 28 deletions
|
@ -24,10 +24,12 @@ var _ provider.Provider = (*Provider)(nil)
|
|||
|
||||
// Provider is a provider.Provider implementation that queries an HTTP(s) endpoint for a configuration.
|
||||
type Provider struct {
|
||||
Endpoint string `description:"Load configuration from this endpoint." json:"endpoint" toml:"endpoint" yaml:"endpoint"`
|
||||
PollInterval ptypes.Duration `description:"Polling interval for endpoint." json:"pollInterval,omitempty" toml:"pollInterval,omitempty" yaml:"pollInterval,omitempty" export:"true"`
|
||||
PollTimeout ptypes.Duration `description:"Polling timeout for endpoint." json:"pollTimeout,omitempty" toml:"pollTimeout,omitempty" yaml:"pollTimeout,omitempty" export:"true"`
|
||||
TLS *types.ClientTLS `description:"Enable TLS support." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
|
||||
Endpoint string `description:"Load configuration from this endpoint." json:"endpoint" toml:"endpoint" yaml:"endpoint"`
|
||||
PollInterval ptypes.Duration `description:"Polling interval for endpoint." json:"pollInterval,omitempty" toml:"pollInterval,omitempty" yaml:"pollInterval,omitempty" export:"true"`
|
||||
PollTimeout ptypes.Duration `description:"Polling timeout for endpoint." json:"pollTimeout,omitempty" toml:"pollTimeout,omitempty" yaml:"pollTimeout,omitempty" export:"true"`
|
||||
Headers map[string]string `description:"Define custom headers to be sent to the endpoint." json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty" export:"true"`
|
||||
TLS *types.ClientTLS `description:"Enable TLS support." json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
|
||||
|
||||
httpClient *http.Client
|
||||
lastConfigurationHash uint64
|
||||
}
|
||||
|
@ -139,9 +141,18 @@ func (p *Provider) updateConfiguration(configurationChan chan<- dynamic.Message)
|
|||
|
||||
// fetchConfigurationData fetches the configuration data from the configured endpoint.
|
||||
func (p *Provider) fetchConfigurationData() ([]byte, error) {
|
||||
res, err := p.httpClient.Get(p.Endpoint)
|
||||
req, err := http.NewRequest(http.MethodGet, p.Endpoint, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("create fetch request: %w", err)
|
||||
}
|
||||
|
||||
for k, v := range p.Headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
res, err := p.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("do fetch request: %w", err)
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
|
|
@ -69,35 +69,53 @@ func TestProvider_SetDefaults(t *testing.T) {
|
|||
|
||||
func TestProvider_fetchConfigurationData(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
handler func(rw http.ResponseWriter, req *http.Request)
|
||||
expData []byte
|
||||
expErr bool
|
||||
desc string
|
||||
statusCode int
|
||||
headers map[string]string
|
||||
expData []byte
|
||||
expErr require.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
desc: "should return the fetched configuration data",
|
||||
expData: []byte("{}"),
|
||||
handler: func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
_, _ = fmt.Fprintf(rw, "{}")
|
||||
},
|
||||
desc: "should return the fetched configuration data",
|
||||
statusCode: http.StatusOK,
|
||||
expData: []byte("{}"),
|
||||
expErr: require.NoError,
|
||||
},
|
||||
{
|
||||
desc: "should return an error if endpoint does not return an OK status code",
|
||||
expErr: true,
|
||||
handler: func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.WriteHeader(http.StatusNoContent)
|
||||
desc: "should send configured headers",
|
||||
statusCode: http.StatusOK,
|
||||
headers: map[string]string{
|
||||
"Foo": "bar",
|
||||
"Bar": "baz",
|
||||
},
|
||||
expData: []byte("{}"),
|
||||
expErr: require.NoError,
|
||||
},
|
||||
{
|
||||
desc: "should return an error if endpoint does not return an OK status code",
|
||||
statusCode: http.StatusInternalServerError,
|
||||
expErr: require.Error,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(test.handler))
|
||||
defer server.Close()
|
||||
handlerCalled := false
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
handlerCalled = true
|
||||
|
||||
for k, v := range test.headers {
|
||||
assert.Equal(t, v, req.Header.Get(k))
|
||||
}
|
||||
|
||||
rw.WriteHeader(test.statusCode)
|
||||
_, _ = rw.Write([]byte("{}"))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
provider := Provider{
|
||||
Endpoint: server.URL,
|
||||
Endpoint: srv.URL,
|
||||
Headers: test.headers,
|
||||
PollInterval: ptypes.Duration(1 * time.Second),
|
||||
PollTimeout: ptypes.Duration(1 * time.Second),
|
||||
}
|
||||
|
@ -106,12 +124,9 @@ func TestProvider_fetchConfigurationData(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
configData, err := provider.fetchConfigurationData()
|
||||
if test.expErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
test.expErr(t, err)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.True(t, handlerCalled)
|
||||
assert.Equal(t, test.expData, configData)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue