1
0
Fork 0

Disable Content-Type auto-detection by default

This commit is contained in:
Simon Delicata 2022-11-29 11:48:05 +01:00 committed by GitHub
parent 4d86668af3
commit db287c4d31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 193 additions and 168 deletions

View file

@ -0,0 +1,46 @@
package contenttype
import (
"context"
"net/http"
"github.com/traefik/traefik/v2/pkg/middlewares"
)
const (
typeName = "ContentType"
)
// ContentType is a middleware used to activate Content-Type auto-detection.
type contentType struct {
next http.Handler
name string
}
// New creates a new handler.
func New(ctx context.Context, next http.Handler, name string) (http.Handler, error) {
middlewares.GetLogger(ctx, name, typeName).Debug().Msg("Creating middleware")
return &contentType{next: next, name: name}, nil
}
func (c *contentType) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// Re-enable auto-detection.
if ct, ok := rw.Header()["Content-Type"]; ok && ct == nil {
middlewares.GetLogger(req.Context(), c.name, typeName).
Debug().Msg("Enable Content-Type auto-detection.")
delete(rw.Header(), "Content-Type")
}
c.next.ServeHTTP(rw, req)
}
func DisableAutoDetection(next http.Handler) http.HandlerFunc {
return func(rw http.ResponseWriter, req *http.Request) {
// Prevent Content-Type auto-detection.
if _, ok := rw.Header()["Content-Type"]; !ok {
rw.Header()["Content-Type"] = nil
}
next.ServeHTTP(rw, req)
}
}

View file

@ -0,0 +1,79 @@
package contenttype
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/traefik/traefik/v2/pkg/testhelpers"
)
func TestAutoDetection(t *testing.T) {
testCases := []struct {
desc string
autoDetect bool
contentType string
wantContentType string
}{
{
desc: "Keep the Content-Type returned by the server",
autoDetect: false,
contentType: "application/json",
wantContentType: "application/json",
},
{
desc: "Don't auto-detect Content-Type header by default when not set by the server",
autoDetect: false,
contentType: "",
wantContentType: "",
},
{
desc: "Keep the Content-Type returned by the server with auto-detection middleware",
autoDetect: true,
contentType: "application/json",
wantContentType: "application/json",
},
{
desc: "Auto-detect when Content-Type header is not already set by the server with auto-detection middleware",
autoDetect: true,
contentType: "",
wantContentType: "text/plain; charset=utf-8",
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
var next http.Handler
next = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if test.contentType != "" {
w.Header().Set("Content-Type", test.contentType)
}
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("Test"))
})
if test.autoDetect {
var err error
next, err = New(context.Background(), next, "foo-content-type")
require.NoError(t, err)
}
server := httptest.NewServer(
DisableAutoDetection(next),
)
t.Cleanup(server.Close)
req := testhelpers.MustNewRequest(http.MethodGet, server.URL, nil)
res, err := server.Client().Do(req)
require.NoError(t, err)
assert.Equal(t, test.wantContentType, res.Header.Get("Content-Type"))
})
}
}