Skip to content

Commit 366e7b6

Browse files
authored
Merge pull request #7 from andreykaipov/feature/remote-file-headers
add optional headers to file backend
2 parents fc03353 + fcca15f commit 366e7b6

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

file/client.go

+28-1
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,41 @@ type Client struct {
2929
httpClient http.Client
3030
}
3131

32+
// transport is a wrapper around any provided underlying transport that will
33+
// also add any provided headers to any request made with this transport.
34+
type transport struct {
35+
Headers map[string]string
36+
UnderlyingTransport http.RoundTripper
37+
}
38+
39+
// RoundTrip satisfies the RoundTripper interface for our custom transport above.
40+
// If an underlying transport is not provided, we default to http.DefaultTransport.
41+
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
42+
for k, v := range t.Headers {
43+
req.Header.Add(k, v)
44+
}
45+
if t.UnderlyingTransport == nil {
46+
t.UnderlyingTransport = http.DefaultTransport
47+
}
48+
return t.UnderlyingTransport.RoundTrip(req)
49+
}
50+
3251
// New returns a new FileClient
3352
// The filepath can be a local path to a file or a remote http/https location.
34-
func New(filepath string) (*Client, error) {
53+
func New(filepath string, opts ...Option) (*Client, error) {
54+
var options Options
55+
for _, o := range opts {
56+
o(&options)
57+
}
58+
3559
c := &Client{filepath: filepath}
3660
if strings.HasPrefix(filepath, "http://") || strings.HasPrefix(filepath, "https://") {
3761
c.isURL = true
3862
c.httpClient = http.Client{
3963
Timeout: 5 * time.Second,
64+
Transport: &transport{
65+
Headers: options.Headers,
66+
},
4067
}
4168
}
4269
return c, nil

file/client_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ package file
1010

1111
import (
1212
"context"
13+
"fmt"
1314
"io/ioutil"
15+
"net/http"
16+
"net/http/httptest"
1417
"os"
1518
"sync"
1619
"testing"
@@ -173,3 +176,31 @@ func (s *FilterSuite) TestWatchPrefixCancel(t *C) {
173176
cancel()
174177
wg.Wait()
175178
}
179+
180+
func (s *FilterSuite) TestHTTPWithHeaders(t *C) {
181+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
182+
fmt.Fprintln(w, "---")
183+
for name, value := range r.Header {
184+
fmt.Fprintf(w, "%s: %q\n", name, value[0])
185+
}
186+
}))
187+
defer ts.Close()
188+
189+
c, _ := New(ts.URL, WithHeaders(map[string]string{
190+
"X-Test-Token": "Hi",
191+
"Content-Type": "application/json",
192+
}))
193+
vals, err := c.GetValues([]string{"/"})
194+
if err != nil {
195+
t.Fatal(err)
196+
}
197+
198+
testHeader := func(header, expected string) {
199+
if vals[header] != expected {
200+
t.Errorf("Expected %q to equal %q", header, expected)
201+
}
202+
}
203+
testHeader("/X-Test-Token", "Hi")
204+
testHeader("/Content-Type", "application/json")
205+
testHeader("/X-Nonexistent", "")
206+
}

file/options.go

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* This file is part of easyKV.
3+
* © 2016 The easyKV Authors
4+
*
5+
* For the full copyright and license information, please view the LICENSE
6+
* file that was distributed with this source code.
7+
*/
8+
9+
package file
10+
11+
// Options contains all (possibly optional) values that are needed to fetch
12+
// JSON or YAML files (either locally or remotely).
13+
type Options struct {
14+
Headers map[string]string
15+
}
16+
17+
// Option configures the file client.
18+
type Option func(*Options)
19+
20+
// WithHeaders sets the headers for the HTTP request made when fetching
21+
// remote files.
22+
func WithHeaders(headers map[string]string) Option {
23+
return func(o *Options) {
24+
o.Headers = headers
25+
}
26+
}

0 commit comments

Comments
 (0)