Skip to content

Instantly share code, notes, and snippets.

@creationix
Created July 26, 2012 04:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save creationix/07a540c97dd1426427f6 to your computer and use it in GitHub Desktop.
Save creationix/07a540c97dd1426427f6 to your computer and use it in GitHub Desktop.
if (process.env.USE_JS) {
process.binding("http_parser").HTTPParser = require('./http_parser').HTTPParser;
}
var http = require('http');
var server = http.createServer(function (req, res) {
res.writeHead(200, {
"Content-Length": 12,
"Content-Type": "text/plain"
});
res.end("Hello World\n");
});
server.listen(8080, function () {
var port = server.address().port;
var url = "http://127.0.0.1:" + port + "/";
console.log(url);
var params = {
method: "GET",
host: "127.0.0.1",
path: "/",
port: 8080
};
if (process.env.NODE_CLIENT) {
function request() {
var req = http.request(params, function (res) {
count++;
request();
});
req.end();
}
request();
var count = 0;
var before = Date.now();
setInterval(function () {
var now = Date.now();
var delta = now - before;
before = now;
var rps = Math.round(count / delta * 1000);
console.log("%s req/second (%s reqs in %s ms)", rps, count, delta);
count = 0;
}, 1000);
}
});
exports.HTTPParser = HTTPParser;
function HTTPParser(type) {
this["INIT_" + type]();
}
HTTPParser.REQUEST = "REQUEST";
HTTPParser.RESPONSE = "RESPONSE";
HTTPParser.prototype.reinitialize = HTTPParser;
HTTPParser.prototype.execute = function (chunk, offset, length) {
// console.log({
// chunk: chunk.toString("utf8", offset, length),
// offset: offset,
// length: length
// });
this.chunk = chunk;
this.start = offset;
this.offset = offset;
this.end = offset + length;
while (this.offset < this.end) {
this[this.state]();
this.offset++;
}
};
HTTPParser.prototype.INIT_REQUEST = function () {
this.state = "REQUEST_LINE";
this.lineState = "DATA";
this.info = {
headers: {}
};
};
HTTPParser.prototype.consumeLine = function () {
if (this.captureStart === undefined) {
this.captureStart = this.offset;
}
var byte = this.chunk[this.offset];
if (byte === 0x0d && this.lineState === "DATA") { // \r
this.captureEnd = this.offset;
this.lineState = "ENDING";
return;
}
if (this.lineState === "ENDING") {
this.lineState = "DATA";
if (byte !== 0x0a) {
return;
}
var line = this.chunk.toString("ascii", this.captureStart, this.captureEnd);
this.captureStart = undefined;
this.captureEnd = undefined;
return line;
}
}
var requestExp = /^([A-Z]+) (.*) HTTP\/([0-9]).([0-9])$/;
HTTPParser.prototype.REQUEST_LINE = function () {
var line = this.consumeLine();
if (line === undefined) return;
var match = requestExp.exec(line);
this.info.method = match[1];
this.info.url = match[2];
this.info.versionMajor = match[3];
this.info.versionMinor = match[4];
this.state = "HEADER";
};
var headerExp = /^([^:]+): *(.*)$/;
HTTPParser.prototype.HEADER = function () {
var line = this.consumeLine();
if (line === undefined) return;
if (line) {
var match = headerExp.exec(line);
this.info.headers[match[1].toLowerCase()] = match[2];
}
else {
this.onHeadersComplete(this.info);
this.state = "BODY";
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment