3

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

例如,以下代码仅调用onHeadersComplete. 无法让它调用onURLonHeaderField并且onHeaderValue

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);

怎么了?

4

3 回答 3

3

对于那些从搜索引擎来到这里的人。最新版本的 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 - 取消解析并释放解析器 (?)
  • 执行 - 读取数据块并解析它。如果标头到达缓慢,可以调用任意次数
  • 完成 - 告诉解析器将不再有数据,完成解析
  • 重新初始化 - 为另一种类型的消息(请求/响应)准备解析器
  • pause - IDK,可能停止解析数据添加
  • resume - IDK,也许开始解析
  • 消费 - IDK,流的东西
  • unconsume - IDK,Stream 的东西
  • getCurrentBuffer - 返回当前数据收集器(?)

至于使用细节,可以参考Node源码:

于 2017-02-02T13:17:42.550 回答
2

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

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

于 2012-12-01T19:04:47.647 回答
0

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'
    ));
于 2021-09-29T11:16:47.020 回答