sinatra 的 send_file 决定使用什么 content-type 的过程是什么?

What is the process by which sinatra's send_file decides what content-type to use?

sinatra 的 send_file 决定使用什么 content-type 的过程是什么?

例如,它似乎是通过传递给 send_file 的文件的扩展名来工作的,所以如果它是 send_file blah.txt 。然后当我 http 到路由时,我将得到/响应 header 将是 content-type: text/plain,因此 txt 文件中的任何 html 都将被网络浏览器解释为纯文本。而如果文件是 blah.html,则服务器将以 content-type: text/html 响应。(并且文件中的任何 html 都是这样呈现的)

当然,路线名称是无关紧要的,因此您可以转到 http://127.0.0.1:4567/zzz.html,它可能会导致 send_file a.txt,而 a.txt 可能包含 html 标签,但由于它是一个 .txt 文件 send_file 将导致 sinatra 以 content-type: text/plain 响应并且浏览器不会呈现任何已发送的 html 并将其显示为纯文本。我可能是错的,但这似乎是我的快速测试所表明的。我尝试了不同的路径、不同的文件扩展名(.txt 和 .html),有时带有 html 的文件有时没有,查看浏览器是否呈现 html,并且使用 wget -d.

查看 content-type header 是什么

那么我的问题是,sinatra 的 send_file 函数使用了一个列表,将文件扩展名与 content-type 相关联吗?我想看看那个清单。如果不是,那么它使用的是什么过程。

注意-我知道有一种方法可以传入 content-type Sinatra: How to respond with an image with headers "content-type" => "image/jpeg" 但我问的是如何/通过什么方法,send_file 在没有传入 content-type 时确定 content-type。

This is the send_file method 在 Sinatra 框架(当前为 v2.0.5)中,请注意,如果设置了 none,它会直接查找内容类型:

if opts[:type] or not response['Content-Type']
  content_type opts[:type] || File.extname(path), :default => 'application/octet-stream'
end

The content_type method will either return immediately or hand off to mime_type, which is a delegate of Rack's mime_type method(当前为 v2.0.7)。这使用众所周知的扩展名列表进行检查。

def mime_type(ext, fallback='application/octet-stream')
  MIME_TYPES.fetch(ext.to_s.downcase, fallback)
end

列表开始on line 49:

MIME_TYPES = {
  ".123"       => "application/vnd.lotus-1-2-3",
  ".3dml"      => "text/vnd.in3d.3dml",
  ".3g2"       => "video/3gpp2",
  ".3gp" => "video/3gpp",
  # <snip>

正如您从 content_type 片段中看到的那样,它返回的默认值是 application/octet-stream.