Always set the Content-Type header when a body is present (#10204)
* Always set the Content-Type header when a body is present Closes https://github.com/hashicorp/consul/issues/10011 * Add Changelog entry * Add more Content-Type exceptions * Fix tests
This commit is contained in:
parent
8d6d898df9
commit
5e33428b22
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:improvement
|
||||||
|
api: The `Content-Type` header is now always set when a body is present in a request.
|
||||||
|
```
|
|
@ -900,6 +900,7 @@ func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, er
|
||||||
func (a *ACL) RulesTranslate(rules io.Reader) (string, error) {
|
func (a *ACL) RulesTranslate(rules io.Reader) (string, error) {
|
||||||
r := a.c.newRequest("POST", "/v1/acl/rules/translate")
|
r := a.c.newRequest("POST", "/v1/acl/rules/translate")
|
||||||
r.body = rules
|
r.body = rules
|
||||||
|
r.header.Set("Content-Type", "text/plain")
|
||||||
rtt, resp, err := requireOK(a.c.doRequest(r))
|
rtt, resp, err := requireOK(a.c.doRequest(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
@ -871,6 +871,12 @@ func (r *request) toHTTP() (*http.Request, error) {
|
||||||
req.Host = r.url.Host
|
req.Host = r.url.Host
|
||||||
req.Header = r.header
|
req.Header = r.header
|
||||||
|
|
||||||
|
// Content-Type must always be set when a body is present
|
||||||
|
// See https://github.com/hashicorp/consul/issues/10011
|
||||||
|
if req.Body != nil && req.Header.Get("Content-Type") == "" {
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
}
|
||||||
|
|
||||||
// Setup auth
|
// Setup auth
|
||||||
if r.config.HttpAuth != nil {
|
if r.config.HttpAuth != nil {
|
||||||
req.SetBasicAuth(r.config.HttpAuth.Username, r.config.HttpAuth.Password)
|
req.SetBasicAuth(r.config.HttpAuth.Username, r.config.HttpAuth.Password)
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -810,7 +811,17 @@ func TestAPI_SetWriteOptions(t *testing.T) {
|
||||||
|
|
||||||
func TestAPI_Headers(t *testing.T) {
|
func TestAPI_Headers(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
c, s := makeClient(t)
|
|
||||||
|
var request *http.Request
|
||||||
|
c, s := makeClientWithConfig(t, func(c *Config) {
|
||||||
|
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||||
|
transport.Proxy = func(r *http.Request) (*url.URL, error) {
|
||||||
|
// Keep track of the last request sent
|
||||||
|
request = r
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
c.Transport = transport
|
||||||
|
}, nil)
|
||||||
defer s.Stop()
|
defer s.Stop()
|
||||||
|
|
||||||
if len(c.Headers()) != 0 {
|
if len(c.Headers()) != 0 {
|
||||||
|
@ -836,6 +847,39 @@ func TestAPI_Headers(t *testing.T) {
|
||||||
if r.header.Get("Auth") != "Token" {
|
if r.header.Get("Auth") != "Token" {
|
||||||
t.Fatalf("Auth header not set: %v", r.header)
|
t.Fatalf("Auth header not set: %v", r.header)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kv := c.KV()
|
||||||
|
_, err := kv.Put(&KVPair{Key: "test-headers", Value: []byte("foo")}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "application/octet-stream", request.Header.Get("Content-Type"))
|
||||||
|
|
||||||
|
_, _, err = kv.Get("test-headers", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "", request.Header.Get("Content-Type"))
|
||||||
|
|
||||||
|
_, err = kv.Delete("test-headers", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "", request.Header.Get("Content-Type"))
|
||||||
|
|
||||||
|
err = c.Snapshot().Restore(nil, strings.NewReader("foo"))
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, "application/octet-stream", request.Header.Get("Content-Type"))
|
||||||
|
|
||||||
|
_, err = c.ACL().RulesTranslate(strings.NewReader(`
|
||||||
|
agent "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
// ACL support is disabled
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, "text/plain", request.Header.Get("Content-Type"))
|
||||||
|
|
||||||
|
_, _, err = c.Event().Fire(&UserEvent{
|
||||||
|
Name: "test",
|
||||||
|
Payload: []byte("foo"),
|
||||||
|
}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "application/octet-stream", request.Header.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPI_RequestToHTTP(t *testing.T) {
|
func TestAPI_RequestToHTTP(t *testing.T) {
|
||||||
|
|
|
@ -45,6 +45,7 @@ func (e *Event) Fire(params *UserEvent, q *WriteOptions) (string, *WriteMeta, er
|
||||||
if params.Payload != nil {
|
if params.Payload != nil {
|
||||||
r.body = bytes.NewReader(params.Payload)
|
r.body = bytes.NewReader(params.Payload)
|
||||||
}
|
}
|
||||||
|
r.header.Set("Content-Type", "application/octet-stream")
|
||||||
|
|
||||||
rtt, resp, err := requireOK(e.c.doRequest(r))
|
rtt, resp, err := requireOK(e.c.doRequest(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -205,6 +205,7 @@ func (k *KV) put(key string, params map[string]string, body []byte, q *WriteOpti
|
||||||
r.params.Set(param, val)
|
r.params.Set(param, val)
|
||||||
}
|
}
|
||||||
r.body = bytes.NewReader(body)
|
r.body = bytes.NewReader(body)
|
||||||
|
r.header.Set("Content-Type", "application/octet-stream")
|
||||||
rtt, resp, err := requireOK(k.c.doRequest(r))
|
rtt, resp, err := requireOK(k.c.doRequest(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
|
|
|
@ -38,6 +38,7 @@ func (s *Snapshot) Save(q *QueryOptions) (io.ReadCloser, *QueryMeta, error) {
|
||||||
func (s *Snapshot) Restore(q *WriteOptions, in io.Reader) error {
|
func (s *Snapshot) Restore(q *WriteOptions, in io.Reader) error {
|
||||||
r := s.c.newRequest("PUT", "/v1/snapshot")
|
r := s.c.newRequest("PUT", "/v1/snapshot")
|
||||||
r.body = in
|
r.body = in
|
||||||
|
r.header.Set("Content-Type", "application/octet-stream")
|
||||||
r.setWriteOptions(q)
|
r.setWriteOptions(q)
|
||||||
_, _, err := requireOK(s.c.doRequest(r))
|
_, _, err := requireOK(s.c.doRequest(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue