From 409bcdaa9677b93dc49855165bf4889f846e9563 Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Thu, 3 Apr 2025 16:16:39 +0300 Subject: [PATCH] [#6597] forced text/javascript content-type when serving .js/.mjs collection uploaded files --- CHANGELOG.md | 4 ++- tools/filesystem/filesystem.go | 8 +++-- tools/filesystem/filesystem_test.go | 48 +++++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27d9ca5d..784f9d19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,9 @@ - Added new `geoPoint` field for storing `{lon:x,lat:y}` record value (@todo docs). -- Minor UI fixes (_removed the superuser fields from the auth record create/update examples, etc._). +- Forced `text/javascript` Content-Type when serving `.js`/`.mjs` collection uploaded files ([#6597](https://github.com/pocketbase/pocketbase/issues/6597)). + +- Minor UI fixes (_removed the superuser fields from the auth record create/update body examples, etc._). ## v0.26.6 diff --git a/tools/filesystem/filesystem.go b/tools/filesystem/filesystem.go index cc44fee6..a6ad37d7 100644 --- a/tools/filesystem/filesystem.go +++ b/tools/filesystem/filesystem.go @@ -358,8 +358,10 @@ var inlineServeContentTypes = []string{ // 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) + ".svg": "image/svg+xml", // (see https://github.com/whatwg/mimesniff/issues/7) + ".css": "text/css", // (see https://github.com/gabriel-vasile/mimetype/pull/113) + ".js": "text/javascript", // (see https://github.com/pocketbase/pocketbase/issues/6597) + ".mjs": "text/javascript", } // forceAttachmentParam is the name of the request query parameter to @@ -394,7 +396,7 @@ func (s *System) Serve(res http.ResponseWriter, req *http.Request, fileKey strin // make an exception for specific content types and force a custom // content type to send in the response so that it can be loaded properly extContentType := realContentType - if ct, found := manualExtensionContentTypes[filepath.Ext(name)]; found && extContentType != ct { + if ct, found := manualExtensionContentTypes[filepath.Ext(name)]; found { extContentType = ct } diff --git a/tools/filesystem/filesystem_test.go b/tools/filesystem/filesystem_test.go index 65f029b3..c065fe3f 100644 --- a/tools/filesystem/filesystem_test.go +++ b/tools/filesystem/filesystem_test.go @@ -430,6 +430,36 @@ func TestFileSystemServe(t *testing.T) { "Cache-Control": cacheControl, }, }, + { + // js exception + "main.js", + "test_name.js", + nil, + nil, + false, + map[string]string{ + "Content-Disposition": "attachment; filename=test_name.js", + "Content-Type": "text/javascript", + "Content-Length": "0", + "Content-Security-Policy": csp, + "Cache-Control": cacheControl, + }, + }, + { + // mjs exception + "main.mjs", + "test_name.mjs", + nil, + nil, + false, + map[string]string{ + "Content-Disposition": "attachment; filename=test_name.mjs", + "Content-Type": "text/javascript", + "Content-Length": "0", + "Content-Security-Policy": csp, + "Cache-Control": cacheControl, + }, + }, { // custom header "test/sub2.txt", @@ -600,6 +630,8 @@ func TestFileSystemList(t *testing.T) { "image.svg", "image_! noext", "style.css", + "main.js", + "main.mjs", "test/sub1.txt", "test/sub2.txt", }, @@ -802,12 +834,24 @@ func createTestDir(t *testing.T) string { } file5.Close() - file6, err := os.OpenFile(filepath.Join(dir, "image_! noext"), os.O_WRONLY|os.O_CREATE, 0644) + file6, err := os.OpenFile(filepath.Join(dir, "main.js"), os.O_WRONLY|os.O_CREATE, 0644) if err != nil { t.Fatal(err) } - png.Encode(file6, image.Rect(0, 0, 1, 1)) // tiny 1x1 png file6.Close() + file7, err := os.OpenFile(filepath.Join(dir, "main.mjs"), os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + t.Fatal(err) + } + file7.Close() + + file8, err := os.OpenFile(filepath.Join(dir, "image_! noext"), os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + t.Fatal(err) + } + png.Encode(file8, image.Rect(0, 0, 1, 1)) // tiny 1x1 png + file8.Close() + return dir }