为什么某些无效的 MIME 类型会触发 "TypeError," 而其他无效的 MIME 类型会绕过错误并触发自动下载?

Why do some invalid MIME types trigger a "TypeError," and other invalid MIME types bypass the error and trigger an unprompted download?

我正在制作一个相当简单的 Express 应用程序,只有几条路线。我的问题不是关于应用程序的功能,而是关于 Express 路线的一些奇怪行为。

当我启动服务器并使用 /search/* 路由或任何接受参数的路由时,我将这四种内容类型之一应用于响应:

参数作为文件下载,没有任何提示。因此,使用 search/foobar 会下载一个名为 "foobar" 的文件,其大小为 6 字节且文件类型不受支持。现在我明白这四种类型中的 none 是实际的 MIME 类型,我应该使用 text/plaintext/html,但为什么要下载?这两种 MIME 类型的行为与它们应该的一样,并且以下具有类型但没有子类型的 MIME 类型都像它们应该的那样失败,它们都是 return 错误 TypeError: invalid media type:

为什么某些无效类型会触发错误,而其他无效类型会绕过错误并触发下载?

到目前为止我发现了什么:

我在 Express 4.x 文档中发现 res.download(path [, filename]) 将路径中的文件作为“附件”传输,并且通常会提示用户下载,但这种下载既不是提示也不是故意的.

我无法在 Express 文档(或此处的 SO)中找到任何类似的情况,其中 运行 路由导致文件自动下载到您的计算机。

起初我以为 res.send(typeof(res)); 行导致了下载,但是在一次注释掉一行并重新 运行 服务器之后,我才发现只有当content-type 设置为 'plain/text' 下载是否发生。 res.send() 里面的内容无关紧要,当内容类型为 plain/text 时,/search/ 之后的文本会下载到我的机器上。

重新排列路由得到了相同的结果(除了下载之外一切正常。)

应用程序只是挂在 /search/foo 之前到达的任何路线,但下载仍然可以进行。

我的代码:

'use strict';
var express = require('express');
var path = require('path');

var app = express();

app.get('/', function (req, res) {
  res.sendFile(path.join(__dirname+'/index.html'));
});


app.get('/search', function(req,res){
  res.send('search route');
});
app.get('/search/*', function(req, res, next) {
  res.setHeader('content-type', 'plain/text');
  var type = typeof(res);
  var reqParams = req.params;
  res.send(type);
});


var server = app.listen(process.env.PORT || 3000, function(){
  console.log('app listening on port ' + process.env.PORT + '!');
});

module.exports = server;

其他详情

定义路由的顺序在 express 中很重要,您可能需要将默认的“/”路由移到“/search/*”路由之后。

Why do some invalid types trigger an error...

因为 MIME 类型有它应该遵循的格式(记录在 RFC 2045 中),而触发错误的类型与该格式不匹配。

格式如下:

type "/" subtype *(";" parameter)

所以有一个强制类型、一个强制斜杠、一个强制子类型和以分号为前缀的可选参数。

但是,当 MIME 类型与该格式匹配时,它仅在句法上有效,不一定在语义上有效,这将我们带到问题的第二部分:

...and other invalid types bypass the error and trigger a download?

RFC 2049 中所写:

Upon encountering any unrecognized Content-Type field, an implementation must treat it as if it had a media type of "application/octet-stream" with no parameter sub-arguments. How such data are handled is up to an implementation, but likely options for handling such unrecognized data include offering the user to write it into a file (decoded from its mail transport format) or offering the user to name a program to which the decoded data should be passed as input.

(强调我的)