Rack应用设置Content-Type后浏览器显示MIME类型为空的问题
Rack应用MIME类型显示不一致问题排查
问题描述
编写了一个Rack应用,代码如下:
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测试时响应头Content-Type正常:
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
但浏览器访问时,加载模块脚本的<script>标签报错:
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.
原因分析
核心问题是代码中使用了String#blank?方法,该方法属于Rails的ActiveSupport扩展,并非Ruby标准库原生方法:
- curl测试时,环境可能加载了ActiveSupport(比如在Rails开发环境中运行),
blank?可以正常调用,代码逻辑执行无误,Content-Type设置正确。 - 浏览器访问时,应用在纯Rack环境(未加载ActiveSupport)运行,调用
blank?会抛出NoMethodError异常。Rack默认的错误处理返回的响应未正确设置Content-Type,导致浏览器检测到MIME类型为空。
解决方案
将blank?替换为Ruby标准库支持的方法,比如empty?:
class Responder def self.call(env) path = env['PATH_INFO'] # 用empty?替代blank?,适配纯Ruby环境 path = File.extname(path).empty? ? '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.这种情况),可以改用strip.empty?:
path = File.extname(path).strip.empty? ? 'index.html' : path
另外,建议添加错误处理逻辑,避免文件读取失败时返回异常响应:
class Responder def self.call(env) path = env['PATH_INFO'] path = File.extname(path).empty? ? 'index.html' : path file_path = File.join(APP_ROOT, path) unless File.exist?(file_path) return [404, {'Content-Type' => 'text/plain'}, ['File not found']] end extension = File.extname(path) headers = { 'Content-Type' => Rack::Mime.mime_type(extension) || 'text/plain' } [200, headers, [ File.read(file_path) ] ] end end
内容的提问来源于stack exchange,提问作者patrick
相关产品推荐
相关产品推荐

