Techioz Blog

Content-Type が設定された JS ファイルを提供するラック アプリですが、ブラウザでは Mimetype が「」であると表示されます

概要

ラックアプリがあります:

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

この目的は、/foo や /bar などのルートがindex.html で応答し、それ以外の場合は、ファイルが要求した .js または .css のリクエストがそのままパススルーされるようにすることです。

これをテストすると、ヘッダーに正しいコンテンツ タイプが設定されていることがわかります。これは、curl でも確認できます。

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

そして

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

しかし、ブラウザでアプリケーションを表示しようとすると、JavaScript ファイルを呼び出すスクリプト タグが次のようなエラーで失敗します。

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.

サーバーが「application/javascript」で応答していることをcurlが示しているのに、ブラウザはサーバーが「」のMIMEタイプで応答していると主張するのはなぜですか?

解決策

実際の Rack::Request / Rack::Response オブジェクトを使用して、MIME タイプを機能させることができました。

  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
  }