Adds an `X-Consul-Translate-Addresses` to signal translation is enabled.

This commit is contained in:
James Phillips 2016-08-16 11:31:41 -07:00
parent 817d7e93e4
commit bc333335be
No known key found for this signature in database
GPG Key ID: 77183E682AC5FC11
6 changed files with 88 additions and 3 deletions

View File

@ -80,6 +80,9 @@ type QueryMeta struct {
// How long did the request take
RequestTime time.Duration
// Is address translation enabled for HTTP responses on this agent
AddressTranslationEnabled bool
}
// WriteMeta is used to return meta data about a write
@ -542,6 +545,15 @@ func parseQueryMeta(resp *http.Response, q *QueryMeta) error {
default:
q.KnownLeader = false
}
// Parse X-Consul-Translate-Addresses
switch header.Get("X-Consul-Translate-Addresses") {
case "true":
q.AddressTranslationEnabled = true
default:
q.AddressTranslationEnabled = false
}
return nil
}

View File

@ -306,6 +306,7 @@ func TestParseQueryMeta(t *testing.T) {
resp.Header.Set("X-Consul-Index", "12345")
resp.Header.Set("X-Consul-LastContact", "80")
resp.Header.Set("X-Consul-KnownLeader", "true")
resp.Header.Set("X-Consul-Translate-Addresses", "true")
qm := &QueryMeta{}
if err := parseQueryMeta(resp, qm); err != nil {
@ -321,6 +322,9 @@ func TestParseQueryMeta(t *testing.T) {
if !qm.KnownLeader {
t.Fatalf("Bad: %v", qm)
}
if !qm.AddressTranslationEnabled {
t.Fatalf("Bad: %v", qm)
}
}
func TestAPI_UnixSocket(t *testing.T) {

View File

@ -329,6 +329,7 @@ func (s *HTTPServer) registerHandlers(enableDebug bool) {
func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Request) (interface{}, error)) func(resp http.ResponseWriter, req *http.Request) {
f := func(resp http.ResponseWriter, req *http.Request) {
setHeaders(resp, s.agent.config.HTTPAPIResponseHeaders)
setTranslateAddr(resp, s.agent.config.TranslateWanAddrs)
// Obfuscate any tokens from appearing in the logs
formVals, err := url.ParseQuery(req.URL.RawQuery)
@ -373,6 +374,7 @@ func (s *HTTPServer) wrap(handler func(resp http.ResponseWriter, req *http.Reque
if strings.Contains(errMsg, "Permission denied") || strings.Contains(errMsg, "ACL not found") {
code = http.StatusForbidden // 403
}
resp.WriteHeader(code)
resp.Write([]byte(err.Error()))
return
@ -452,6 +454,14 @@ func decodeBody(req *http.Request, out interface{}, cb func(interface{}) error)
return mapstructure.Decode(raw, out)
}
// setTranslateAddr is used to set the address translation header. This is only
// present if the feature is active.
func setTranslateAddr(resp http.ResponseWriter, active bool) {
if active {
resp.Header().Set("X-Consul-Translate-Addresses", "true")
}
}
// setIndex is used to set the index response header
func setIndex(resp http.ResponseWriter, index uint64) {
resp.Header().Set("X-Consul-Index", strconv.FormatUint(index, 10))

View File

@ -223,6 +223,51 @@ func TestSetMeta(t *testing.T) {
}
}
func TestHTTPAPI_TranslateAddrHeader(t *testing.T) {
// Header should not be present if address translation is off.
{
dir, srv := makeHTTPServer(t)
defer os.RemoveAll(dir)
defer srv.Shutdown()
defer srv.agent.Shutdown()
resp := httptest.NewRecorder()
handler := func(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
return nil, nil
}
req, _ := http.NewRequest("GET", "/v1/agent/self", nil)
srv.wrap(handler)(resp, req)
translate := resp.Header().Get("X-Consul-Translate-Addresses")
if translate != "" {
t.Fatalf("bad: expected %q, got %q", "", translate)
}
}
// Header should be set to true if it's turned on.
{
dir, srv := makeHTTPServer(t)
srv.agent.config.TranslateWanAddrs = true
defer os.RemoveAll(dir)
defer srv.Shutdown()
defer srv.agent.Shutdown()
resp := httptest.NewRecorder()
handler := func(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
return nil, nil
}
req, _ := http.NewRequest("GET", "/v1/agent/self", nil)
srv.wrap(handler)(resp, req)
translate := resp.Header().Get("X-Consul-Translate-Addresses")
if translate != "true" {
t.Fatalf("bad: expected %q, got %q", "true", translate)
}
}
}
func TestHTTPAPIResponseHeaders(t *testing.T) {
dir, srv := makeHTTPServer(t)
srv.agent.config.HTTPAPIResponseHeaders = map[string]string{

View File

@ -96,3 +96,12 @@ configuration option. However, the token can also be specified per-request
by using the `X-Consul-Token` request header or the `token` querystring
parameter. The request header takes precedence over the default token, and
the querystring parameter takes precedence over everything.
## <a id="translate_header"></a>Translated Addresses
Consul 0.7 added the ability to translate addresses in HTTP response based on the configuration
setting for [`translate_wan_addrs`](/docs/agent/options.html#translate_wan_addrs). In order to
allow clients to know if address translation is in effect, the `X-Consul-Translate-Addresses`
header will be added if translation is enabled, and will have a value of `true`. If translation
is not enabled then this header will not be present.

View File

@ -756,9 +756,14 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass
default.
<br>
<br>
Starting in Consul 0.7 and later, node addresses in responses to the following HTTP endpoints will
prefer a node's configured <a href="#_advertise-wan">WAN address</a> when querying for a node in a
remote datacenter:
Starting in Consul 0.7 and later, node addresses in responses to HTTP requests will also prefer a
node's configured <a href="#_advertise-wan">WAN address</a> when querying for a node in a remote
datacenter. An [`X-Consul-Translate-Addresses`](/docs/agent/http.html#translate_header) header
will be present on all responses when translation is enabled to help clients know that the addresses
may be translated. The `TaggedAddresses` field in responses also have a `lan` address for clients that
need knowledge of that address, regardless of translation.
<br>
<br>The following endpoints translate addresses:
<br>
* [`/v1/catalog/nodes`](/docs/agent/http/catalog.html#catalog_nodes)
* [`/v1/catalog/node/<node>`](/docs/agent/http/catalog.html#catalog_node)