diff --git a/tools/filesystem/filesystem.go b/tools/filesystem/filesystem.go index 2e7ad542..22c64aa3 100644 --- a/tools/filesystem/filesystem.go +++ b/tools/filesystem/filesystem.go @@ -196,6 +196,12 @@ var inlineServeContentTypes = []string{ "application/pdf", "application/x-pdf", } +// manualExtensionContentTypes is a map of file extensions to content types. +var manualExtensionContentTypes = map[string]string{ + ".svg": "image/svg+xml", // (see https://github.com/whatwg/mimesniff/issues/7) + ".css": "text/css", // (see https://github.com/gabriel-vasile/mimetype/pull/113) +} + // Serve serves the file at fileKey location to an HTTP response. func (s *System) Serve(response http.ResponseWriter, fileKey string, name string) error { r, readErr := s.bucket.NewReader(s.ctx, fileKey, nil) @@ -210,12 +216,11 @@ func (s *System) Serve(response http.ResponseWriter, fileKey string, name string disposition = "inline" } - // make an exception for svg and force a custom content type - // to send in the response so that it can be loaded in an img tag - // (see https://github.com/whatwg/mimesniff/issues/7) + // make an exception for specific content types and force a + // custom content type to send in the response so that it can be loaded directly. extContentType := realContentType - if extContentType != "image/svg+xml" && filepath.Ext(name) == ".svg" { - extContentType = "image/svg+xml" + if ct, found := manualExtensionContentTypes[filepath.Ext(name)]; found && extContentType != ct { + extContentType = ct } response.Header().Set("Content-Disposition", disposition+"; filename="+name) diff --git a/tools/filesystem/filesystem_test.go b/tools/filesystem/filesystem_test.go index e9a6a7d4..89fa78dc 100644 --- a/tools/filesystem/filesystem_test.go +++ b/tools/filesystem/filesystem_test.go @@ -207,6 +207,18 @@ func TestFileSystemServe(t *testing.T) { "Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; sandbox", }, }, + { + // css exception + "style.css", + "test_name.css", + false, + map[string]string{ + "Content-Disposition": "attachment; filename=test_name.css", + "Content-Type": "text/css", + "Content-Length": "0", + "Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; sandbox", + }, + }, } for _, scenario := range scenarios { @@ -216,7 +228,7 @@ func TestFileSystemServe(t *testing.T) { hasErr := err != nil if hasErr != scenario.expectError { - t.Errorf("(%s) Expected hasError %v, got %v", scenario.path, scenario.expectError, hasErr) + t.Errorf("(%s) Expected hasError %v, got %v (%v)", scenario.path, scenario.expectError, hasErr, err) continue } @@ -321,5 +333,11 @@ func createTestDir(t *testing.T) string { } file4.Close() + file5, err := os.OpenFile(filepath.Join(dir, "style.css"), os.O_WRONLY|os.O_CREATE, 0666) + if err != nil { + t.Fatal(err) + } + file5.Close() + return dir }