NodeJS - https - TypeError [ERR_INVALID_HTTP_TOKEN]:标头名称必须是有效的 HTTP 令牌 [“接受?”]

ben*_*siu 9 https request http-headers node.js

我有一个 NodeJS 代码,它使用https模块作为:像这样的对象https.request(options, (res) => {......在哪里options

const options = {
    hostname: SERVICE_HOSTNAME,
    path: BASE_PATH,
    method: 'GET',
    headers: {
        'Content-Type': 'application/json',
        'Accept?': 'application/json',
        ApplicationId,
        Authorization
    }
  };
Run Code Online (Sandbox Code Playgroud)

当我添加Accept标题时,我的问题就开始了。我收到一个错误:

TypeError [ERR_INVALID_HTTP_TOKEN]: Header name must be a valid HTTP token ["Accept?"]
    at ClientRequest.setHeader (_http_outgoing.js:472:3)
    at new ClientRequest (_http_client.js:203:14)
    at Object.request (https.js:289:10)
Run Code Online (Sandbox Code Playgroud)

Acceptheader怎么会无效?

hlf*_*rmn 20

现在这很疯狂,但是您的“接受”字符串中有一个额外的字符。如果你跑

console.log('Accept?'.charCodeAt(6)) // prints 8203
Run Code Online (Sandbox Code Playgroud)

(您必须使用问题中的“接受”副本运行它,我认为这是从其他地方复制粘贴的)

Unicode 8203 是零宽度空间,因此我们人类看不到它:)


顺便说一句,最初我通过复制粘贴到 Node REPL 并在收到错误后注意到控制台输出中的“正方形”来发现该字符。

然后我尝试将您的代码复制粘贴到我的 IntelliJ 编辑器中,看到这个警告感到惊喜:

在此处输入图片说明


eol*_*eol 7

hlfrmn 已经发现了这个棘手的错误并给出了正确的答案,以防其他人感兴趣:

14.3.0版本开始,Node 的 http模块将执行validateHeaderNamevalidateHeaderValue您在您的请求选项报头指定每个键-值对。

所以如果你这样做

const {validateHeaderName} = require('http');

try {
    const options = {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            'Accept?': 'application/json',
        }
    };
    for (const header in options.headers) {
        validateHeaderName(header);
    }

} catch (err) {
    console.log(err);
}
Run Code Online (Sandbox Code Playgroud)

将打印上述错误:

TypeError [ERR_INVALID_HTTP_TOKEN]: Header name must be a valid HTTP token ["Accept?"] will be printed from the catch block.
Run Code Online (Sandbox Code Playgroud)