using node http package it doesn't seem possible to catch the exception caused by opening a bad URL. This is a problem, because it kills my cluster, which I'd like to guarantee will live forever
Here's the code: (uses fibers.promise)
function openConnection(dest, port, contentType, method, throwErrorOnBadStatus)
{
"use strict";
assert.ok(dest, "generalUtilities.openConnection: dest is null");
//dest = dest.replace('//','/');
console.log('opening connection: ' + dest + " contentType: " + contentType);
var prom = promise(),
errProm = promise(),
ar = [],
urlParts = url.parse(dest),
httpClient,
req,
got,
res;
//console.log('urlParts.port: ' + urlParts.port);
if (port) {
urlParts.port = port;
} else if (!urlParts.port) {
urlParts.port = 80;
}
if (contentType) {
urlParts.accept = contentType;
} else {
urlParts.contentType = 'text/html';
}
if (!urlParts.method) {
if (method) {
urlParts.method = method;
} else {
urlParts.method = 'GET';
}
}
try {
httpClient = http.createClient(urlParts.port, urlParts.hostname);
req = httpClient.request(urlParts.method, urlParts.path, urlParts);
//console.log('req: ' + req);
//if (req.connection) {
// req.connection.setTimeout(HTTP_REQUEST_TIMEOUT);
//}
//else {
// throw new Error ("No Connection Established!");
//}
req.end();
req.on('response', prom);
req.on('error', errProm);
got = promise.waitAny(prom, errProm);
if (got === errProm) {
//assert.ifError(errProm.get(), HTTP_REQUEST_TIMEOUT_MSG + dest);
throw new Error(HTTP_REQUEST_TIMEOUT_MSG + dest + ': ' + got.get());
}
res = prom.get();
ar.res = res;
ar.statusCode = res.statusCode;
if (ar.statusCode >= 300 && throwErrorOnBadStatus) {
assert.ifError("page not found!");
}
return ar;
}
catch (err) {
console.log(err);
}
}
and here's how I tested it
var promise = require('fibers-promise');
var gu = require("../src/utils/generalutilities.js");
var brokenSite = 'http://foo.bar.com:94//foo.js';
promise.start(function () {
try {
gu.openConnection(brokenSite, null, null, "GET", true);
}
catch (err) {
console.log('got: ' + err);
}
});
When I run this code I get:
Error: getaddrinfo ENOENT. It is never caught in the try catch
It works for me, when supplying an error handler for the request:
req.on('error', errorHandler);
I see that you also do that, but you set it after issuing
req.end();
Could you try issuing the end()
after you attached the error handler?
As a side note, I really recommend request, as it handles issues like this with sensible defaults. It's really a breeze to work with.
Edit: Here is a simple example showing that attaching an error handler lets me handle ENOENT
/ENOTFOUND
errors:
var http = require('http');
var req = http.request({hostname: 'foo.example.com'}, function(err, res) {
if(err) return console.error(err);
console.log('got response!');
});
req.on('error', function(err) {
console.error('error!', err);
});
Another piece of valuable information: I'm not sure how it fits in with fibers, but in general, you should never throw
in nodejs asynchronous code. It rarely works the way you want. Instead, use the standard practice of passing any error as the first parameter to the next callback, and handle the error where it makes sense (usually, high up in the call chain where you can do something sensible with it).
You can scrape the page for the error code.