【问题标题】:Node.js HTTPParser doesn't call some of the callbacksNode.js HTTPParser 不调用某些回调
【发布时间】:2012-11-19 00:27:50
【问题描述】:

我正在使用 Node.js v0.8.15 中的 HTTPParser。不幸的是,有些回调永远不会被调用。

例如,以下代码仅调用onHeadersComplete。无法调用onURLonHeaderFieldonHeaderValue

var
    HTTPParser = process.binding('http_parser').HTTPParser,
    parser = new HTTPParser(HTTPParser.REQUEST),
    request = new Buffer(
        'GET /test HTTP/1.1\r\n' +
        'Host: www.example.com\r\n' +
        'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/17.0 Firefox/17.0\r\n' +
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n' +
        'Accept-Language: en-US,en;q=0.5\r\n' +
        'Accept-Encoding: gzip, deflate\r\n' +
        '\r\n'
    );

parser.onURL = function() {
    console.log('onURL');
}

parser.onHeaderField = function() {
    console.log('onHeaderField');
}

parser.onHeaderValue = function() {
    console.log('onHeaderValue');
}

parser.onHeadersComplete = function() {
    console.log('onHeadersComplete');
}

parser.execute(request, 0, request.length);

怎么了?

【问题讨论】:

    标签: node.js http parsing


    【解决方案1】:

    2021 年 9 月不再有效:

    $ node test.js
    terminate called after throwing an instance of 'std::bad_alloc'
      what():  std::bad_alloc
    Aborted (core dumped)
    
    $ node --version
    v14.15.0
    $ uname -a
    Linux linux 5.4.0-84-generic #94~18.04.1-Ubuntu SMP Thu Aug 26 23:17:46 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
    

    更好地使用新的http解析器模块https://github.com/creationix/http-parser-js

    然后

    npm install http-parser-js
    

    然后下面的代码工作:

    HTTPParser = require('http-parser-js').HTTPParser;
    
    var parser = new HTTPParser(HTTPParser.REQUEST);
    
    const kOnHeaders = HTTPParser.kOnHeaders | 0;
    const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
    const kOnBody = HTTPParser.kOnBody | 0;
    const kOnMessageComplete = HTTPParser.kOnMessageComplete | 0;
    const kOnExecute = HTTPParser.kOnExecute | 0;
    
    parser[kOnHeaders] = 
        function(headers, url) {
            console.log('kOnHeaders');
        }
    parser[kOnHeadersComplete] = 
        function(versionMajor, versionMinor, headers, method,
                 url, statusCode, statusMessage, upgrade, shouldKeepAlive) {
            console.log('kOnHeadersComplete');
        }
    parser[kOnBody] = 
        function(b, start, len) {
            console.log('kOnBody');
        }
    parser[kOnMessageComplete] = 
        function() {
            console.log('kOnMessageComplete');
        }
    parser[kOnExecute] = 
        function() {
            console.log('kOnExecute');
        }
    
    var ret = parser.execute(new Buffer.from(
            'GET /test HTTP/1.1\r\n' +
            'Host: www.example.com\r\n' +
            'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/17.0 Firefox/17.0\r\n' +
            'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n' +
            'Accept-Language: en-US,en;q=0.5\r\n' +
            'Accept-Encoding: gzip, deflate\r\n' +
            '\r\n'
        ));
    

    【讨论】:

      【解决方案2】:

      对于那些从搜索引擎来到这里的人。 最新版本的 Node 使用稍微不同的组织。此代码有效:

      var HTTPParser = process.binding('http_parser').HTTPParser;
      
      var parser = new HTTPParser(HTTPParser.REQUEST);
      
      const kOnHeaders = HTTPParser.kOnHeaders | 0;
      const kOnHeadersComplete = HTTPParser.kOnHeadersComplete | 0;
      const kOnBody = HTTPParser.kOnBody | 0;
      const kOnMessageComplete = HTTPParser.kOnMessageComplete | 0;
      const kOnExecute = HTTPParser.kOnExecute | 0;
      
      parser[kOnHeaders] = 
          function(headers, url) {
              console.log('kOnHeaders');
          }
      parser[kOnHeadersComplete] = 
          function(versionMajor, versionMinor, headers, method,
                   url, statusCode, statusMessage, upgrade, shouldKeepAlive) {
              console.log('kOnHeadersComplete');
          }
      parser[kOnBody] = 
          function(b, start, len) {
              console.log('kOnBody');
          }
      parser[kOnMessageComplete] = 
          function() {
              console.log('kOnMessageComplete');
          }
      parser[kOnExecute] = 
          function() {
              console.log('kOnExecute');
          }
      
      var ret = parser.execute(new Buffer(
              'GET /test HTTP/1.1\r\n' +
              'Host: www.example.com\r\n' +
              'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/17.0 Firefox/17.0\r\n' +
              'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n' +
              'Accept-Language: en-US,en;q=0.5\r\n' +
              'Accept-Encoding: gzip, deflate\r\n' +
              '\r\n'
          ));
      

      另外,还有一些包装模块。 该对象目前有以下方法:

      • close - 取消解析并释放解析器 (?)
      • 执行 - 读取数据块并对其进行解析。如果标头到达缓慢,可以调用任意次数
      • finish - 告诉解析器不再有数据,完成解析
      • 重新初始化 - 为另一种类型的消息(请求/响应)准备解析器
      • 暂停 - IDK,可能在添加数据时停止解析
      • resume - IDK,也许开始解析
      • 消费 - IDK,Stream 的东西
      • 取消消费 - IDK,用于 Stream 的东西
      • getCurrentBuffer - 返回当前数据收集器 (?)

      至于使用详情,可以参考Node源码:

      【讨论】:

        【解决方案3】:

        process.binding 应该只被核心节点库使用。根据我对源代码的简要阅读,http 解析器 C++ 代码仅公开了一小部分事件(onHeadersonHeadersCompleteonBodyonMessageComplete)所以我相信这些是您可以锁定的唯一事件。

        解析器在内部使用来自解析器的一些额外回调,但它们不会作为事件暴露给 JS 领域。

        【讨论】:

          猜你喜欢
          • 2016-03-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-24
          • 2013-05-21
          • 2016-01-26
          • 2018-03-02
          • 1970-01-01
          相关资源
          最近更新 更多