diff --git a/benchmark/http_simple.js b/benchmark/http_simple.js index 6d21c38eb5e29a..40515779928e60 100644 --- a/benchmark/http_simple.js +++ b/benchmark/http_simple.js @@ -1,7 +1,7 @@ path = require("path"); var puts = require("sys").puts; -http = require("http2"); +http = require("http"); fixed = "" for (var i = 0; i < 20*1024; i++) { diff --git a/lib/http.js b/lib/http.js index 832df6b2cb25a5..a8d09d3ea8c718 100644 --- a/lib/http.js +++ b/lib/http.js @@ -1,11 +1,110 @@ var sys = require('sys'); +var net = require('net'); var events = require('events'); -// FIXME: The TCP binding isn't actually used here, but it needs to be -// loaded before the http binding. -process.binding('tcp'); +var HTTPParser = process.binding('http_parser').HTTPParser; + +var parserFreeList = []; + +function newParser (type) { + var parser; + if (parserFreeList.length) { + parser = parserFreeList.shift(); + parser.reinitialize(type); + } else { + parser = new HTTPParser(type); + + parser.onMessageBegin = function () { + parser.incoming = new IncomingMessage(parser.socket); + parser.field = null; + parser.value = null; + }; + + // Only servers will get URL events. + parser.onURL = function (b, start, len) { + var slice = b.asciiSlice(start, start+len); + if (parser.incoming.url) { + parser.incoming.url += slice; + } else { + // Almost always will branch here. + parser.incoming.url = slice; + } + }; + + parser.onHeaderField = function (b, start, len) { + var slice = b.asciiSlice(start, start+len).toLowerCase(); + if (parser.value) { + parser.incoming._addHeaderLine(parser.field, parser.value); + parser.field = null; + parser.value = null; + } + if (parser.field) { + parser.field += slice; + } else { + parser.field = slice; + } + }; + + parser.onHeaderValue = function (b, start, len) { + var slice = b.asciiSlice(start, start+len); + if (parser.value) { + parser.value += slice; + } else { + parser.value = slice; + } + }; + + parser.onHeadersComplete = function (info) { + if (parser.field && parser.value) { + parser.incoming._addHeaderLine(parser.field, parser.value); + } + + parser.incoming.httpVersionMajor = info.versionMajor; + parser.incoming.httpVersionMinor = info.versionMinor; + + if (info.method) { + // server only + parser.incoming.method = info.method; + } else { + // client only + parser.incoming.statusCode = info.statusCode; + } + + parser.onIncoming(parser.incoming, info.shouldKeepAlive); + }; + + parser.onBody = function (b, start, len) { + // TODO body encoding? + var enc = parser.incoming._encoding; + if (!enc) { + parser.incoming.emit('data', b.slice(start, start+len)); + } else { + var string; + switch (enc) { + case 'utf8': + string = b.utf8Slice(start, start+len); + break; + case 'ascii': + string = b.asciiSlice(start, start+len); + break; + default: + throw new Error('Unsupported encoding ' + self._encoding + '. Use Buffer'); + } + parser.incoming.emit('data', string); + } + }; + + parser.onMessageComplete = function () { + parser.incoming.emit("end"); + }; + } + return parser; +} + +function freeParser (parser) { + if (parserFreeList.length < 1000) parserFreeList.push(parser); +} -var http = process.binding('http'); var CRLF = "\r\n"; var STATUS_CODES = exports.STATUS_CODES = { @@ -56,10 +155,10 @@ var content_length_expression = /Content-Length/i; /* Abstract base class for ServerRequest and ClientResponse. */ -function IncomingMessage (connection) { +function IncomingMessage (socket) { events.EventEmitter.call(this); - this.connection = connection; + this.socket = socket; this.httpVersion = null; this.headers = {}; @@ -70,7 +169,7 @@ function IncomingMessage (connection) { // response (client) only this.statusCode = null; - this.client = this.connection; + this.client = this.socket; } sys.inherits(IncomingMessage, events.EventEmitter); exports.IncomingMessage = IncomingMessage; @@ -80,16 +179,21 @@ IncomingMessage.prototype._parseQueryString = function () { }; IncomingMessage.prototype.setBodyEncoding = function (enc) { - // TODO: Find a cleaner way of doing this. - this.connection.setEncoding(enc); + // TODO deprecation message? + this.setEncoding(enc); +}; + +IncomingMessage.prototype.setEncoding = function (enc) { + // TODO check values, error out on bad, and deprecation message? + this._encoding = enc.toLowerCase(); }; IncomingMessage.prototype.pause = function () { - this.connection.pause(); + this.socket.pause(); }; IncomingMessage.prototype.resume = function () { - this.connection.resume(); + this.socket.resume(); }; IncomingMessage.prototype._addHeaderLine = function (field, value) { @@ -102,10 +206,10 @@ IncomingMessage.prototype._addHeaderLine = function (field, value) { } }; -function OutgoingMessage (connection) { - events.EventEmitter.call(this, connection); +function OutgoingMessage (socket) { + events.EventEmitter.call(this, socket); - this.connection = connection; + this.socket = socket; this.output = []; this.outputEncodings = []; @@ -126,7 +230,7 @@ exports.OutgoingMessage = OutgoingMessage; OutgoingMessage.prototype._send = function (data, encoding) { var length = this.output.length; - if (length === 0) { + if (length === 0 || typeof data != 'string') { this.output.push(data); encoding = encoding || "ascii"; this.outputEncodings.push(encoding); @@ -138,11 +242,7 @@ OutgoingMessage.prototype._send = function (data, encoding) { if ((lastEncoding === encoding) || (!encoding && data.constructor === lastData.constructor)) { - if (lastData.constructor === String) { - this.output[length-1] = lastData + data; - } else { - this.output[length-1] = lastData.concat(data); - } + this.output[length-1] = lastData + data; return; } @@ -228,7 +328,11 @@ OutgoingMessage.prototype.write = function (chunk, encoding) { encoding = encoding || "ascii"; if (this.chunked_encoding) { - this._send(process._byteLength(chunk, encoding).toString(16)); + if (typeof chunk == 'string') { + this._send(process._byteLength(chunk, encoding).toString(16)); + } else { + this._send(chunk.length.toString(16)); + } this._send(CRLF); this._send(chunk, encoding); this._send(CRLF); @@ -259,7 +363,7 @@ OutgoingMessage.prototype.close = function () { function ServerResponse (req) { - OutgoingMessage.call(this, req.connection); + OutgoingMessage.call(this, req.socket); if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) { this.use_chunked_encoding_by_default = false; @@ -297,8 +401,8 @@ ServerResponse.prototype.writeHead = function (statusCode) { ServerResponse.prototype.sendHeader = ServerResponse.prototype.writeHead; ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead; -function ClientRequest (connection, method, url, headers) { - OutgoingMessage.call(this, connection); +function ClientRequest (socket, method, url, headers) { + OutgoingMessage.call(this, socket); this.should_keep_alive = false; if (method === "GET" || method === "HEAD") { @@ -330,85 +434,19 @@ ClientRequest.prototype.close = function () { }; -function createIncomingMessageStream (connection, incoming_listener) { - var incoming, field, value; - - connection.addListener("messageBegin", function () { - incoming = new IncomingMessage(connection); - field = null; - value = null; - }); - - // Only servers will get URL events. - connection.addListener("url", function (data) { - incoming.url += data; - }); - - connection.addListener("headerField", function (data) { - if (value) { - incoming._addHeaderLine(field, value); - field = null; - value = null; - } - if (field) { - field += data; - } else { - field = data; - } - }); - - connection.addListener("headerValue", function (data) { - if (value) { - value += data; - } else { - value = data; - } - }); - - connection.addListener("headerComplete", function (info) { - if (field && value) { - incoming._addHeaderLine(field, value); - } - - incoming.httpVersion = info.httpVersion; - incoming.httpVersionMajor = info.versionMajor; - incoming.httpVersionMinor = info.versionMinor; - - if (info.method) { - // server only - incoming.method = info.method; - } else { - // client only - incoming.statusCode = info.statusCode; - } - - incoming_listener(incoming, info.should_keep_alive); - }); - - connection.addListener("body", function (chunk) { - incoming.emit('data', chunk); - }); - - connection.addListener("messageComplete", function () { - incoming.emit('end'); - }); -} - -/* Returns true if the message queue is finished and the connection +/* Returns true if the message queue is finished and the socket * should be closed. */ -function flushMessageQueue (connection, queue) { +function flushMessageQueue (socket, queue) { while (queue[0]) { var message = queue[0]; while (message.output.length > 0) { - if (connection.readyState !== "open" && connection.readyState !== "writeOnly") { - return true; - } + if (!socket.writable) return true; var data = message.output.shift(); var encoding = message.outputEncodings.shift(); - connection.write(data, encoding); + socket.write(data, encoding); } if (!message.finished) break; @@ -422,152 +460,173 @@ function flushMessageQueue (connection, queue) { } -exports.createServer = function (requestListener, options) { - var server = new http.Server(); - //server.setOptions(options); - server.addListener("request", requestListener); - server.addListener("connection", connectionListener); - return server; +function Server (requestListener) { + net.Server.call(this); + this.addListener("request", requestListener); + this.addListener("connection", connectionListener); +} +sys.inherits(Server, net.Server); + +exports.Server = Server; + +exports.createServer = function (requestListener) { + return new Server(requestListener); }; -function connectionListener (connection) { - // An array of responses for each connection. In pipelined connections +function connectionListener (socket) { + var self = this; + // An array of responses for each socket. In pipelined connections // we need to keep track of the order they were sent. var responses = []; - connection.resetParser(); + var parser = newParser('request'); + + socket.ondata = function (d, start, end) { + parser.execute(d, start, end - start); + }; + + socket.onend = function () { + parser.finish(); + // unref the parser for easy gc + freeParser(parser); - // is this really needed? - connection.addListener("end", function () { if (responses.length == 0) { - connection.close(); + socket.close(); } else { responses[responses.length-1].closeOnFinish = true; } - }); - + }; - createIncomingMessageStream(connection, function (incoming, should_keep_alive) { + parser.socket = socket; + // The following callback is issued after the headers have been read on a + // new message. In this callback we setup the response object and pass it + // to the user. + parser.onIncoming = function (incoming, shouldKeepAlive) { var req = incoming; - var res = new ServerResponse(req); - res.should_keep_alive = should_keep_alive; - res.addListener("flush", function () { - if (flushMessageQueue(connection, responses)) { - connection.close(); + + res.shouldKeepAlive = shouldKeepAlive; + res.addListener('flush', function () { + if (flushMessageQueue(socket, responses)) { + socket.close(); } }); responses.push(res); - connection.server.emit("request", req, res); - }); + self.emit('request', req, res); + }; } -exports.createClient = function (port, host) { - var client = new http.Client(); - var secure_credentials={ secure : false }; +function Client ( ) { + net.Stream.call(this); + + var self = this; var requests = []; var currentRequest; - client.tcpSetSecure = client.setSecure; - client.setSecure = function(format_type, ca_certs, crl_list, private_key, certificate) { - secure_credentials.secure = true; - secure_credentials.format_type = format_type; - secure_credentials.ca_certs = ca_certs; - secure_credentials.crl_list = crl_list; - secure_credentials.private_key = private_key; - secure_credentials.certificate = certificate; - } + var parser = newParser('response'); + parser.socket = this; - client._reconnect = function () { - if (client.readyState != "opening") { - //sys.debug("HTTP CLIENT: reconnecting readyState = " + client.readyState); - client.connect(port, host); - if (secure_credentials.secure) { - client.tcpSetSecure(secure_credentials.format_type, - secure_credentials.ca_certs, - secure_credentials.crl_list, - secure_credentials.private_key, - secure_credentials.certificate); - } + self._reconnect = function () { + if (self.readyState != "opening") { + sys.debug("HTTP CLIENT: reconnecting readyState = " + self.readyState); + self.connect(self.port, self.host); } }; - client._pushRequest = function (req) { + self._pushRequest = function (req) { req.addListener("flush", function () { - if (client.readyState == "closed") { - //sys.debug("HTTP CLIENT request flush. reconnect. readyState = " + client.readyState); - client._reconnect(); + if (self.readyState == "closed") { + sys.debug("HTTP CLIENT request flush. reconnect. readyState = " + self.readyState); + self._reconnect(); return; } - //sys.debug("client flush readyState = " + client.readyState); - if (req == currentRequest) flushMessageQueue(client, [req]); + + sys.debug("self flush readyState = " + self.readyState); + if (req == currentRequest) flushMessageQueue(self, [req]); }); requests.push(req); }; - client.addListener("connect", function () { - client.resetParser(); - currentRequest = requests.shift(); + this.ondata = function (d, start, end) { + parser.execute(d, start, end - start); + }; + + self.addListener("connect", function () { + parser.reinitialize('response'); + sys.puts('requests: ' + sys.inspect(requests)); + currentRequest = requests.shift() currentRequest.flush(); }); - client.addListener("end", function () { - //sys.debug("client got end closing. readyState = " + client.readyState); - client.close(); + self.addListener("end", function () { + parser.finish(); + freeParser(parser); + + //sys.debug("self got end closing. readyState = " + self.readyState); + self.close(); }); - client.addListener("close", function (had_error) { + self.addListener("close", function (had_error) { if (had_error) { - client.emit("error"); + self.emit("error"); return; } - //sys.debug("HTTP CLIENT onClose. readyState = " + client.readyState); + sys.debug("HTTP CLIENT onClose. readyState = " + self.readyState); // If there are more requests to handle, reconnect. if (requests.length > 0) { - client._reconnect(); + self._reconnect(); } }); - createIncomingMessageStream(client, function (res) { - //sys.debug("incoming response!"); + parser.onIncoming = function (res) { + sys.debug("incoming response!"); res.addListener('end', function ( ) { - //sys.debug("request complete disconnecting. readyState = " + client.readyState); - client.close(); + //sys.debug("request complete disconnecting. readyState = " + self.readyState); + self.close(); }); currentRequest.emit("response", res); - }); - - return client; + }; }; +sys.inherits(Client, net.Stream); + +exports.Client = Client; + +exports.createClient = function (port, host) { + var c = new Client; + c.port = port; + c.host = host; + return c; +} + -http.Client.prototype.get = function () { +Client.prototype.get = function () { throw new Error("client.get(...) is now client.request('GET', ...)"); }; -http.Client.prototype.head = function () { +Client.prototype.head = function () { throw new Error("client.head(...) is now client.request('HEAD', ...)"); }; -http.Client.prototype.post = function () { +Client.prototype.post = function () { throw new Error("client.post(...) is now client.request('POST', ...)"); }; -http.Client.prototype.del = function () { +Client.prototype.del = function () { throw new Error("client.del(...) is now client.request('DELETE', ...)"); }; -http.Client.prototype.put = function () { +Client.prototype.put = function () { throw new Error("client.put(...) is now client.request('PUT', ...)"); }; -http.Client.prototype.request = function (method, url, headers) { +Client.prototype.request = function (method, url, headers) { if (typeof(url) != "string") { // assume method was omitted, shift arguments headers = url; url = method; @@ -580,7 +639,7 @@ http.Client.prototype.request = function (method, url, headers) { exports.cat = function (url, encoding_, headers_) { - var encoding = 'utf8', + var encoding = 'utf8', headers = {}, callback = null; diff --git a/lib/http2.js b/lib/http_old.js similarity index 63% rename from lib/http2.js rename to lib/http_old.js index a8d09d3ea8c718..832df6b2cb25a5 100644 --- a/lib/http2.js +++ b/lib/http_old.js @@ -1,110 +1,11 @@ var sys = require('sys'); -var net = require('net'); var events = require('events'); -var HTTPParser = process.binding('http_parser').HTTPParser; - -var parserFreeList = []; - -function newParser (type) { - var parser; - if (parserFreeList.length) { - parser = parserFreeList.shift(); - parser.reinitialize(type); - } else { - parser = new HTTPParser(type); - - parser.onMessageBegin = function () { - parser.incoming = new IncomingMessage(parser.socket); - parser.field = null; - parser.value = null; - }; - - // Only servers will get URL events. - parser.onURL = function (b, start, len) { - var slice = b.asciiSlice(start, start+len); - if (parser.incoming.url) { - parser.incoming.url += slice; - } else { - // Almost always will branch here. - parser.incoming.url = slice; - } - }; - - parser.onHeaderField = function (b, start, len) { - var slice = b.asciiSlice(start, start+len).toLowerCase(); - if (parser.value) { - parser.incoming._addHeaderLine(parser.field, parser.value); - parser.field = null; - parser.value = null; - } - if (parser.field) { - parser.field += slice; - } else { - parser.field = slice; - } - }; - - parser.onHeaderValue = function (b, start, len) { - var slice = b.asciiSlice(start, start+len); - if (parser.value) { - parser.value += slice; - } else { - parser.value = slice; - } - }; - - parser.onHeadersComplete = function (info) { - if (parser.field && parser.value) { - parser.incoming._addHeaderLine(parser.field, parser.value); - } - - parser.incoming.httpVersionMajor = info.versionMajor; - parser.incoming.httpVersionMinor = info.versionMinor; - - if (info.method) { - // server only - parser.incoming.method = info.method; - } else { - // client only - parser.incoming.statusCode = info.statusCode; - } - - parser.onIncoming(parser.incoming, info.shouldKeepAlive); - }; - - parser.onBody = function (b, start, len) { - // TODO body encoding? - var enc = parser.incoming._encoding; - if (!enc) { - parser.incoming.emit('data', b.slice(start, start+len)); - } else { - var string; - switch (enc) { - case 'utf8': - string = b.utf8Slice(start, start+len); - break; - case 'ascii': - string = b.asciiSlice(start, start+len); - break; - default: - throw new Error('Unsupported encoding ' + self._encoding + '. Use Buffer'); - } - parser.incoming.emit('data', string); - } - }; - - parser.onMessageComplete = function () { - parser.incoming.emit("end"); - }; - } - return parser; -} - -function freeParser (parser) { - if (parserFreeList.length < 1000) parserFreeList.push(parser); -} +// FIXME: The TCP binding isn't actually used here, but it needs to be +// loaded before the http binding. +process.binding('tcp'); +var http = process.binding('http'); var CRLF = "\r\n"; var STATUS_CODES = exports.STATUS_CODES = { @@ -155,10 +56,10 @@ var content_length_expression = /Content-Length/i; /* Abstract base class for ServerRequest and ClientResponse. */ -function IncomingMessage (socket) { +function IncomingMessage (connection) { events.EventEmitter.call(this); - this.socket = socket; + this.connection = connection; this.httpVersion = null; this.headers = {}; @@ -169,7 +70,7 @@ function IncomingMessage (socket) { // response (client) only this.statusCode = null; - this.client = this.socket; + this.client = this.connection; } sys.inherits(IncomingMessage, events.EventEmitter); exports.IncomingMessage = IncomingMessage; @@ -179,21 +80,16 @@ IncomingMessage.prototype._parseQueryString = function () { }; IncomingMessage.prototype.setBodyEncoding = function (enc) { - // TODO deprecation message? - this.setEncoding(enc); -}; - -IncomingMessage.prototype.setEncoding = function (enc) { - // TODO check values, error out on bad, and deprecation message? - this._encoding = enc.toLowerCase(); + // TODO: Find a cleaner way of doing this. + this.connection.setEncoding(enc); }; IncomingMessage.prototype.pause = function () { - this.socket.pause(); + this.connection.pause(); }; IncomingMessage.prototype.resume = function () { - this.socket.resume(); + this.connection.resume(); }; IncomingMessage.prototype._addHeaderLine = function (field, value) { @@ -206,10 +102,10 @@ IncomingMessage.prototype._addHeaderLine = function (field, value) { } }; -function OutgoingMessage (socket) { - events.EventEmitter.call(this, socket); +function OutgoingMessage (connection) { + events.EventEmitter.call(this, connection); - this.socket = socket; + this.connection = connection; this.output = []; this.outputEncodings = []; @@ -230,7 +126,7 @@ exports.OutgoingMessage = OutgoingMessage; OutgoingMessage.prototype._send = function (data, encoding) { var length = this.output.length; - if (length === 0 || typeof data != 'string') { + if (length === 0) { this.output.push(data); encoding = encoding || "ascii"; this.outputEncodings.push(encoding); @@ -242,7 +138,11 @@ OutgoingMessage.prototype._send = function (data, encoding) { if ((lastEncoding === encoding) || (!encoding && data.constructor === lastData.constructor)) { - this.output[length-1] = lastData + data; + if (lastData.constructor === String) { + this.output[length-1] = lastData + data; + } else { + this.output[length-1] = lastData.concat(data); + } return; } @@ -328,11 +228,7 @@ OutgoingMessage.prototype.write = function (chunk, encoding) { encoding = encoding || "ascii"; if (this.chunked_encoding) { - if (typeof chunk == 'string') { - this._send(process._byteLength(chunk, encoding).toString(16)); - } else { - this._send(chunk.length.toString(16)); - } + this._send(process._byteLength(chunk, encoding).toString(16)); this._send(CRLF); this._send(chunk, encoding); this._send(CRLF); @@ -363,7 +259,7 @@ OutgoingMessage.prototype.close = function () { function ServerResponse (req) { - OutgoingMessage.call(this, req.socket); + OutgoingMessage.call(this, req.connection); if (req.httpVersionMajor < 1 || req.httpVersionMinor < 1) { this.use_chunked_encoding_by_default = false; @@ -401,8 +297,8 @@ ServerResponse.prototype.writeHead = function (statusCode) { ServerResponse.prototype.sendHeader = ServerResponse.prototype.writeHead; ServerResponse.prototype.writeHeader = ServerResponse.prototype.writeHead; -function ClientRequest (socket, method, url, headers) { - OutgoingMessage.call(this, socket); +function ClientRequest (connection, method, url, headers) { + OutgoingMessage.call(this, connection); this.should_keep_alive = false; if (method === "GET" || method === "HEAD") { @@ -434,19 +330,85 @@ ClientRequest.prototype.close = function () { }; -/* Returns true if the message queue is finished and the socket +function createIncomingMessageStream (connection, incoming_listener) { + var incoming, field, value; + + connection.addListener("messageBegin", function () { + incoming = new IncomingMessage(connection); + field = null; + value = null; + }); + + // Only servers will get URL events. + connection.addListener("url", function (data) { + incoming.url += data; + }); + + connection.addListener("headerField", function (data) { + if (value) { + incoming._addHeaderLine(field, value); + field = null; + value = null; + } + if (field) { + field += data; + } else { + field = data; + } + }); + + connection.addListener("headerValue", function (data) { + if (value) { + value += data; + } else { + value = data; + } + }); + + connection.addListener("headerComplete", function (info) { + if (field && value) { + incoming._addHeaderLine(field, value); + } + + incoming.httpVersion = info.httpVersion; + incoming.httpVersionMajor = info.versionMajor; + incoming.httpVersionMinor = info.versionMinor; + + if (info.method) { + // server only + incoming.method = info.method; + } else { + // client only + incoming.statusCode = info.statusCode; + } + + incoming_listener(incoming, info.should_keep_alive); + }); + + connection.addListener("body", function (chunk) { + incoming.emit('data', chunk); + }); + + connection.addListener("messageComplete", function () { + incoming.emit('end'); + }); +} + +/* Returns true if the message queue is finished and the connection * should be closed. */ -function flushMessageQueue (socket, queue) { +function flushMessageQueue (connection, queue) { while (queue[0]) { var message = queue[0]; while (message.output.length > 0) { - if (!socket.writable) return true; + if (connection.readyState !== "open" && connection.readyState !== "writeOnly") { + return true; + } var data = message.output.shift(); var encoding = message.outputEncodings.shift(); - socket.write(data, encoding); + connection.write(data, encoding); } if (!message.finished) break; @@ -460,173 +422,152 @@ function flushMessageQueue (socket, queue) { } -function Server (requestListener) { - net.Server.call(this); - this.addListener("request", requestListener); - this.addListener("connection", connectionListener); -} -sys.inherits(Server, net.Server); - -exports.Server = Server; - -exports.createServer = function (requestListener) { - return new Server(requestListener); +exports.createServer = function (requestListener, options) { + var server = new http.Server(); + //server.setOptions(options); + server.addListener("request", requestListener); + server.addListener("connection", connectionListener); + return server; }; -function connectionListener (socket) { - var self = this; - // An array of responses for each socket. In pipelined connections +function connectionListener (connection) { + // An array of responses for each connection. In pipelined connections // we need to keep track of the order they were sent. var responses = []; - var parser = newParser('request'); - - socket.ondata = function (d, start, end) { - parser.execute(d, start, end - start); - }; - - socket.onend = function () { - parser.finish(); - // unref the parser for easy gc - freeParser(parser); + connection.resetParser(); + // is this really needed? + connection.addListener("end", function () { if (responses.length == 0) { - socket.close(); + connection.close(); } else { responses[responses.length-1].closeOnFinish = true; } - }; + }); - parser.socket = socket; - // The following callback is issued after the headers have been read on a - // new message. In this callback we setup the response object and pass it - // to the user. - parser.onIncoming = function (incoming, shouldKeepAlive) { + + createIncomingMessageStream(connection, function (incoming, should_keep_alive) { var req = incoming; - var res = new ServerResponse(req); - res.shouldKeepAlive = shouldKeepAlive; - res.addListener('flush', function () { - if (flushMessageQueue(socket, responses)) { - socket.close(); + var res = new ServerResponse(req); + res.should_keep_alive = should_keep_alive; + res.addListener("flush", function () { + if (flushMessageQueue(connection, responses)) { + connection.close(); } }); responses.push(res); - self.emit('request', req, res); - }; + connection.server.emit("request", req, res); + }); } -function Client ( ) { - net.Stream.call(this); - - var self = this; +exports.createClient = function (port, host) { + var client = new http.Client(); + var secure_credentials={ secure : false }; var requests = []; var currentRequest; - var parser = newParser('response'); - parser.socket = this; + client.tcpSetSecure = client.setSecure; + client.setSecure = function(format_type, ca_certs, crl_list, private_key, certificate) { + secure_credentials.secure = true; + secure_credentials.format_type = format_type; + secure_credentials.ca_certs = ca_certs; + secure_credentials.crl_list = crl_list; + secure_credentials.private_key = private_key; + secure_credentials.certificate = certificate; + } - self._reconnect = function () { - if (self.readyState != "opening") { - sys.debug("HTTP CLIENT: reconnecting readyState = " + self.readyState); - self.connect(self.port, self.host); + client._reconnect = function () { + if (client.readyState != "opening") { + //sys.debug("HTTP CLIENT: reconnecting readyState = " + client.readyState); + client.connect(port, host); + if (secure_credentials.secure) { + client.tcpSetSecure(secure_credentials.format_type, + secure_credentials.ca_certs, + secure_credentials.crl_list, + secure_credentials.private_key, + secure_credentials.certificate); + } } }; - self._pushRequest = function (req) { + client._pushRequest = function (req) { req.addListener("flush", function () { - if (self.readyState == "closed") { - sys.debug("HTTP CLIENT request flush. reconnect. readyState = " + self.readyState); - self._reconnect(); + if (client.readyState == "closed") { + //sys.debug("HTTP CLIENT request flush. reconnect. readyState = " + client.readyState); + client._reconnect(); return; } - - sys.debug("self flush readyState = " + self.readyState); - if (req == currentRequest) flushMessageQueue(self, [req]); + //sys.debug("client flush readyState = " + client.readyState); + if (req == currentRequest) flushMessageQueue(client, [req]); }); requests.push(req); }; - this.ondata = function (d, start, end) { - parser.execute(d, start, end - start); - }; - - self.addListener("connect", function () { - parser.reinitialize('response'); - sys.puts('requests: ' + sys.inspect(requests)); - currentRequest = requests.shift() + client.addListener("connect", function () { + client.resetParser(); + currentRequest = requests.shift(); currentRequest.flush(); }); - self.addListener("end", function () { - parser.finish(); - freeParser(parser); - - //sys.debug("self got end closing. readyState = " + self.readyState); - self.close(); + client.addListener("end", function () { + //sys.debug("client got end closing. readyState = " + client.readyState); + client.close(); }); - self.addListener("close", function (had_error) { + client.addListener("close", function (had_error) { if (had_error) { - self.emit("error"); + client.emit("error"); return; } - sys.debug("HTTP CLIENT onClose. readyState = " + self.readyState); + //sys.debug("HTTP CLIENT onClose. readyState = " + client.readyState); // If there are more requests to handle, reconnect. if (requests.length > 0) { - self._reconnect(); + client._reconnect(); } }); - parser.onIncoming = function (res) { - sys.debug("incoming response!"); + createIncomingMessageStream(client, function (res) { + //sys.debug("incoming response!"); res.addListener('end', function ( ) { - //sys.debug("request complete disconnecting. readyState = " + self.readyState); - self.close(); + //sys.debug("request complete disconnecting. readyState = " + client.readyState); + client.close(); }); currentRequest.emit("response", res); - }; -}; -sys.inherits(Client, net.Stream); - -exports.Client = Client; - -exports.createClient = function (port, host) { - var c = new Client; - c.port = port; - c.host = host; - return c; -} + }); + return client; +}; -Client.prototype.get = function () { +http.Client.prototype.get = function () { throw new Error("client.get(...) is now client.request('GET', ...)"); }; -Client.prototype.head = function () { +http.Client.prototype.head = function () { throw new Error("client.head(...) is now client.request('HEAD', ...)"); }; -Client.prototype.post = function () { +http.Client.prototype.post = function () { throw new Error("client.post(...) is now client.request('POST', ...)"); }; -Client.prototype.del = function () { +http.Client.prototype.del = function () { throw new Error("client.del(...) is now client.request('DELETE', ...)"); }; -Client.prototype.put = function () { +http.Client.prototype.put = function () { throw new Error("client.put(...) is now client.request('PUT', ...)"); }; -Client.prototype.request = function (method, url, headers) { +http.Client.prototype.request = function (method, url, headers) { if (typeof(url) != "string") { // assume method was omitted, shift arguments headers = url; url = method; @@ -639,7 +580,7 @@ Client.prototype.request = function (method, url, headers) { exports.cat = function (url, encoding_, headers_) { - var encoding = 'utf8', + var encoding = 'utf8', headers = {}, callback = null; diff --git a/src/node.cc b/src/node.cc index 42b7ff77bf4d28..3fb9f8043692af 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1190,7 +1190,7 @@ static Handle Binding(const Arguments& args) { exports->Set(String::New("file"), String::New(native_file)); exports->Set(String::New("fs"), String::New(native_fs)); exports->Set(String::New("http"), String::New(native_http)); - exports->Set(String::New("http2"), String::New(native_http2)); + exports->Set(String::New("http_old"), String::New(native_http_old)); exports->Set(String::New("ini"), String::New(native_ini)); exports->Set(String::New("mjsunit"), String::New(native_mjsunit)); exports->Set(String::New("multipart"), String::New(native_multipart)); diff --git a/test/simple/test-event-emitter-modify-in-emit.js b/test/simple/test-event-emitter-modify-in-emit.js index 1dd94ba7127ddf..81bba7c89e32f5 100644 --- a/test/simple/test-event-emitter-modify-in-emit.js +++ b/test/simple/test-event-emitter-modify-in-emit.js @@ -35,4 +35,4 @@ e.addListener("foo", callback1); e.addListener("foo", callback2); assert.equal(2, e.listeners("foo").length) e.removeAllListeners("foo") -assert.equal(0, e.listeners("foo").length) \ No newline at end of file +assert.equal(0, e.listeners("foo").length) diff --git a/test/simple/test-file-read-stream.js b/test/simple/test-file-read-stream.js index df57387947b29e..3ac308b9a26dad 100644 --- a/test/simple/test-file-read-stream.js +++ b/test/simple/test-file-read-stream.js @@ -60,4 +60,4 @@ process.addListener('exit', function() { for (var k in callbacks) { assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); } -}); \ No newline at end of file +}); diff --git a/test/simple/test-file-write-stream.js b/test/simple/test-file-write-stream.js index 579455c7d91bde..df045998cd7b67 100644 --- a/test/simple/test-file-write-stream.js +++ b/test/simple/test-file-write-stream.js @@ -59,4 +59,4 @@ process.addListener('exit', function() { for (var k in callbacks) { assert.equal(0, callbacks[k], k+' count off by '+callbacks[k]); } -}); \ No newline at end of file +}); diff --git a/test/simple/test-http-1.0.js b/test/simple/test-http-1.0.js index 106313d2817735..105acdcd8babcc 100644 --- a/test/simple/test-http-1.0.js +++ b/test/simple/test-http-1.0.js @@ -1,6 +1,6 @@ require("../common"); net = require("net"); -http = require("http2"); +http = require("http"); var body = "hello world\n"; var server_response = ""; diff --git a/test/simple/test-http-cat.js b/test/simple/test-http-cat.js index 32177ee92b8c24..e81a5c502fe531 100644 --- a/test/simple/test-http-cat.js +++ b/test/simple/test-http-cat.js @@ -1,5 +1,5 @@ require("../common"); -http = require("http2"); +http = require("http"); var body = "exports.A = function() { return 'A';}"; var server = http.createServer(function (req, res) { diff --git a/test/simple/test-http-chunked.js b/test/simple/test-http-chunked.js index 4325d113dabc63..a838235472d642 100644 --- a/test/simple/test-http-chunked.js +++ b/test/simple/test-http-chunked.js @@ -1,5 +1,5 @@ require("../common"); -var http = require("http2"); +var http = require("http"); var UTF8_STRING = "Il était tué"; diff --git a/test/simple/test-http-client-race.js b/test/simple/test-http-client-race.js index a3824cfce1e823..9076924b37e870 100644 --- a/test/simple/test-http-client-race.js +++ b/test/simple/test-http-client-race.js @@ -1,5 +1,5 @@ require("../common"); -http = require("http2"); +http = require("http"); url = require("url"); var body1_s = "1111111111111111"; diff --git a/test/simple/test-http-client-upload.js b/test/simple/test-http-client-upload.js index e1d746c35d2da1..b4c0f61acba059 100644 --- a/test/simple/test-http-client-upload.js +++ b/test/simple/test-http-client-upload.js @@ -1,5 +1,5 @@ require("../common"); -http = require("http2"); +http = require("http"); var sent_body = ""; var server_req_complete = false; diff --git a/test/simple/test-http-eof-on-connect.js b/test/simple/test-http-eof-on-connect.js index 7838c8d141c96c..1f2f2e5121eba9 100644 --- a/test/simple/test-http-eof-on-connect.js +++ b/test/simple/test-http-eof-on-connect.js @@ -1,6 +1,6 @@ require("../common"); net = require("net"); -http = require("http2"); +http = require("http"); // This is a regression test for http://github.com/ry/node/issues/#issue/44 // It is separate from test-http-malformed-request.js because it is only diff --git a/test/simple/test-http-malformed-request.js b/test/simple/test-http-malformed-request.js index 98d6da780c02e7..47bcfca3249aaa 100644 --- a/test/simple/test-http-malformed-request.js +++ b/test/simple/test-http-malformed-request.js @@ -1,6 +1,6 @@ require("../common"); net = require("net"); -http = require("http2"); +http = require("http"); url = require("url"); // Make sure no exceptions are thrown when receiving malformed HTTP diff --git a/test/simple/test-http-proxy.js b/test/simple/test-http-proxy.js index 5d57ba5310f459..348851d6bab588 100644 --- a/test/simple/test-http-proxy.js +++ b/test/simple/test-http-proxy.js @@ -1,5 +1,5 @@ require("../common"); -http = require("http2"); +http = require("http"); url = require("url"); var PROXY_PORT = PORT; diff --git a/test/simple/test-http-server.js b/test/simple/test-http-server.js index e42d55429e9146..c7deeb8baff55d 100644 --- a/test/simple/test-http-server.js +++ b/test/simple/test-http-server.js @@ -1,6 +1,6 @@ require("../common"); net = require("net"); -http = require("http2"); +http = require("http"); url = require("url"); qs = require("querystring"); diff --git a/test/simple/test-http-wget.js b/test/simple/test-http-wget.js index 38a41896034d44..1d7f341263070c 100644 --- a/test/simple/test-http-wget.js +++ b/test/simple/test-http-wget.js @@ -1,6 +1,6 @@ require("../common"); net = require("net"); -http = require("http2"); +http = require("http"); // wget sends an HTTP/1.0 request with Connection: Keep-Alive // diff --git a/test/simple/test-http.js b/test/simple/test-http.js index df0ebea4064e98..c59927763ab700 100644 --- a/test/simple/test-http.js +++ b/test/simple/test-http.js @@ -1,5 +1,5 @@ require("../common"); -http = require("http2"); +http = require("http"); url = require("url"); var responses_sent = 0; diff --git a/test/simple/test-remote-module-loading.js b/test/simple/test-remote-module-loading.js index 8a7edbbe27bf71..0a2af87e087e5e 100644 --- a/test/simple/test-remote-module-loading.js +++ b/test/simple/test-remote-module-loading.js @@ -1,6 +1,6 @@ require("../common"); -var http = require('http2'); +var http = require('http'); var sys = require('sys'); var url = require("url"); var modulesLoaded = 0;