joy-framework / joy

A full stack web framework written in janet

Home Page:https://joy.swlkr.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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?

commented

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

commented

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

commented

Decided to actually push it in the halo repo