req.header vs req.headers in Express



我正在使用带有Body Parser的Express。给定以下标题键:

X-Master-Key

当我使用下面的代码片段时,它无法输出值

req.headers['X-Master-Key'] // Fails

但当上述内容更改为时,它会工作

req.headers['x-master-key'] // Works

此外,当我尝试输出req.headers时,发现Express以小写格式输出所有标头。


我开始进一步挖掘,并尝试使用下面的代码,这两个片段中的任何一个都可以使用

req.header('X-Master-Key'); // Works
// -- OR
req.header('x-master-key'); // Works

那么这里有什么问题?为什么Express将所有标题键更改为小写?此外,使用req.header()与使用req.headers[]有何不同?

问题的出现是因为在HTTP协议中,标头不区分大小写。这意味着content-typeContent-TypecoNTEnt-tYPe都引用相同的头,Express框架需要能够处理其中的任何一个。

req.headers(对象(和req.header(函数(之间的区别很简单:

如果要从Javascript对象获取属性,则属性名称区分大小写。因此req.headers['content-type']将起作用;req.headers['Content-Type']不会。为什么小写版本有效?因为Express框架试图处理所有不同的可能情况(记住,HTTP将允许任何内容(,它会将所有内容转换为小写。

但是Express的开发人员认识到,您(开发人员(可能正在寻找Content-Type,而您可能不记得转换为小写,所以他们提供了一个函数req.header,它将为您解决这个问题。

简而言之:

建议这样做:

const myHeader = req.header('Content-Type');

使用您想要的任何大小写-函数会将其转换为小写,并在req.headers中查找值。

不建议这样做:

const myHeader = req.headers['Content-Type'];

如果您不使用小写标题名称,您将无法得到您所期望的。

问题归结为区分大小写。

当您查看req.get(由req.header别名(的文档时,它指出:

返回指定的HTTP请求标头字段(不区分大小写的匹配(。Referrer和Referrer字段可以互换。

w3标准指出标头应不区分大小写:

每个标题字段都由一个名称、一个冒号(":"(和字段值组成。字段名不区分大小写。

因此,express使用的节点http模块似乎只是将它们全部视为小写,以根据github问题"节省步骤">

您可以看到express框架req对象实际上使用了节点模块http:

var accepts = require('accepts');
var deprecate = require('depd')('express');
var isIP = require('net').isIP;
var typeis = require('type-is');
var http = require('http');
var fresh = require('fresh');
var parseRange = require('range-parser');
var parse = require('parseurl');

此外,在代码中,您可以看到req.header方法将您给它的任何内容转换为小写:

req.get =
req.header = function header(name) {
if (!name) {
throw new TypeError('name argument is required to req.get');
}
if (typeof name !== 'string') {
throw new TypeError('name must be a string to req.get');
}
var lc = name.toLowerCase();
switch (lc) {
case 'referer':
case 'referrer':
return this.headers.referrer
|| this.headers.referer;
default:
return this.headers[lc];
}
};

最后,http模块使用matchKnownFields函数解析标头,该函数会自动降低非"传统标头"的所有标头的大小写,在这种情况下,它不区分大小写。

以下是负责的代码片段,它实现了您所看到的行为:

if (lowercased) {
return 'u0000' + field;
} else {
return matchKnownFields(field.toLowerCase(), true);
}

最新更新