stone/server.js
Martin Donnelly 891dc7ecb6 working..
2020-06-01 08:52:44 +01:00

271 lines
6.5 KiB
JavaScript

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
// const config = require('./config');
const log4js = require('log4js');
const logger = log4js.getLogger();
const urlparser = require('url');
const URL = require('url').URL;
const http = require('http');
const https = require('https');
const apicache = require('apicache');
const request = require('request');
const ipfilter = require('express-ipfilter').IpFilter;
const IpDeniedError = require('express-ipfilter').IpDeniedError;
const port = process.env.PORT || 8080;
logger.level = 'debug';
// app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ 'extended': true }));
apicache.options({ 'debug': true });
const cache = apicache.middleware;
// app.use(cache('15 minutes'));
const ips = ['212.71.255.44', '82.35.75.161', '54.146.189.113', '52.90.194.191', '52.71.167.171'];
ips.push('82.46.161.156'); // flat
// 54.146.189.113, 52.90.194.191, 52.71.167.171 is for ifttt
const complexUrls = new Map();
app.use(ipfilter(ips, { 'mode': 'allow' }));
app.use((err, req, res, _next) => {
const thisErr = Object.assign({}, err);
thisErr.originalUrl = req.originalUrl;
console.error('Error handler', thisErr);
if(thisErr instanceof IpDeniedError)
res.status(401);
else
res.status(thisErr.status || 500);
res.status(403).end();
});
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'];
const httpStart = RegExp('(http|ftp|https):\\/\\/');
function getUrl (req, res) {
let final;
const firstUrl = req.params.encoded_id;
// let theUrl;
logger.debug('Want', firstUrl);
const theUrl = complexUrls.get(firstUrl) || firstUrl;
if (theUrl === undefined || bouncer.indexOf(theUrl) !== -1 || theUrl === '') {
logger.warn(`You're not getting in ${theUrl}`);
res.status(400).send('');
return;
}
if (theUrl !== firstUrl)
logger.info(`>>> Using ${theUrl} instead of ${firstUrl}`);
const options = urlparser.parse(theUrl);
options.followAllRedirects = true;
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'
};
// console.log('Options', options);
logger.info(`>> getting ${theUrl}`);
function urlQuery (callback) {
try {
let count = 0;
final = options.href;
if (options.protocol === 'https:')
https.request(options, responseHandler).end();
else
http.request(options, responseHandler).end();
function responseHandler(response) {
response.setEncoding('utf8');
if (response.statusCode === 302 || response.statusCode === 301) {
body = [];
logger.debug('>> follow', response.headers.location, count);
let rUrl;
if (!httpStart.test(response.headers.location)) {
//
logger.warn('response.headers.location is not a valid url...');
logger.info(`Trying to fix for ${theUrl}`);
logger.warn(response.headers.location);
logger.debug(response.headers);
const tempUrl = new URL(theUrl);
// logger.debug('theUrl:', theUrl);
// logger.debug('tempurl:', tempUrl);
rUrl = new URL(response.headers.location, tempUrl.origin);
logger.debug(rUrl.href);
}
else
rUrl = urlparser.parse(response.headers.location);
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++;
final = rUrl.href;
if (rUrl.protocol === 'https:')
https.request(rUrl, responseHandler).end();
else
http.request(rUrl, responseHandler).end();
}
let data = '';
response.on('data', chunk => {
data += chunk;
});
response.on('end', () => {
if (response.statusCode !== 302 && response.statusCode !== 301)
callback(data);
});
response.on('error', e => {
logger.error(e);
});
}
}
catch (e) {
logger.error(e);
}
}
urlQuery(a => {
// logger.info(a);
logger.info(`Got result for ${theUrl}`);
logger.info(`Actually used: ${final}`);
if (theUrl !== final)
complexUrls.set(theUrl, final);
// res.setHeader('Content-Type', 'application/json');
res.send(a);
});
}
function getUrlV2(req, res) {
let final;
const firstUrl = req.params.encoded_id;
// let theUrl;
logger.debug('Want', firstUrl);
const theUrl = complexUrls.get(firstUrl) || firstUrl;
if (theUrl === undefined || bouncer.indexOf(theUrl) !== -1 || theUrl === '') {
logger.warn(`You're not getting in ${theUrl}`);
res.status(400).send('');
return;
}
if (theUrl !== firstUrl)
logger.info(`>>> Using ${theUrl} instead of ${firstUrl}`);
const options = urlparser.parse(theUrl);
options.followAllRedirects = true;
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'
};
// console.log('Options', options);
logger.info(`V2 >> getting ${theUrl}`);
request({
'url' : theUrl,
'proxy' : 'http://us-wa.proxymesh.com:31280',
'tunnel' : true
}, (err, _res, body) => {
console.log(err);
console.log(body);
if (!err)
res.send(body);
else
res.send(err);
});
}
app.get('/:encoded_id', cache('15 minutes'), getUrlV2);
process.on('uncaughtException', function (err) {
console.error(err);
});
const server = app.listen(port, () => {
logger.info(`Server listening on port ${port}`);
});