I adapted this functions to get redirected uri in Node.js with built-in http or https module (Based on URL):
function hasHeader(header, headers) {
var headers = Object.keys(headers)
, lheaders = headers.map(function (h) { return h.toLowerCase() })
;
header = header.toLowerCase()
for (var i = 0; i < lheaders.length; i++) {
if (lheaders[i] === header) return headers[i]
}
return false
}//hasHeader
function redirect_resolve(url, resolve, reject) {
var q = new URL(url);
var protocol = (q.protocol == "http") ? require('http') : require('https');
let options = {
path: q.pathname,
host: q.hostname,
port: q.port,
protocol: q.protocol,
method: 'HEAD'
};
// protocol.get(url, (res) => { // this works
protocol.request(options, (res) => { // this one hangs...
if (res.statusCode >= 300 && res.statusCode < 400 && hasHeader('location', res.headers)) {
return redirect_resolve(res.headers.location, resolve, reject)
}
res.on("data", (_) => { // LP: required to fire "end"
});
res.on("end", () => {
return resolve({
status_code: res.statusCode,
uri: url
});
});
}).end();
}//redirect
async function redirect(url) {
return new Promise((resolve, reject) => redirect_resolve(url, resolve, reject));
}
The version using the simpler protocol.get it works, while using protocol.request(options) it hangs:
for (const uri of uris) {
try {
var res = await redirect(uri);
console.log("URL: [%s]\nREDIRECTED: [%s]\nstatus_code: %d\n", uri, res.uri, res.status_code);
} catch (error) {
console.error(error);
}
}
This code will return an error when using protocol.request:
events.js:352
throw er; // Unhandled 'error' event
^
Error: connect ECONNREFUSED xxx.xxx.xxx.xxx:443
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1148:16)
Emitted 'error' event on ClientRequest instance at: