req.header 与 Express 中的 req.headers

req.header vs req.headers in Express

我正在使用带有 Body 解析器的 Express。给定以下 header 键:

X-Master-Key

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

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

但是上面改成后就可以了

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

此外,当我尝试输出 req.headers 时,事实证明 Express 以 down-case 格式输出所有 header。


我开始进一步深入挖掘并尝试使用以下代码,这些代码段中的任何一个都有效

req.header('X-Master-Key'); // Works

// -- OR

req.header('x-master-key'); // Works

那么这里的问题是什么?为什么 Express 将所有 header 键更改为 down-case?此外,使用 req.header()req.headers[] 有何不同?

问题归结为 case-sensitivity。

当您查看 documentation for req.get(别名为 req.header)时,它指出:

Returns the specified HTTP request header field (case-insensitive match). The Referrer and Referer fields are interchangeable.

w3 standard表示headers应该是case-insensitive:

Each header field consists of a name followed by a colon (":") and the field value. Field names are case-insensitive.

因此,express 使用的节点 http 模块似乎根据此 github issue

将它们全部视为 lower-case 到 "save you steps"

You can see express 框架 req object 实际上利用了节点模块 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 方法将您提供的任何内容转换为 lower-case:

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 函数解析 headers,该函数自动 lower-cases 任何和所有 headers 不是 "traditional headers",在这种情况下它是 case-insensitive.

这是负责的片段,实现了您看到的行为:

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

问题的出现是因为在HTTP协议中,header是case-insensitive。这意味着 content-typeContent-TypecoNTEnt-tYPe 都引用相同的 header,并且 Express 框架需要能够处理它们中的任何一个。

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

如果您想从 Javascript object 得到一个 属性,属性 名称是 case-sensitive。所以 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'];

如果您不使用 lower-case header 名称,您将无法获得预期的效果。