Handle http redirect (#4)
- Fixed panic if req.Body is nil or basicAuth is not set - Switched over to http.DefaultTransport if RoundTripper is not provided Closes #2, #3
This commit is contained in:
committed by
Christopher Boumenot
parent
3ea3d20764
commit
e0b63eb299
@@ -14,7 +14,19 @@ type Negotiator struct{ http.RoundTripper }
|
|||||||
//RoundTrip sends the request to the server, handling any authentication
|
//RoundTrip sends the request to the server, handling any authentication
|
||||||
//re-sends as needed.
|
//re-sends as needed.
|
||||||
func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error) {
|
func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error) {
|
||||||
|
// Use default round tripper if not provided
|
||||||
|
rt := l.RoundTripper
|
||||||
|
if rt == nil {
|
||||||
|
rt = http.DefaultTransport
|
||||||
|
}
|
||||||
|
// If it is not basic auth, just round trip the request as usual
|
||||||
|
reqauth := authheader(req.Header.Get("Authorization"))
|
||||||
|
if !reqauth.IsBasic() {
|
||||||
|
return rt.RoundTrip(req)
|
||||||
|
}
|
||||||
|
// Save request body
|
||||||
body := bytes.Buffer{}
|
body := bytes.Buffer{}
|
||||||
|
if req.Body != nil {
|
||||||
_, err = body.ReadFrom(req.Body)
|
_, err = body.ReadFrom(req.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -22,38 +34,36 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||||||
|
|
||||||
req.Body.Close()
|
req.Body.Close()
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
||||||
|
}
|
||||||
reqauth := authheader(req.Header.Get("Authorization"))
|
|
||||||
if reqauth.IsBasic() {
|
|
||||||
// first try anonymous, in case the server still finds us
|
// first try anonymous, in case the server still finds us
|
||||||
// authenticated from previous traffic
|
// authenticated from previous traffic
|
||||||
req.Header.Del("Authorization")
|
req.Header.Del("Authorization")
|
||||||
|
res, err = rt.RoundTrip(req)
|
||||||
res, err = l.RoundTripper.RoundTrip(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if res.StatusCode != 401 {
|
if res.StatusCode != http.StatusUnauthorized {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
resauth := authheader(res.Header.Get("Www-Authenticate"))
|
resauth := authheader(res.Header.Get("Www-Authenticate"))
|
||||||
if !resauth.IsNegotiate() {
|
if !resauth.IsNegotiate() {
|
||||||
// Unauthorized, Negotiate not requested, let's try with basic auth
|
// Unauthorized, Negotiate not requested, let's try with basic auth
|
||||||
res.Body.Close()
|
|
||||||
req.Header.Set("Authorization", string(reqauth))
|
req.Header.Set("Authorization", string(reqauth))
|
||||||
|
res.Body.Close()
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
||||||
|
|
||||||
res, err = l.RoundTripper.RoundTrip(req)
|
res, err = rt.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if res.StatusCode != http.StatusUnauthorized {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
resauth = authheader(res.Header.Get("Www-Authenticate"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if res.StatusCode == 401 {
|
if resauth.IsNegotiate() {
|
||||||
resauth := authheader(res.Header.Get("Www-Authenticate"))
|
|
||||||
if reqauth.IsBasic() && resauth.IsNegotiate() {
|
|
||||||
// 401 with request:Basic and response:Negotiate
|
// 401 with request:Basic and response:Negotiate
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
|
|
||||||
@@ -68,7 +78,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||||||
req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(negotiateMessage))
|
req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(negotiateMessage))
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
||||||
|
|
||||||
res, err = l.RoundTripper.RoundTrip(req)
|
res, err = rt.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -93,8 +103,7 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||||||
req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(authenticateMessage))
|
req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(authenticateMessage))
|
||||||
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
req.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
|
||||||
|
|
||||||
res, err = l.RoundTripper.RoundTrip(req)
|
res, err = rt.RoundTrip(req)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, err
|
return res, err
|
||||||
|
Reference in New Issue
Block a user