api: Support redirect for HA

This commit is contained in:
Armon Dadgar
2015-04-20 11:30:35 -07:00
parent 0454e1f48e
commit 462ff7f374
2 changed files with 98 additions and 1 deletions

View File

@@ -1,6 +1,8 @@
package api
import (
"errors"
"fmt"
"net/http"
"net/http/cookiejar"
"net/url"
@@ -9,6 +11,10 @@ import (
vaultHttp "github.com/hashicorp/vault/http"
)
var (
errRedirect = errors.New("redirect")
)
// Config is used to configure the creation of the client.
type Config struct {
// Address is the address of the Vault server. This should be a complete
@@ -30,7 +36,7 @@ type Config struct {
func DefaultConfig() Config {
config := Config{
Address: "https://127.0.0.1:8200",
HttpClient: http.DefaultClient,
HttpClient: &http.Client{},
}
return config
@@ -64,6 +70,11 @@ func NewClient(c Config) (*Client, error) {
c.HttpClient.Jar = jar
}
// Ensure redirects are not automatically followed
c.HttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return errRedirect
}
return &Client{
addr: u,
config: c,
@@ -128,6 +139,8 @@ func (c *Client) NewRequest(method, path string) *Request {
// a Vault server not configured with this client. This is an advanced operation
// that generally won't need to be called externally.
func (c *Client) RawRequest(r *Request) (*Response, error) {
redirectCount := 0
START:
req, err := r.ToHTTP()
if err != nil {
return nil, err
@@ -138,10 +151,46 @@ func (c *Client) RawRequest(r *Request) (*Response, error) {
if resp != nil {
result = &Response{Response: resp}
}
if err != nil {
urlErr, ok := err.(*url.Error)
if ok && urlErr.Err == errRedirect {
err = nil
}
}
if err != nil {
return result, err
}
// Check for a redirect, only allowing for a single redirect
if (resp.StatusCode == 302 || resp.StatusCode == 307) && redirectCount == 0 {
// Parse the updated location
respLoc, err := resp.Location()
if err != nil {
return result, err
}
// Ensure a protocol downgrade doesn't happen
if req.URL.Scheme == "https" && respLoc.Scheme != "https" {
return result, fmt.Errorf("redirect would cause protocol downgrade")
}
// Copy the cookies so that our client auth transfers
cookies := c.config.HttpClient.Jar.Cookies(r.URL)
c.config.HttpClient.Jar.SetCookies(respLoc, cookies)
// Update the request
r.URL = respLoc
// Reset the request body if any
if err := r.ResetJSONBody(); err != nil {
return result, err
}
// Retry the request
redirectCount++
goto START
}
if err := result.Error(); err != nil {
return result, err
}