2017-09-11 10:13:57 +00:00
|
|
|
const express = require('express');
|
|
|
|
const app = express();
|
|
|
|
const bodyParser = require('body-parser');
|
|
|
|
|
2017-10-01 09:51:10 +00:00
|
|
|
// const config = require('./config');
|
2017-09-11 10:13:57 +00:00
|
|
|
|
|
|
|
const log4js = require('log4js');
|
|
|
|
const logger = log4js.getLogger();
|
2018-06-13 23:18:54 +00:00
|
|
|
const urlparser = require('url');
|
|
|
|
const URL = require('url').URL;
|
2017-09-11 10:13:57 +00:00
|
|
|
const http = require('http');
|
2017-09-11 11:19:14 +00:00
|
|
|
const https = require('https');
|
2017-09-11 14:29:31 +00:00
|
|
|
const apicache = require('apicache');
|
2017-09-11 10:13:57 +00:00
|
|
|
|
2018-06-13 21:50:57 +00:00
|
|
|
const ipfilter = require('express-ipfilter').IpFilter;
|
2018-06-13 22:12:12 +00:00
|
|
|
const IpDeniedError = require('express-ipfilter').IpDeniedError;
|
2018-06-13 21:50:57 +00:00
|
|
|
|
2018-01-23 17:00:29 +00:00
|
|
|
const port = process.env.PORT || 8080;
|
2017-10-01 09:51:10 +00:00
|
|
|
|
2017-09-11 10:13:57 +00:00
|
|
|
logger.level = 'debug';
|
|
|
|
|
|
|
|
// app.use(compression());
|
|
|
|
app.use(bodyParser.json());
|
|
|
|
app.use(bodyParser.urlencoded({ 'extended': true }));
|
2017-09-11 14:36:12 +00:00
|
|
|
|
|
|
|
apicache.options({ 'debug': true });
|
2017-09-11 14:29:31 +00:00
|
|
|
const cache = apicache.middleware;
|
|
|
|
|
2018-06-13 22:12:12 +00:00
|
|
|
// app.use(cache('15 minutes'));
|
2017-09-11 10:13:57 +00:00
|
|
|
|
2018-06-14 09:02:09 +00:00
|
|
|
const ips = ['212.71.255.44', '82.35.75.161', '54.146.189.113', '52.90.194.191'];
|
2018-06-14 07:25:39 +00:00
|
|
|
|
2018-06-14 09:02:09 +00:00
|
|
|
// 54.146.189.113, 52.90.194.191 is for ifttt
|
2018-06-14 07:25:39 +00:00
|
|
|
|
2018-06-13 23:37:47 +00:00
|
|
|
const complexUrls = new Map();
|
|
|
|
|
2018-06-13 23:38:37 +00:00
|
|
|
app.use(ipfilter(ips, { 'mode': 'allow' }));
|
2018-06-13 21:57:24 +00:00
|
|
|
|
2018-06-13 22:12:12 +00:00
|
|
|
app.use((err, req, res, _next) => {
|
2018-06-14 10:33:17 +00:00
|
|
|
const thisErr = Object.assign({}, err);
|
2018-06-14 00:00:11 +00:00
|
|
|
thisErr.originalUrl = req.originalUrl;
|
|
|
|
|
2018-06-14 00:04:05 +00:00
|
|
|
console.error('Error handler', thisErr);
|
|
|
|
|
2018-06-14 00:00:11 +00:00
|
|
|
if(thisErr instanceof IpDeniedError)
|
2018-06-13 22:12:12 +00:00
|
|
|
res.status(401);
|
|
|
|
|
|
|
|
else
|
2018-06-14 00:00:11 +00:00
|
|
|
res.status(thisErr.status || 500);
|
2018-06-13 22:12:12 +00:00
|
|
|
|
|
|
|
res.status(403).end();
|
|
|
|
});
|
|
|
|
|
2017-10-01 12:37:31 +00:00
|
|
|
const bouncer = ['phpmyadmin',
|
|
|
|
'phpMyadmin',
|
|
|
|
'phpMyAdmin',
|
|
|
|
'phpmyAdmin',
|
|
|
|
'phpmyadmin2',
|
|
|
|
'phpmyadmin3',
|
|
|
|
'phpmyadmin4',
|
|
|
|
'2phpmyadmin',
|
|
|
|
'phpmy',
|
|
|
|
'phppma',
|
|
|
|
'myadmin',
|
|
|
|
'shopdb',
|
|
|
|
'MyAdmin',
|
|
|
|
'program',
|
|
|
|
'PMA',
|
|
|
|
'dbadmin',
|
|
|
|
'pma',
|
|
|
|
'db',
|
|
|
|
'admin',
|
|
|
|
'mysql',
|
|
|
|
'database',
|
|
|
|
'sqlmanager',
|
|
|
|
'mysqlmanager',
|
|
|
|
'php-myadmin',
|
|
|
|
'phpmy-admin',
|
|
|
|
'mysqladmin',
|
|
|
|
'mysql-admin',
|
|
|
|
'phpMyAdmin2',
|
|
|
|
'phpMyAdmin3',
|
|
|
|
'phpMyAdmin4',
|
|
|
|
'phpMyAdmin-3',
|
|
|
|
'php-my-admin',
|
|
|
|
'PMA2011',
|
|
|
|
'PMA2012',
|
|
|
|
'PMA2013',
|
|
|
|
'PMA2014',
|
|
|
|
'PMA2015',
|
|
|
|
'PMA2016',
|
|
|
|
'PMA2017',
|
|
|
|
'PMA2018',
|
|
|
|
'pma2011',
|
|
|
|
'pma2012',
|
|
|
|
'pma2013',
|
|
|
|
'pma2014',
|
|
|
|
'pma2015',
|
|
|
|
'pma2016',
|
|
|
|
'pma2017',
|
|
|
|
'pma2018',
|
|
|
|
'phpmyadmin2011',
|
|
|
|
'phpmyadmin2012',
|
|
|
|
'phpmyadmin2013',
|
|
|
|
'phpmyadmin2014',
|
|
|
|
'phpmyadmin2015',
|
|
|
|
'phpmyadmin2016',
|
|
|
|
'phpmyadmin2017',
|
|
|
|
'phpmyadmin2018',
|
|
|
|
'phpmanager'];
|
|
|
|
|
2018-06-13 22:51:27 +00:00
|
|
|
const httpStart = RegExp('(http|ftp|https):\\/\\/');
|
|
|
|
|
2017-09-11 10:13:57 +00:00
|
|
|
function getUrl (req, res) {
|
2018-06-13 23:37:47 +00:00
|
|
|
let final;
|
|
|
|
const firstUrl = req.params.encoded_id;
|
|
|
|
// let theUrl;
|
|
|
|
logger.debug('Want', firstUrl);
|
|
|
|
const theUrl = complexUrls.get(firstUrl) || firstUrl;
|
|
|
|
|
2017-10-01 12:54:26 +00:00
|
|
|
if (theUrl === undefined || bouncer.indexOf(theUrl) !== -1 || theUrl === '') {
|
2017-10-01 12:37:31 +00:00
|
|
|
logger.warn(`You're not getting in ${theUrl}`);
|
2017-10-01 12:59:43 +00:00
|
|
|
res.status(400).send('');
|
2018-06-13 21:14:28 +00:00
|
|
|
|
2017-10-01 12:37:31 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-06-14 10:33:17 +00:00
|
|
|
if (theUrl !== firstUrl)
|
|
|
|
logger.info(`>>> Using ${theUrl} instead of ${firstUrl}`);
|
|
|
|
|
2018-06-13 23:18:54 +00:00
|
|
|
const options = urlparser.parse(theUrl);
|
2017-09-11 10:50:04 +00:00
|
|
|
options.followAllRedirects = true;
|
2017-09-11 10:43:04 +00:00
|
|
|
options.headers = {
|
|
|
|
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
|
|
|
|
};
|
2017-09-11 10:13:57 +00:00
|
|
|
|
2017-09-11 11:19:14 +00:00
|
|
|
// console.log('Options', options);
|
2018-06-13 21:57:24 +00:00
|
|
|
logger.info(`>> getting ${theUrl}`);
|
2017-09-11 10:13:57 +00:00
|
|
|
function urlQuery (callback) {
|
|
|
|
try {
|
2017-09-11 10:52:17 +00:00
|
|
|
let count = 0;
|
2018-06-13 23:37:47 +00:00
|
|
|
|
|
|
|
final = options.href;
|
|
|
|
if (options.protocol === 'https:')
|
|
|
|
https.request(options, responseHandler).end();
|
|
|
|
else
|
|
|
|
http.request(options, responseHandler).end();
|
2017-09-11 11:19:14 +00:00
|
|
|
|
|
|
|
function responseHandler(response) {
|
2017-09-11 10:47:34 +00:00
|
|
|
response.setEncoding('utf8');
|
2017-09-11 11:19:14 +00:00
|
|
|
if (response.statusCode === 302 || response.statusCode === 301) {
|
2017-09-11 10:52:17 +00:00
|
|
|
body = [];
|
2017-09-11 11:19:14 +00:00
|
|
|
logger.debug('>> follow', response.headers.location, count);
|
2018-06-13 22:51:27 +00:00
|
|
|
let rUrl;
|
2018-01-23 17:00:29 +00:00
|
|
|
|
2018-06-13 22:41:06 +00:00
|
|
|
if (!httpStart.test(response.headers.location)) {
|
|
|
|
//
|
|
|
|
logger.warn('response.headers.location is not a valid url...');
|
2018-06-13 22:51:27 +00:00
|
|
|
logger.info(`Trying to fix for ${theUrl}`);
|
2018-06-13 22:41:06 +00:00
|
|
|
logger.warn(response.headers.location);
|
|
|
|
logger.debug(response.headers);
|
2018-06-13 22:51:27 +00:00
|
|
|
|
2018-06-13 23:18:54 +00:00
|
|
|
const tempUrl = new URL(theUrl);
|
2018-06-14 07:25:39 +00:00
|
|
|
// logger.debug('theUrl:', theUrl);
|
|
|
|
// logger.debug('tempurl:', tempUrl);
|
2018-06-13 23:18:54 +00:00
|
|
|
|
|
|
|
rUrl = new URL(response.headers.location, tempUrl.origin);
|
2018-06-14 07:25:39 +00:00
|
|
|
logger.debug(rUrl.href);
|
2018-06-13 22:41:06 +00:00
|
|
|
}
|
2018-06-13 22:51:27 +00:00
|
|
|
else
|
2018-06-13 23:18:54 +00:00
|
|
|
rUrl = urlparser.parse(response.headers.location);
|
2018-06-13 22:51:27 +00:00
|
|
|
|
|
|
|
rUrl.followAllRedirects = true;
|
|
|
|
rUrl.headers = {
|
|
|
|
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
|
|
|
|
};
|
|
|
|
|
|
|
|
count++;
|
2018-06-13 23:37:47 +00:00
|
|
|
final = rUrl.href;
|
2018-06-13 22:51:27 +00:00
|
|
|
if (rUrl.protocol === 'https:')
|
|
|
|
https.request(rUrl, responseHandler).end();
|
|
|
|
else
|
|
|
|
http.request(rUrl, responseHandler).end();
|
2017-09-11 10:52:17 +00:00
|
|
|
}
|
|
|
|
|
2017-09-11 10:13:57 +00:00
|
|
|
let data = '';
|
|
|
|
response.on('data', chunk => {
|
|
|
|
data += chunk;
|
|
|
|
});
|
|
|
|
response.on('end', () => {
|
2018-06-13 21:14:28 +00:00
|
|
|
if (response.statusCode !== 302 && response.statusCode !== 301)
|
2017-09-11 11:19:14 +00:00
|
|
|
callback(data);
|
2017-09-11 10:13:57 +00:00
|
|
|
});
|
|
|
|
response.on('error', e => {
|
|
|
|
logger.error(e);
|
|
|
|
});
|
2017-09-11 11:19:14 +00:00
|
|
|
}
|
2017-09-11 10:13:57 +00:00
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
logger.error(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-11 10:43:04 +00:00
|
|
|
urlQuery(a => {
|
2017-09-11 10:13:57 +00:00
|
|
|
// logger.info(a);
|
2018-06-13 22:16:48 +00:00
|
|
|
logger.info(`Got result for ${theUrl}`);
|
2018-06-13 23:37:47 +00:00
|
|
|
logger.info(`Actually used: ${final}`);
|
|
|
|
|
|
|
|
if (theUrl !== final)
|
|
|
|
complexUrls.set(theUrl, final);
|
|
|
|
|
2017-09-11 10:13:57 +00:00
|
|
|
// res.setHeader('Content-Type', 'application/json');
|
2017-09-11 11:19:14 +00:00
|
|
|
res.send(a);
|
2017-09-11 10:13:57 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-06-13 23:38:37 +00:00
|
|
|
app.get('/:encoded_id', cache('15 minutes'), getUrl);
|
2017-09-11 10:13:57 +00:00
|
|
|
|
2018-06-13 22:31:48 +00:00
|
|
|
process.on('uncaughtException', function (err) {
|
|
|
|
console.error(err);
|
|
|
|
});
|
|
|
|
|
2017-10-01 09:51:10 +00:00
|
|
|
const server = app.listen(port, () => {
|
|
|
|
logger.info(`Server listening on port ${port}`);
|
2017-09-11 10:13:57 +00:00
|
|
|
});
|