Serving JS modules with proper content-type
hweeks opened this issue · comments
When you try and create a <script src="/app.js" type="module">
joy has no idea what content-type it is. It should be 'application/js' but is getting no type. To reproduce:
Take your default scaffolding, and update layout.janet to this:
(import joy :prefix "")
(defn app [{:body body :request request}]
(text/html
(doctype :html5)
[:html {:lang "en"}
[:head
[:meta {:charset "utf-8"}]
[:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]
[:meta {:name "csrf-token" :content (authenticity-token request)}]
[:link {:href "/app.css" :rel "stylesheet"}]
[:title "test"]]
[:body
body
[:script {:src "/app.js" :type "module"}]]]))
The HTML output is dead right. If you could show me where to make that update I'd be game. I just was not seeing a place that was obvious to me, as I'm currently just learning janet.
Here maybe?
I kind of left this out and I rely on proxying from nginx/caddy in prod (or dev) for the mimetype stuff.
If it was going to be added, it would probably go in halo somewhere around here: https://github.com/joy-framework/halo/blob/master/sandbird.c#L584-L585
We would need a mapping of file extensions to mimetypes in C (could be a file too) and then send it along with:
err = sb_send_header(st, "Content-Type", "application/js"); // or whatever comes out of the mapping from file extension to content-type
if (err) goto fail;
Or you could try removing the X-Content-Type-Options: nosniff
header here: https://github.com/joy-framework/joy/blob/master/src/joy/middleware.janet#L92
I added this bit in halo just to test it out:
const char *get_filename_ext(const char *filename) {
const char *dot = strrchr(filename, '.');
if(!dot || dot == filename) return "";
return dot + 1;
}
const char *ext = get_filename_ext(filename);
if (strcmp(ext, "js") == 0) {
err = sb_send_header(st, "Content-Type", "text/javascript");
} else if(strcmp(ext, "css") == 0) {
err = sb_send_header(st, "Content-Type", "text/css");
} else if(strcmp(ext, "svg")) {
err = sb_send_header(st, "Content-Type", "text/svg");
} else if(strcmp(ext, "html") == 0) {
err = sb_send_header(st, "Content-Type", "text/html");
} else if(strcmp(ext, "png") == 0) {
err = sb_send_header(st, "Content-Type", "image/png");
} else if(strcmp(ext, "jpg") == 0 || strcmp(ext, "jpeg") == 0) {
err = sb_send_header(st, "Content-Type", "image/jpeg");
} else if(strcmp(ext, "gif") == 0) {
err = sb_send_header(st, "Content-Type", "image/gif");
} else {
err = sb_send_header(st, "Content-Type", "text/plain");
}
if (err) goto fail;
It's ugly but it seems to get :type "module"
working
Decided to actually push it in the halo repo