Node.js создать объект из строки необработанного HTTP-запроса
У меня есть необработанная строка запроса HTTP, из которой мне нужно создать представление объекта.
Вместо того, чтобы изобретать колесо, я думал об использовании внутреннего парсера http, чтобы получить экземпляр http.IncomingMessage
Возможно ли это?
Я так думаю, потому что строка не так сильно отличается от полного потока.
Как это сделать?
Я посмотрел исходный код, и они получили парсер запросов, как следует
var HTTPParser = process.binding('http_parser').HTTPParser;
var parser = new HTTPParser(HTTPParser.REQUEST)
Edit
Некоторый прогресс от node.js test
var request = Buffer(raw);
var parser = new HTTPParser(HTTPParser.REQUEST);
parser.execute(request, 0, request.length);
Изменить 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');
};
Спасибо
Ответы
Ответ 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
и обычно строится вокруг идеи его использования на сервере. Код для его синтаксического анализа несколько запутан, чтобы повторно использовать as-is (по моему вкусу).
Ответ 2
Старая тема, но я что-то скажу.
Экспорт HTTPParser в собственные материалы (модуль или приложение) не так прост, потому что http-библиотека использует множество внутренних локальных функций и конструкторов. Кроме того, сам HTTPParser связан с библиотекой C и некоторыми помощниками.
Как я знаю, http.parsers был удален из Node > 4, поэтому единственный способ - импортировать все необходимые вещи из библиотеки http.
Для Node 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 }
Подробнее здесь
Кроме того, благодаря @KT для элегантного решения