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) {
|
||||
r := a.c.newRequest("POST", "/v1/acl/rules/translate")
|
||||
r.body = rules
|
||||
r.header.Set("Content-Type", "text/plain")
|
||||
rtt, resp, err := requireOK(a.c.doRequest(r))
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
@ -871,6 +871,12 @@ func (r *request) toHTTP() (*http.Request, error) {
|
|||
req.Host = r.url.Host
|
||||
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
|
||||
if r.config.HttpAuth != nil {
|
||||
req.SetBasicAuth(r.config.HttpAuth.Username, r.config.HttpAuth.Password)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
@ -810,7 +811,17 @@ func TestAPI_SetWriteOptions(t *testing.T) {
|
|||
|
||||
func TestAPI_Headers(t *testing.T) {
|
||||
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()
|
||||
|
||||
if len(c.Headers()) != 0 {
|
||||
|
@ -836,6 +847,39 @@ func TestAPI_Headers(t *testing.T) {
|
|||
if r.header.Get("Auth") != "Token" {
|
||||
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) {
|
||||
|
|
|
@ -45,6 +45,7 @@ func (e *Event) Fire(params *UserEvent, q *WriteOptions) (string, *WriteMeta, er
|
|||
if params.Payload != nil {
|
||||
r.body = bytes.NewReader(params.Payload)
|
||||
}
|
||||
r.header.Set("Content-Type", "application/octet-stream")
|
||||
|
||||
rtt, resp, err := requireOK(e.c.doRequest(r))
|
||||
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.body = bytes.NewReader(body)
|
||||
r.header.Set("Content-Type", "application/octet-stream")
|
||||
rtt, resp, err := requireOK(k.c.doRequest(r))
|
||||
if err != nil {
|
||||
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 {
|
||||
r := s.c.newRequest("PUT", "/v1/snapshot")
|
||||
r.body = in
|
||||
r.header.Set("Content-Type", "application/octet-stream")
|
||||
r.setWriteOptions(q)
|
||||
_, _, err := requireOK(s.c.doRequest(r))
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue