enhancer-data-bridge
Version:
A bridge between Enhancer Clould and user business datasource
186 lines (170 loc) • 6.39 kB
JavaScript
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
var express = require( 'express' );
var router = express.Router();
var os = require('os');
var request = require('request');
var axios = require('axios');
var requireNocache = require('require-nocache')(module);
var fs = require('fs-extra');
var path = require('path');
var mocker = require('../mock');
var DatabaseService = require('../database-service');
var config = require('../config');
var customInterfacePathBase = '../repository/project/custom-interface/';
var customModuleBase = path.resolve(__dirname, '../repository/project/custom-module');
if (os.platform() === 'win32') {
customModuleBase = customModuleBase.replace(/\\/g, '/') + '/';
} else {
customModuleBase = customModuleBase + '/';
}
var requireNocacheDefine = "var requireNocache = require('require-nocache')(module);";
var interfaceCache = {};
function fetchCustomInterface(host, project_id, interface_name, method, _u_t_k_, callback) {
var url = host + '/proj/' + project_id + '/httpinterface/name/' + interface_name + '/' + method;
var result = interfaceCache[url];
if (result) {
console.log('Cache hit for ', interface_name, method);
callback(null, result);
return;
}
axios.get(url, {
headers: {
'Cookie': 'token=' + _u_t_k_
}
}).then(function(res) {
if (!res.data || !res.data.success || !res.data.result) {
var err = new Error('Failed to get interface \'' + interface_name + '\'. responseText: ' + res.data);
callback(err);
return
}
var data = res.data;
var interface = requireNocacheDefine
+ data.result.interface.replace(/@\w+(\.\w+)*@/g, function(s) {
return 'Enhancer.getVariable("' + s.split(/@/g)[1].toUpperCase() + '")';
})
.replace(/require\(\s*(\'|\")@custom\//g, function(s, $1) {
return 'requireNocache(' + $1 + customModuleBase;
});
var file = path.resolve(__dirname, customInterfacePathBase + interface_name);
fs.ensureFileSync(file);
fs.writeFileSync(file, interface);
var f;
try {
f = requireNocache(customInterfacePathBase + interface_name);
} catch (e) {
e.message = '[Interface Calling Error] Error occured when calling interface: '
+ e.message.replace(customModuleBase, '@custom');
callback(e);
return
}
if (typeof f !== 'function') {
var err = new Error('[Interface Error] No function module is exported.');
callback(err);
return
}
var result = data.result;
result.interface = f;
interfaceCache[url] = result;
callback(null, result);
setTimeout(function() {
delete interfaceCache[url];
}, 5000);
})
.catch(function(err) {
callback(err);
});
}
router.all('/custom-interface/p/:project_id/call/:interface_name', function(req, res, next) {
if (req.method === 'OPTIONS') {
res.send('OK');
return
}
var dbConfiguration;
try {
dbConfiguration = JSON.parse(req.query._d_b_ || '{"default":"","connections":{}}');
} catch (e) {
console.warn('Invalid database settings for calling custom interface which is caused by bad url string.');
console.warn('The database service of Enhancer is not available in this test environment.');
}
// Mock getDatabaseService
req.getDatabaseService = function() {
return new DatabaseService(dbConfiguration);
};
var serverVars = req.query._s_v_ || '{}';
try {
serverVars = JSON.parse(decodeURIComponent(serverVars));
} catch(e) {
serverVars = {};
}
// Append Session Variables
var vbs = req.session._variables;
if (vbs) {
for (var i in vbs) {
serverVars[i.toUpperCase()] = vbs[i];
}
}
// Mock getServerVariables
req.getServerVariables = function() {
return serverVars;
};
// Mock getUser
req.getUser = function() {
return {
getId: function() {
return serverVars['USER_ID'];
},
getName: function() {
return serverVars['USER_NAME'];
},
getRoles: function() {
return serverVars['ROLES'];
}
}
};
// Mock enhancer api
global.Enhancer = mocker.mockEnhancer(dbConfiguration, serverVars, req, res);
res.setHeader('Access-Control-Allow-Origin', '*');
var that = this;
var pid = req.params.project_id;
var iname = req.params.interface_name;
var host = 'https://workbench.wuyuan.io';
if (/previewer\.enhancer\.cc/.test(req.headers.referer)) {
host = 'http://workbench.enhancer.cc';
}
var method = req.method
if (method == 'OPTIONS') {
method = req.headers['access-control-request-method'];
}
fetchCustomInterface(host, pid, iname, method, req.query._u_t_k_, function(err, result) {
if (err) {
var msg = 'Error occured when fetch custom interface. Reason:' + err.message;
console.error(err);
res.status(500).send(msg)
return;
}
var isCompleted = false;
res.on('finish', function(e) {
isCompleted = true;
});
setTimeout(function() {
if (!isCompleted) {
isCompleted = true;
res.status(500)
.end('[Timeout Error] Interface response timeout, please check if it responses correctly.');
res.jsonp = res.send = res.end = function() {
console.log('The request has been timeout and the response has been ended.');
}
}
}, config.isOfficialEnv ? 5000 : (parseInt(result.timeout) || 5000));
try {
result.interface.apply(that, [req, res, Enhancer]);
} catch(err) {
console.log(err);
isCompleted = true;
return res.status(500)
.send('[Interface Calling Error] Error occured when calling interface: '
+ err.stack);
}
});
});
module.exports = router;