A suite to track Project Diva score statistics and ratings / D4DJ event data.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
projectdivar/server/node_modules/ngrok/index.js

104 lines
2.9 KiB

const request = require('request-promise-native');
const uuid = require('uuid');
const {getProcess, killProcess, setAuthtoken} = require('./process');
let processUrl;
let internalApi;
let tunnels = {};
async function connect (opts) {
opts = defaults(opts);
validate(opts);
if (opts.authtoken) {
await setAuthtoken(opts);
}
processUrl = await getProcess(opts);
internalApi = request.defaults({baseUrl: processUrl});
return connectRetry(opts);
}
function defaults (opts) {
opts = opts || {proto: 'http', addr: 80}
if (typeof opts === 'function') opts = {proto: 'http', addr: 80};
if (typeof opts !== 'object') opts = {proto: 'http', addr: opts};
if (!opts.proto) opts.proto = 'http';
if (!opts.addr) opts.addr = opts.port || opts.host || 80;
if (opts.httpauth) opts.auth = opts.httpauth;
return opts
}
function validate (opts) {
if (opts.web_addr === false || opts.web_addr === 'false') {
throw new Error('web_addr:false is not supported, module depends on internal ngrok api')
}
}
async function connectRetry (opts, retryCount = 0) {
opts.name = String(opts.name || uuid.v4());
try {
const response = await internalApi.post({url: 'api/tunnels', json: opts});
const publicUrl = response.public_url;
if (!publicUrl) {
throw new Error('failed to start tunnel');
}
tunnels[publicUrl] = response.uri;
if (opts.proto === 'http' && opts.bind_tls !== false) {
tunnels[publicUrl.replace('https', 'http')] = response.uri + ' (http)';
}
return publicUrl;
} catch (err) {
if (!isRetriable(err) || retryCount >= 100) {
throw err.error || err.response;
}
await new Promise((resolve) => setTimeout(resolve, 200));
return connectRetry(opts, ++retryCount);
}
}
function isRetriable (err) {
if (!err.response) return false;
const body = err.response.body;
const notReady500 = err.statusCode === 500 && /panic/.test(body)
const notReady502 = err.statusCode === 502 && body.details && body.details.err === 'tunnel session not ready yet';
const notReady503 = err.statusCode === 503 && body.details && body.details.err === 'a successful ngrok tunnel session has not yet been established';
return notReady500 || notReady502 || notReady503;
}
async function disconnect (publicUrl) {
if (!internalApi) return;
if (!publicUrl) {
const disconnectAll = Object.keys(tunnels).map(disconnect);
return Promise.all(disconnectAll);
}
const tunnelUrl = tunnels[publicUrl];
if (!tunnelUrl) {
throw new Error(`there is no tunnel with url: ${publicUrl}`)
}
await internalApi.del(tunnelUrl)
delete tunnels[publicUrl];
}
async function kill () {
if (!internalApi) return;
await killProcess();
internalApi = null;
tunnels = {}
}
function getUrl() {
return processUrl;
}
function getApi() {
return internalApi;
}
module.exports = {
connect,
disconnect,
authtoken: setAuthtoken,
kill,
getUrl,
getApi
};