change how content-type enforcement is handled

If no content types are specified, then accept all responses, regardless
of content type (this is the behavior imageproxy has historically had).
Change default value for the contentTypes flag to be "image/*", so that
the new default when running cmd/imageproxy is that only images will be
proxied.  The old default behavior can be achieved by passing an empty
string for the contentTypes flag:

    imageproxy -contentTypes ""

Do not send the "XCTO: nosniff" header, since all documentation that I
can find still says that it can cause problems when served with images.
If it's effectively a noop when an explicit content-type is specified in
the response, then this shouldn't actually matter for us either way.
But in the absence of certainty, I'd rather err on the side of following
the spec.

Also add documentation for the new functionality.

Fixes #141
This commit is contained in:
Will Norris 2018-09-15 04:29:05 +00:00
parent 39a4e1813d
commit 0370572130
4 changed files with 60 additions and 45 deletions

View file

@ -304,7 +304,7 @@ func (t testTransport) RoundTrip(req *http.Request) (*http.Response, error) {
case "/error":
return nil, errors.New("http protocol error")
case "/nocontent":
raw = "HTTP/1.1 204 No Content\nContent-Type: image/png\n\n"
raw = "HTTP/1.1 204 No Content\n\n"
case "/etag":
raw = "HTTP/1.1 200 OK\nEtag: \"tag\"\n\n"
case "/png":
@ -326,7 +326,8 @@ func TestProxy_ServeHTTP(t *testing.T) {
Client: &http.Client{
Transport: testTransport{},
},
Whitelist: []string{"good.test"},
Whitelist: []string{"good.test"},
ContentTypes: []string{"image/*"},
}
tests := []struct {
@ -413,29 +414,49 @@ func TestTransformingTransport(t *testing.T) {
}
func TestValidContentType(t *testing.T) {
for contentType, expected := range map[string]bool{
"": false,
"image/png": true,
"text/html": false,
} {
actual := validContentType(nil, contentType)
if actual != expected {
t.Errorf("got %v, expected %v for content type: %v", actual, expected, contentType)
}
}
}
tests := []struct {
patterns []string
contentType string
valid bool
}{
// no patterns
{nil, "", true},
{nil, "text/plain", true},
{[]string{}, "", true},
{[]string{}, "text/plain", true},
func TestValidContentType_Patterns(t *testing.T) {
for contentType, expected := range map[string]bool{
"": false,
"image/png": false,
"foo/asdf": true,
"bar/baz": true,
"bar/bazz": false,
} {
actual := validContentType([]string{"foo/*", "bar/baz"}, contentType)
if actual != expected {
t.Errorf("got %v, expected %v for content type: %v", actual, expected, contentType)
// empty pattern
{[]string{""}, "", true},
{[]string{""}, "text/plain", false},
// exact match
{[]string{"text/plain"}, "", false},
{[]string{"text/plain"}, "text", false},
{[]string{"text/plain"}, "text/html", false},
{[]string{"text/plain"}, "text/plain", true},
{[]string{"text/plain"}, "text/plaintext", false},
{[]string{"text/plain"}, "text/plain+foo", false},
// wildcard match
{[]string{"text/*"}, "", false},
{[]string{"text/*"}, "text", false},
{[]string{"text/*"}, "text/html", true},
{[]string{"text/*"}, "text/plain", true},
{[]string{"text/*"}, "image/jpeg", false},
{[]string{"image/svg*"}, "image/svg", true},
{[]string{"image/svg*"}, "image/svg+html", true},
// complete wildcard does not match
{[]string{"*"}, "text/foobar", false},
// multiple patterns
{[]string{"text/*", "image/*"}, "image/jpeg", true},
}
for _, tt := range tests {
got := validContentType(tt.patterns, tt.contentType)
if want := tt.valid; got != want {
t.Errorf("validContentType(%q, %q) returned %v, want %v", tt.patterns, tt.contentType, got, want)
}
}
}