2014-10-03 4 views
15

У меня есть строка запроса HTTP, из которой мне нужно создать представление объекта.node.js создать объект из строки необработанного HTTP-запроса

Вместо изобретать колесо, я думал о том, использовать внутренний HTTP-анализатор, чтобы получить экземпляр http.IncomingMessage

возможно ли это?

Я так думаю, потому что строка не так сильно отличается от полного потока.

Как это сделать?

Я имел взгляд на исходный код, и они получают запрос анализатор, как следовать

var HTTPParser = process.binding('http_parser').HTTPParser; 
var parser = new HTTPParser(HTTPParser.REQUEST) 

Редактировать

некоторый прогресс с node.js test

var request = Buffer(raw); 
var parser = new HTTPParser(HTTPParser.REQUEST); 

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

Edit 2

Некоторые eventHandlers пропали без вести (все из них)

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

parser.onBody = function(body) { 
    console.log('body done'); 
    console.log(body.toString()); 
} 

parser.onMessageComplete = function(res) { 
    console.log('done'); 
}; 

Благодаря

+0

Я обновил свой вопрос. У меня есть строка «GET/HTTP/1.1 \ nHost: localhost \ n \ n», которую мне нужно проанализировать для создания объекта. Результирующий объект должен быть экземпляром [http.IncomingMessage] (http://nodejs.org/api/http.html # http_http_incomingmessage) – PauloASilva

+2

Итак, в чем именно вопрос? – OrangeDog

+0

Полный рабочий процесс до получения объекта IncomingMessage. – PauloASilva

ответ

1

Видимо, http_parser модуль низкого уровня обратного вызова на основе синтаксического анализа. Он отправит любые части строки, которые он сможет проанализировать вам через эти обратные вызовы, и вам решать сделать IncomingMessage или что-то еще, что вам нужно от них.

Я считаю, что что-то подобное, что могло бы быть то, что вы ищете:

var HTTPParser = process.binding('http_parser').HTTPParser; 

function parseMessage(request) { 
    var _message = {}; 
    var _parser = new HTTPParser(HTTPParser.REQUEST); 

    _parser.onHeadersComplete = function(headers) { 
     _message = headers; 
    } 

    _parser.onBody = function(body, start, len) { 
     _message.data = body.slice(start, start+len); 
    } 

    var _result = _parser.execute(request, 0, request.length); 

    if (_result != request.length) { 
     _message.error = _result; 
    } 
    else { 
     _message.error = false; 
    } 
    return _message; 
} 

var request = Buffer("GET/HTTP/1.1\nHost: localhost\nContent-Length: 2\n\nHi\n\n"); 
result = parseMessage(request); 

Обратите внимание, что конкретный класс IncomingMessage спараметрирован с socket и вообще построен вокруг идеи он используется в сервере. code for parsing it несколько грязный, чтобы повторно использовать как есть (на мой вкус).

+0

Новые версии узлов изменили интерфейс, теперь обратные вызовы назначаются как 'parser [HTTPParser.kOnHeaders] = function() {...}' – Fr0sT

0

Старая тема, но я скажу что-то.

Экспорт HTTPParser в собственные материалы (модуль или приложение) не так прост, потому что http-библиотека использует множество внутренних локальных функций и конструкторов. Кроме того, сам HTTPParser связан с библиотекой C и некоторыми помощниками.

Как я знаю, http.parsers был удален из Node> 4, поэтому единственный способ - импортировать все необходимые материалы из библиотеки http.

Для узла 0.x есть простой способ импорта:

var parser = require("http").parsers.alloc(); 

parser.onIncoming = function(response) { 
    console.log(response); 
}; 

function parse(data) { 
    var buffer = new Buffer(data); 
    parser.execute(buffer, 0, buffer.length); 
} 
/** 
* tests 
*/ 
parse("DELETE/HTTP/1.1\r\n"); 
parse("user-agent: curl\r\n"); 
parse("x-pingback:"); 
parse("12023\r\n"); 
parse("\r\n"); 

//response 
{ _readableState: 
    { highWaterMark: 16384, 
    buffer: [], 
    length: 0, 
    pipes: null, 
    pipesCount: 0, 
    flowing: false, 
    ended: false, 
    endEmitted: false, 
    reading: false, 
    calledRead: false, 
    sync: true, 
    needReadable: false, 
    emittedReadable: false, 
    readableListening: false, 
    objectMode: false, 
    defaultEncoding: 'utf8', 
    ranOut: false, 
    awaitDrain: 0, 
    readingMore: false, 
    decoder: null, 
    encoding: null }, 
    readable: true, 
    domain: null, 
    _events: {}, 
    _maxListeners: 10, 
    socket: undefined, 
    connection: undefined, 
    httpVersion: '1.1', 
    complete: false, 
    headers: { 'user-agent': 'curl', 'x-pingback': '12023' }, 
    trailers: {}, 
    _pendings: [], 
    _pendingIndex: 0, 
    url: '/', 
    method: 'DELETE', 
    statusCode: null, 
    client: undefined, 
    _consuming: false, 
    _dumped: false, 
    httpVersionMajor: 1, 
    httpVersionMinor: 1, 
    upgrade: false } 

here Подробнее

Кроме того, благодаря @KT для элегантного решения

Смежные вопросы