From e901f1679ba0286c34737518113f5dcca6a89a09 Mon Sep 17 00:00:00 2001 From: tigerbot Date: Tue, 20 Jun 2017 15:33:45 -0600 Subject: [PATCH] implemented check for hotel/ISP paywall --- packages/apis/com.daplie.goldilocks/index.js | 91 ++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/packages/apis/com.daplie.goldilocks/index.js b/packages/apis/com.daplie.goldilocks/index.js index eb3d88b..6f97d2e 100644 --- a/packages/apis/com.daplie.goldilocks/index.js +++ b/packages/apis/com.daplie.goldilocks/index.js @@ -63,6 +63,81 @@ module.exports.create = function (deps, conf) { }); } + function checkPaywall() { + var PromiseA = require('bluebird'); + var testDomains = [ + 'daplie.com' + , 'duckduckgo.com' + , 'google.com' + , 'amazon.com' + , 'facebook.com' + , 'msn.com' + , 'yahoo.com' + ]; + + // While this is not being developed behind a paywall the current idea is that + // a paywall will either manipulate DNS queries to point to the paywall gate, + // or redirect HTTP requests to the paywall gate. So we check for both and + // hope we can detect most hotel/ISP paywalls out there in the world. + + return PromiseA.resolve() + .then(function () { + var dns = PromiseA.promisifyAll(require('dns')); + var proms = testDomains.map(function (dom) { + return dns.resolve6Async(dom) + .catch(function (err) { + if (err.code === 'ENODATA') { + return dns.resolve4Async(dom); + } else { + return PromiseA.reject(err); + } + }) + .then(function (result) { + return result[0]; + }); + }); + + return PromiseA.all(proms).then(function (addrs) { + var unique = addrs.filter(function (value, ind, self) { + return value && self.indexOf(value) === ind; + }); + // It is possible some walls might have exceptions that leave some of the domains + // we test alone, so we might have more than one unique address even behind an + // active paywall. + return unique.length < addrs.length; + }); + }) + .then(function (paywall) { + if (paywall) { + return paywall; + } + var request = deps.request.defaults({ + followRedirect: false + , headers: { + connection: 'close' + } + }); + + var proms = testDomains.map(function (dom) { + return request('https://'+dom).then(function (resp) { + if (resp.statusCode >= 300 && resp.statusCode < 400) { + return resp.headers.location; + } else { + return 'https://'+dom; + } + }); + }); + + return PromiseA.all(proms).then(function (urls) { + var unique = urls.filter(function (value, ind, self) { + return value && self.indexOf(value) === ind; + }); + return unique.length < urls.length; + }); + }) + ; + } + return { init: function (req, res) { if (handleCors(req, res, 'POST')) { @@ -233,6 +308,22 @@ module.exports.create = function (deps, conf) { }); }); } + , paywall_check: function (req, res) { + if (handleCors(req, res, 'GET')) { + return; + } + isAuthorized(req, res, function () { + res.setHeader('Content-Type', 'application/json;'); + + checkPaywall().then(function (paywall) { + res.end(JSON.stringify({paywall: paywall})); + }, function (err) { + err.message = err.message || err.toString(); + res.statusCode = 500; + res.end(JSON.stringify({error: {message: err.message, code: err.code}})); + }); + }); + } , _api: api }; };