Merge pull request #1203 from influxdata/feature/meta-redirect

Add meta redirect for Influx Enterprise similar to meta client.
pull/1202/head^2
Chris Goller 2017-04-06 14:17:01 -05:00 committed by GitHub
commit c9f1f3a660
3 changed files with 79 additions and 1 deletions

View File

@ -17,6 +17,7 @@
1. [#1179](https://github.com/influxdata/chronograf/pull/1179): Admin Databases Page will render a database without retention policies
1. [#1128](https://github.com/influxdata/chronograf/pull/1128): No more ghost dashboards 👻
1. [#1189](https://github.com/influxdata/chronograf/pull/1189): Clicking inside the graph header edit box will no longer blur the field. Use the Escape key for that behavior instead.
1. [#1195](https://github.com/influxdata/chronograf/issues/1195): Chronograf was not redirecting with authentiation for Influx Enterprise Meta service
1. [#1095](https://github.com/influxdata/chronograf/pull/1095): Make logout button display again
1. [#1209](https://github.com/influxdata/chronograf/pull/1209): HipChat Kapacitor config now uses only the subdomain instead of asking for the entire HipChat URL.

View File

@ -384,7 +384,12 @@ func (d *defaultClient) Do(URL *url.URL, path, method string, params map[string]
req.Header.Set("Content-Type", "application/json")
}
res, err := http.DefaultClient.Do(req)
// Meta servers will redirect (307) to leader. We need
// special handling to preserve authentication headers.
client := &http.Client{
CheckRedirect: AuthedCheckRedirect,
}
res, err := client.Do(req)
if err != nil {
return nil, err
}
@ -404,6 +409,21 @@ func (d *defaultClient) Do(URL *url.URL, path, method string, params map[string]
}
// AuthedCheckRedirect tries to follow the Influx Enterprise pattern of
// redirecting to the leader but preserving authentication headers.
func AuthedCheckRedirect(req *http.Request, via []*http.Request) error {
if len(via) >= 10 {
return errors.New("too many redirects")
} else if len(via) == 0 {
return nil
}
preserve := "Authorization"
if auth, ok := via[0].Header[preserve]; ok {
req.Header[preserve] = auth
}
return nil
}
// Do is a cancelable function to interface with Influx Enterprise's Meta API
func (m *MetaClient) Do(ctx context.Context, method, path string, params map[string]string, body io.Reader) (*http.Response, error) {
type result struct {

View File

@ -7,6 +7,7 @@ import (
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"reflect"
"testing"
@ -1396,3 +1397,59 @@ func (c *MockClient) Do(URL *url.URL, path, method string, params map[string]str
Body: ioutil.NopCloser(bytes.NewReader(c.Body)),
}, nil
}
func Test_AuthedCheckRedirect_Do(t *testing.T) {
var ts2URL string
ts1 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
want := http.Header{
"Referer": []string{ts2URL},
"Accept-Encoding": []string{"gzip"},
"Authorization": []string{"hunter2"},
}
for k, v := range want {
if !reflect.DeepEqual(r.Header[k], v) {
t.Errorf("Request.Header = %#v; want %#v", r.Header[k], v)
}
}
if t.Failed() {
w.Header().Set("Result", "got errors")
} else {
w.Header().Set("Result", "ok")
}
}))
defer ts1.Close()
ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, ts1.URL, http.StatusFound)
}))
defer ts2.Close()
ts2URL = ts2.URL
tr := &http.Transport{}
defer tr.CloseIdleConnections()
c := &http.Client{
Transport: tr,
CheckRedirect: AuthedCheckRedirect,
}
req, _ := http.NewRequest("GET", ts2.URL, nil)
req.Header.Add("Cookie", "foo=bar")
req.Header.Add("Authorization", "hunter2")
req.Header.Add("Howdy", "doody")
req.Header.Set("User-Agent", "Darth Vader, an extraterrestrial from the Planet Vulcan")
res, err := c.Do(req)
if err != nil {
t.Fatal(err)
}
defer res.Body.Close()
if res.StatusCode != 200 {
t.Fatal(res.Status)
}
if got := res.Header.Get("Result"); got != "ok" {
t.Errorf("result = %q; want ok", got)
}
}