From ab05583c7fb82af2755462950443e63933c9513a Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Sat, 15 Aug 2026 10:30:18 +1200 Subject: [PATCH 1/4] Serve JavaScript modules by default --- lib/utopia/static/mime_types.rb | 2 +- test/utopia/.static/module.mjs | 1 + test/utopia/static.rb | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 test/utopia/.static/module.mjs diff --git a/lib/utopia/static/mime_types.rb b/lib/utopia/static/mime_types.rb index e2586142..330b0f2f 100644 --- a/lib/utopia/static/mime_types.rb +++ b/lib/utopia/static/mime_types.rb @@ -17,7 +17,7 @@ module Static :xiph, "mp3", "mp4", "wav", "aiff", "aac", "webm", "weba", "mov", "avi", "wmv", "mpg", "m3u8", "ts" ], :text => [ - "html", "css", "js", "map", "txt", "rtf", "xml", "pdf" + "html", "css", "js", "mjs", "map", "txt", "rtf", "xml", "pdf" ], :fonts => [ "otf", "eot", "ttf", "woff", "woff2" diff --git a/test/utopia/.static/module.mjs b/test/utopia/.static/module.mjs new file mode 100644 index 00000000..ff3177ba --- /dev/null +++ b/test/utopia/.static/module.mjs @@ -0,0 +1 @@ +export default true; diff --git a/test/utopia/static.rb b/test/utopia/static.rb index 32978d4a..527fe164 100755 --- a/test/utopia/static.rb +++ b/test/utopia/static.rb @@ -35,6 +35,14 @@ expect(last_response.read).to be == "Uppercase extension!\n" end + it "serves JavaScript modules" do + client.get "/module.mjs" + + expect(last_response.status).to be == 200 + expect(last_response.headers["content-type"]).to be == "text/javascript" + expect(last_response.read).to be == "export default true;\n" + end + it "serves HEAD requests without opening a response body" do client.head "/test.txt" @@ -276,6 +284,7 @@ it "should give the correct mime type" do expect(extensions).to have_keys( ".txt" => be == "text/plain", + ".mjs" => be == "text/javascript", ".webm" => be == "video/webm", ".weba" => be == "audio/webm", ".ogg" => be == "audio/vorbis", From 0f08295b2f369ecc09c57c58a722c10668791206 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Sat, 15 Aug 2026 10:43:35 +1200 Subject: [PATCH 2/4] Serve WebAssembly modules by default --- lib/utopia/static/mime_types.rb | 2 +- test/utopia/.static/module.wasm | 1 + test/utopia/static.rb | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 test/utopia/.static/module.wasm diff --git a/lib/utopia/static/mime_types.rb b/lib/utopia/static/mime_types.rb index 330b0f2f..6c28ca65 100644 --- a/lib/utopia/static/mime_types.rb +++ b/lib/utopia/static/mime_types.rb @@ -29,7 +29,7 @@ module Static "png", "gif", "jpeg", "tiff", "svg", "webp" ], :default => [ - :media, :text, :archive, :images, :fonts + :media, :text, :archive, :images, :fonts, "wasm" ] } diff --git a/test/utopia/.static/module.wasm b/test/utopia/.static/module.wasm new file mode 100644 index 00000000..c34a9e48 --- /dev/null +++ b/test/utopia/.static/module.wasm @@ -0,0 +1 @@ +WebAssembly diff --git a/test/utopia/static.rb b/test/utopia/static.rb index 527fe164..85dd12ab 100755 --- a/test/utopia/static.rb +++ b/test/utopia/static.rb @@ -43,6 +43,14 @@ expect(last_response.read).to be == "export default true;\n" end + it "serves WebAssembly modules" do + client.get "/module.wasm" + + expect(last_response.status).to be == 200 + expect(last_response.headers["content-type"]).to be == "application/wasm" + expect(last_response.read).to be == "WebAssembly\n" + end + it "serves HEAD requests without opening a response body" do client.head "/test.txt" @@ -285,6 +293,7 @@ expect(extensions).to have_keys( ".txt" => be == "text/plain", ".mjs" => be == "text/javascript", + ".wasm" => be == "application/wasm", ".webm" => be == "video/webm", ".weba" => be == "audio/webm", ".ogg" => be == "audio/vorbis", From b8cb345b9f20547db79837128ea9214624fbc208 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Sat, 15 Aug 2026 10:47:21 +1200 Subject: [PATCH 3/4] Group browser script extensions --- lib/utopia/static/mime_types.rb | 7 +++++-- test/utopia/static.rb | 9 +++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/utopia/static/mime_types.rb b/lib/utopia/static/mime_types.rb index 6c28ca65..cad8f8f0 100644 --- a/lib/utopia/static/mime_types.rb +++ b/lib/utopia/static/mime_types.rb @@ -16,8 +16,11 @@ module Static :media => [ :xiph, "mp3", "mp4", "wav", "aiff", "aac", "webm", "weba", "mov", "avi", "wmv", "mpg", "m3u8", "ts" ], + :scripts => [ + "js", "mjs", "wasm" + ], :text => [ - "html", "css", "js", "mjs", "map", "txt", "rtf", "xml", "pdf" + "html", "css", "js", "map", "txt", "rtf", "xml", "pdf" ], :fonts => [ "otf", "eot", "ttf", "woff", "woff2" @@ -29,7 +32,7 @@ module Static "png", "gif", "jpeg", "tiff", "svg", "webp" ], :default => [ - :media, :text, :archive, :images, :fonts, "wasm" + :media, :scripts, :text, :archive, :images, :fonts ] } diff --git a/test/utopia/static.rb b/test/utopia/static.rb index 85dd12ab..6922057e 100755 --- a/test/utopia/static.rb +++ b/test/utopia/static.rb @@ -288,6 +288,15 @@ describe Utopia::Static::MIME_TYPES do let(:extensions) {Utopia::Static::MimeTypeLoader.extensions_for(subject[:default])} + let(:script_extensions) {Utopia::Static::MimeTypeLoader.extensions_for(subject[:scripts])} + + it "groups script extensions" do + expect(script_extensions).to have_keys( + ".js" => be == "text/javascript", + ".mjs" => be == "text/javascript", + ".wasm" => be == "application/wasm", + ) + end it "should give the correct mime type" do expect(extensions).to have_keys( From 4fc861a5b8d4314d031cf57be92d0bd5131c85e5 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Sat, 15 Aug 2026 10:47:57 +1200 Subject: [PATCH 4/4] Keep scripts separate from text types --- lib/utopia/static/mime_types.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utopia/static/mime_types.rb b/lib/utopia/static/mime_types.rb index cad8f8f0..ed1e9bae 100644 --- a/lib/utopia/static/mime_types.rb +++ b/lib/utopia/static/mime_types.rb @@ -20,7 +20,7 @@ module Static "js", "mjs", "wasm" ], :text => [ - "html", "css", "js", "map", "txt", "rtf", "xml", "pdf" + "html", "css", "map", "txt", "rtf", "xml", "pdf" ], :fonts => [ "otf", "eot", "ttf", "woff", "woff2"