rack app serving js file with Content-Type set yet browser says Mimetype is ""

70 Views Asked by At

I have a rack app:

class Responder
  def self.call(env)
    path = env['PATH_INFO']
    path = File.extname(path).blank? ? 'index.html' : path
    extension = File.extname(path)
    headers = {
      'Content-Type' => Rack::Mime.mime_type(extension)
    }
   [200, headers, [ File.read(File.join(APP_ROOT, path)) ] ]
  end
end

The goal of this is that any route like /foo or /bar will respond with index.html and otherwise any request for .js or .css the file requested will just be passed through...

When testing this, I see the correct content type in the headers being set.. And I can even see this with curl:

curl -i http://localhost:3000/foo
HTTP/1.1 200 OK
Content-Type: text/html

and

curl -i http://localhost:3000/main.js
HTTP/1.1 200 OK
Content-Type: application/javascript

Yet when I try to view the application in the browser, any script tags that are calling for javascript files are failing with errors saying:

main.js:1 Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.

Why does the browser claim the server is responding with a MIME type of "" when curl is showing the server is responding with "application/javascript" ?

1

There are 1 best solutions below

0
patrick On BEST ANSWER

I was able to get the mime type stuff to work by using actual Rack::Request / Rack::Response objects.

  get '(*path)', to: ->(env) {
    request = Rack::Request.new(env)
    response = Rack::Response.new
    extension = File.extname(request.path_info)

    if extension.blank?
      content_type = Rack::Mime.mime_type('.html')
      filename = 'index.html'
    else
      content_type = Rack::Mime.mime_type(extension)
      filename = request.path_info
    end

    response.header['Content-Type'] = content_type
    response.status = 200
    response.write File.read("public/app/#{filename}")
    response.finish
  }