Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node.js create object from raw http request string

Tags:

I have a raw HTTP request string from which I need to create an object representation.

Instead of reinvent the wheel I was thinking about use the internal http parser to get an instance of http.IncomingMessage

Is it possible?

I think so because string is not so different from a complete stream.

How to do it?

I had a look on source code and they get a request parser as follow

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

Edit

Some progress from a node.js test

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

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

Edit 2

Some eventHandlers were missing (all of them)

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

Thanks

like image 895
PauloASilva Avatar asked Oct 03 '14 14:10

PauloASilva


People also ask

How do I use HTTP request in node JS?

Setup a new project: To create a new project, enter the following command in your terminal. Project Structure: It will look like the following. Approach 1: In this approach we will send request to getting a resource using AXIOS library. Axios is a promise base HTTP client for NodeJS.

What is setHeader in node JS?

setHeader(name, value) (Added in v0. 4.0) method is an inbuilt application programming interface of the 'http' module which sets a single header value for implicit headers. If this header already exists in the to-be-sent headers, its value will be replaced.


1 Answers

Apparently, the http_parser module is a low-level callback-based parser. It will send whatever parts of the string it can parse to you via those callbacks, and it is up to you to make an IncomingMessage or whatever else you need from them.

I believe something like that might be what you are looking for:

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

Note that the particular IncomingMessage class is parameterized with a socket and generally built around the idea of it being used within a server. The code for parsing it is somewhat messy to be reused as-is (to my taste).

like image 156
KT. Avatar answered Oct 15 '22 13:10

KT.