commit
2120089421
@ -0,0 +1,123 @@ |
||||
const http = require("http"); |
||||
const fs = require("fs"); |
||||
const path = require("path"); |
||||
const express = require("express"); // could be good to replace with code, no dep
|
||||
|
||||
const port = process.env.PORT || 7788; |
||||
const configFilePath = path.resolve(__dirname, "config.json") |
||||
const usageFilePath = path.resolve(__dirname, "usage.json") |
||||
process.title = 'onhygi'
|
||||
|
||||
// didn't work on its own with ^C nor killall
|
||||
process.on('beforeExit', _ => { console.log('trying to save before exit') }); |
||||
// process.on('exit', _ => { console.log('trying to save on exit') });
|
||||
|
||||
// catching signals and do something before exit
|
||||
['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT', |
||||
'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGTERM' |
||||
].forEach(function (sig) { |
||||
process.on(sig, function () { |
||||
terminator(sig); |
||||
console.log('signal: ' + sig); |
||||
}); |
||||
}); |
||||
|
||||
function terminator(sig) { |
||||
if (typeof sig === "string") { |
||||
console.log('Received %s - terminating server app ...', sig); |
||||
console.log('trying to save on exit') |
||||
fs.writeFileSync(usageFilePath, JSON.stringify( usage )) |
||||
process.exit(1); |
||||
} |
||||
console.log('Node server stopped.'); |
||||
} |
||||
// from https://stackoverflow.com/a/40574758/1442164
|
||||
|
||||
var usage = {} |
||||
if (fs.existsSync( usageFilePath ) ){ |
||||
console.log('found usage file') |
||||
usage = JSON.parse( fs.readFileSync(usageFilePath).toString() ) |
||||
} |
||||
console.log('past usage', usage) |
||||
|
||||
// does not apply in a P2P fashion, must rely on local configuration here config.json
|
||||
let quota = [ |
||||
{id:"ownhome", pattern:/.*fabien\.benetou\.fr.*/, perHour:10, perDay:200}, |
||||
{id:"twitter",pattern:/.*twitter\.com.*/,perHour:1,perDay:12}, |
||||
{id:"proton",pattern:/.*proton\.me.*/,perHour:6,perDay:12}, |
||||
{id:"yt",pattern:/.*youtube\.com.*/,perHour:1,perDay:12}, |
||||
{id:"linkedin",pattern:/.*linkedin\.com.*/,perHour:1,perDay:12}, |
||||
{id:"reddit",pattern:/.*reddit\.com.*/,perHour:1,perDay:12}, |
||||
{id:"element",pattern:/.*element\.io.*/,perHour:1,perDay:12}, |
||||
{id:"discord",pattern:/.*discord\.com.*/,perHour:1,perDay:12}, |
||||
] |
||||
// could also check on time, e.g not before 7am nor after 10pm as done via tridactyl now
|
||||
|
||||
if (fs.existsSync( configFilePath ) ){ |
||||
const configurationFromFile = JSON.parse( fs.readFileSync( configFilePath ).toString() ) |
||||
console.log('found quota file') |
||||
quota = configurationFromFile |
||||
} |
||||
console.log('quota', quota) |
||||
quota.map( rule => { if (typeof usage[rule.id] == 'undefined') usage[rule.id] = [] } ) |
||||
|
||||
// Setup and configure Express http server.
|
||||
const app = express(); |
||||
|
||||
// CORS
|
||||
app.use(function(req, res, next) { |
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); |
||||
next(); |
||||
}); |
||||
|
||||
app.get('/', (req, res) => { |
||||
res.json( quota ) |
||||
}) |
||||
|
||||
app.get('/check', (req, res) => { |
||||
console.log('starting check') |
||||
if (!req.query.url) { |
||||
res.sendStatus(400); |
||||
console.log('no url found') |
||||
return; |
||||
} |
||||
let matched = false |
||||
quota.map( rule => { |
||||
if ( req.query.url.match( rule.pattern ) ){ |
||||
matched = true |
||||
console.log('match on', rule.id) |
||||
let now = Date.now()/1000
|
||||
usage[rule.id].push( now ) |
||||
if ( usage[rule.id].filter( t => t>now-60*60).length > rule.perHour ){ |
||||
res.json( { passed: false, msg: 'over quota per hour' } ) |
||||
return |
||||
} |
||||
if ( usage[rule.id].filter( t => t>now-60*60*24).length > rule.perDay ){ |
||||
res.json( { passed: false, msg: 'over quota per day' } ) |
||||
return |
||||
} |
||||
res.json( { passed: true, msg: 'within quota' } ) |
||||
return // returns from map, not get
|
||||
} |
||||
}) |
||||
if (!matched) { |
||||
res.json( { passed: true, msg: 'no quota' } ) |
||||
console.log('no match') |
||||
} |
||||
// otherwise assume response already sent
|
||||
}) |
||||
|
||||
/* |
||||
const privateKey = fs.readFileSync("naf-key.pem", "utf8"); |
||||
const certificate = fs.readFileSync("naf.pem", "utf8"); |
||||
const credentials = { key: privateKey, cert: certificate }; |
||||
const webServer = https.createServer(credentials, app); |
||||
*/ |
||||
|
||||
// Start Express http server
|
||||
const webServer = http.createServer(app); |
||||
// Listen on port
|
||||
webServer.listen(port, () => { |
||||
console.log("listening on http://localhost:" + port); |
||||
}); |
Loading…
Reference in new issue