};
+
+function Client () {
+ net.Socket.call(this);
+
+ var self = this;
+ var requests = [];
+ var currentRequest;
+
+ var parser = newParser('response');
+ parser.socket = self;
+
+ self.addListener("connect", function () {
+ self.resetParser();
+ currentRequest = requests.shift();
+ currentRequest.flush();
+ });
+
+ self.ondata = function (d, start, end) {
+ parser.execute(d, start, end - start);
+ };
+
+ parser.onIncoming = function (res) {
+ //sys.debug("incoming response!");
+
+ res.addListener('end', function ( ) {
+ //sys.debug("request complete disconnecting. readyState = " + self.readyState);
+ self.close();
+ });
+
+ currentRequest.emit("response", res);
+ };
+
+ self._pushRequest = function (req) {
+ };
+
+ self.addListener("end", function () {
+ self.close();
+ });
+
+ self.onend = function () {
+ parser.finish();
+ // unref the parser for easy gc
+ freeParser(parser);
+ //sys.debug("self got end closing. readyState = " + self.readyState);
+ self.close();
+ };
+
+ self.addListener("close", function (had_error) {
+ if (had_error) {
+ self.emit("error");
+ return;
+ }
+
+ //sys.debug("HTTP CLIENT onClose. readyState = " + self.readyState);
+
+ // If there are more requests to handle, reconnect.
+ if (requests.length > 0) {
+ self._reconnect();
+ }
+ });
+}
+sys.inherits(Client, net.Socket);
+
+
+exports.Client = Client;
+
+
+exports.createClient = function (port, host) {
+ var client = new Client();
+ client.port = port;
+ client.host = host;
+ client.connect(port, host);
+ return client;
+};
+
+
+Client.prototype._reconnect = function () {
+ if (this.readyState != "opening") {
+ //sys.debug("HTTP CLIENT: reconnecting readyState = " + self.readyState);
+ this.connect(this.port, this.host);
+ }
+};
+
+
+Client.prototype.request = function (method, url, headers) {
+ var self = this;
+
+ if (typeof(url) != "string") { // assume method was omitted, shift arguments
+ headers = url;
+ url = method;
+ method = null;
+ }
+ var req = new ClientRequest(this, method || "GET", url, headers);
+
+ req.addListener("flush", function () {
+ if (self.readyState == "closed") {
+ //sys.debug("HTTP CLIENT request flush. reconnect. readyState = " + self.readyState);
+ self._reconnect();
+ return;
+ }
+ //sys.debug("self flush readyState = " + self.readyState);
+ if (req == currentRequest) flushMessageQueue(self, [req]);
+ });
+ requests.push(req);
+
+ return req;
+};
+
+Client.prototype.get = function () {
+ throw new Error("client.get(...) is now client.request('GET', ...)");
+};
+
+Client.prototype.head = function () {
+ throw new Error("client.head(...) is now client.request('HEAD', ...)");
+};
+
+Client.prototype.post = function () {
+ throw new Error("client.post(...) is now client.request('POST', ...)");
+};
+
+Client.prototype.del = function () {
+ throw new Error("client.del(...) is now client.request('DELETE', ...)");
+};
+
+Client.prototype.put = function () {
+ throw new Error("client.put(...) is now client.request('PUT', ...)");
+};
+
+
+exports.cat = function (url, encoding_, headers_) {
+ var encoding = 'utf8',
+ headers = {},
+ callback = null;
+
+ // parse the arguments for the various options... very ugly
+ if (typeof(arguments[1]) == 'string') {
+ encoding = arguments[1];
+ if (typeof(arguments[2]) == 'object') {
+ headers = arguments[2];
+ if (typeof(arguments[3]) == 'function') callback = arguments[3];
+ } else {
+ if (typeof(arguments[2]) == 'function') callback = arguments[2];
+ }
+ } else {
+ // didn't specify encoding
+ if (typeof(arguments[1]) == 'object') {
+ headers = arguments[1];
+ callback = arguments[2];
+ } else {
+ callback = arguments[1];
+ }
+ }
+
+ var url = require("url").parse(url);
+
+ var hasHost = false;
+ for (var i in headers) {
+ if (i.toLowerCase() === "host") {
+ hasHost = true;
+ break;
+ }
+ }
+ if (!hasHost) headers["Host"] = url.hostname;
+
+ var content = "";
+
+ var client = exports.createClient(url.port || 80, url.hostname);
+ var req = client.request((url.pathname || "/")+(url.search || "")+(url.hash || ""), headers);
+
+ req.addListener('response', function (res) {
+ if (res.statusCode < 200 || res.statusCode >= 300) {
+ if (callback) callback(res.statusCode);
+ client.close();
+ return;
+ }
+ res.setBodyEncoding(encoding);
+ res.addListener('data', function (chunk) { content += chunk; });
+ res.addListener('end', function () {
+ if (callback) callback(null, content);
+ });
+ });
+
+ client.addListener("error", function (err) {
+ // todo an error should actually be passed here...
+ if (callback) callback(new Error('Connection error'));
+ });
+
+ req.close();
+};
// stream.connect(80, 'nodejs.org') - TCP connect to port 80 on nodejs.org
// stream.connect('/tmp/socket') - UNIX connect to socket specified by path
Socket.prototype.connect = function () {
- initSocket(this);
-
var self = this;
+ initSocket(self);
if (self.fd) throw new Error('Socket already opened');
+ if (!self._readWatcher) throw new Error('No readWatcher');
timeout.active(socket);
- if (typeof(arguments[0]) == 'string') {
- self.fd = socket('unix');
- self.type = 'unix';
- // TODO check if sockfile exists?
- doConnect(self, arguments[0]);
- } else {
+ var port = parseInt(arguments[0]);
+
+ if (port >= 0) {
self.fd = socket('tcp');
debug('new fd = ' + self.fd);
self.type = 'tcp';
lookupDomainName(arguments[1], function (ip) {
doConnect(self, port, ip);
});
+ } else {
+ self.fd = socket('unix');
+ self.type = 'unix';
+ // TODO check if sockfile exists?
+ doConnect(self, arguments[0]);
}
};