Merge pull request #1203 from influxdata/feature/meta-redirect
Add meta redirect for Influx Enterprise similar to meta client.pull/1202/head^2
commit
c9f1f3a660
|
@ -17,6 +17,7 @@
|
||||||
1. [#1179](https://github.com/influxdata/chronograf/pull/1179): Admin Databases Page will render a database without retention policies
|
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. [#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. [#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. [#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.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -384,7 +384,12 @@ func (d *defaultClient) Do(URL *url.URL, path, method string, params map[string]
|
||||||
req.Header.Set("Content-Type", "application/json")
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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
|
// 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) {
|
func (m *MetaClient) Do(ctx context.Context, method, path string, params map[string]string, body io.Reader) (*http.Response, error) {
|
||||||
type result struct {
|
type result struct {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"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)),
|
Body: ioutil.NopCloser(bytes.NewReader(c.Body)),
|
||||||
}, nil
|
}, 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue