【问题标题】:NodeJS - https - TypeError [ERR_INVALID_HTTP_TOKEN]: Header name must be a valid HTTP token ["Accept​"]NodeJS - https - TypeError [ERR_INVALID_HTTP_TOKEN]:标头名称必须是有效的 HTTP 令牌 [“Accept​”]
【发布时间】:2020-09-14 13:14:32
【问题描述】:

我有一个 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
    }
  };

当我添加 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)

Accept 标头如何无效?

【问题讨论】:

    标签: node.js https request http-headers


    【解决方案1】:

    因为你的问题我没吃T_T

    正如@hlfrmn 所说,您的接受词中有一个罕见的字符!

    我重现了错误:

    const https = require('https');
    
    //copied from origin question
    var copiedOptions = {
      headers: {
        'Content-Type': 'application/json',
        "Accept​": 'application/json'
      }
    }
    
    var writedOptions = {
      headers: {
        'Content-Type': 'application/json',
        "Accept": 'application/json'
      }
    }
    
    https.get('https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY',writedOptions, (resp) => {
      let data = '';
    
      // A chunk of data has been recieved.
      resp.on('data', (chunk) => {
        data += chunk;
      });
    
      // The whole response has been received. Print out the result.
      resp.on('end', () => {
        console.log(JSON.parse(data).explanation);
      });
    
    }).on("error", (err) => {
      console.log("Error: " + err.message);
    });
    

    如果你尝试使用 copiedOptions,你会得到同样的错误。


    自节点 v10.20.1

    https://github.com/nodejs/node/tree/master 和 stackTrace 中搜索:_http_outgoing.js:472

    at ClientRequest.setHeader (_http_outgoing.js:472:3)
    

    我创立了这个:

    const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
    /**
     * Verifies that the given val is a valid HTTP token
     * per the rules defined in RFC 7230
     * See https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6
     */
    function checkIsHttpToken(val) {
      return tokenRegExp.test(val);
    }
    

    该正则表达式确保标头名称仅具有根据https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6 允许的标记或字符

    也许 nodejs 核心中的早期验证可能会有所帮助:

    标题名称中有一个不允许的字符!

    【讨论】:

      【解决方案2】:

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

      从版本 14.3.0 开始,节点的 http module 将对您在请求选项标头中指定的每个键值对执行 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);
      }
      

      将打印提到的错误:

      TypeError [ERR_INVALID_HTTP_TOKEN]: Header name must be a valid HTTP token ["Accept​"] will be printed from the catch block.
      

      【讨论】:

        【解决方案3】:

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

        console.log('Accept​'.charCodeAt(6)) // prints 8203
        

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

        Unicode 8203 是 zero width space,因此我们人类看不到它:)


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

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

        【讨论】:

        • 直到我在 WebStorm 中验证后才相信,这是我以前从未见过的 :) +1
        猜你喜欢
        • 1970-01-01
        • 2021-06-28
        • 2021-02-07
        • 2017-11-06
        • 2021-01-20
        • 2023-03-07
        • 1970-01-01
        • 2021-07-30
        • 1970-01-01
        相关资源
        最近更新 更多