Select Git revision
server.js 26.60 KiB
var express = require('express')
var app = express()
var path=require('path');
const IS_NODE = typeof module !== 'undefined' && module.exports;
//------------------- parse command line ------------------------------
var gPI;
var ROOT;
var awRoot; // path to autowrangler files (if enabled)
var PORT=3000;
// secure can be turned off on command line, but default is on
var bSecure=true;
var argv = require('minimist')(process.argv.slice(2));
if (1!=argv._.length) {
ljsLog.error('USAGE: node server.js [--port=PORT] [--pi=piName] [--secure=true] [--log=/path/to/log.txt] [--awRoot=/path/to/awFiles] /path/to/files_LEVER/');
return;
}
ROOT = argv._[0];
// git rid of trailing slashes -- these mess up concatenation in middleware below
if ('/'===ROOT[ROOT.length-1] || '\\'===ROOT[ROOT.length-1] )
ROOT=ROOT.slice(0,ROOT.length-1);
awRoot=argv.awRoot;
global.leverRoot=ROOT;
global.logFile=argv.log;
// init logger after we set the root and log file, so we get file logs
const LJS_LOG=require('./leverjs/ljsLog.js');
const ljsLog=new LJS_LOG(true);
if (undefined!==argv.port) {
PORT=argv.port;
}
if (false==argv.secure || "false"==argv.secure) {
ljsLog.log(' --> security DISABLED!')
bSecure=false;
}
else {
ljsLog.log('jwt security enabled : bSecure='+bSecure);
}
gPI=argv.pi;
if (undefined==gPI || null==gPI)
gPI='';
else
gPI=gPI.toLowerCase();
ljsLog.log('gPI set to : '+gPI);
const config=require('./config.js');
// kick off a dbupdate
function initRoot()
{
ljsLog.log('initiating dbUpdate');
const spawn = require('child_process').spawn;
var updateProc=spawn('node', ['leverjs/dbUpdate.js',ROOT]);
var bUpdate=true;
updateProc.on('close', (code) => {
ljsLog.log('update complete. calling optimize');
var optimizeProc=spawn('node', ['leverjs/dbOptimize.js',ROOT,"--quiet"]);
optimizeProc.stdout.on('data', (data) => {
ljsLog.log(`optimizeProc: ${data}`);
});
optimizeProc.on('close', (code) => {
ljsLog.log('optimize completed with code '+code);
});
});
updateProc.stdout.on('data', (data) => {
ljsLog.log(`updateProc: ${data}`);
});
}
initRoot();
//--------------- auth0 security -------------------
//
var checkJwt;
if (bSecure) {
const express = require('express');
const app = express();
const jwt = require('express-jwt');
const jwksRsa = require('jwks-rsa');
// Authentication middleware. When used, the
// access token must exist and be verified against
// the Auth0 JSON Web Key Set
checkJwt = jwt({
// Dynamically provide a signing key
// based on the kid in the header and
// the signing keys provided by the JWKS endpoint.
secret: jwksRsa.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: config.jwksUri
}),
// Validate the audience and the issuer.
aud: config.aud,
issuer: config.issuer,
algorithms: ['RS256']
});
}
else {
checkJwt=function(res,req,next){
next();
}
}
//--------------- auth0 end -------------------
function checkLWT(req,res,next)
{
const jwt = require('jsonwebtoken');
const fs=require('fs');
const path=require('path');
var token=req.headers.authorization;
if (false===bSecure) {
return next();
}
if (undefined===token) {
// no token. user needs to login via auth0 or send jwt directly
return res.status(401).send('login required');
}
if (0===token.indexOf("Bearer")) {
// then this originates via auth0
// first, make sure jwt is valid
checkJwt(req,res,function(){
// check config override
// reload config -- allows dynamic reconfig of access control
const path=require('path');
var configPath=path.join(process.cwd(),'config.js');
delete require.cache[configPath]
var config=require(configPath);
var pi;
if (undefined!=req.user) {
// next check authorization (i.e. pi matches)
pi=req.user['https://leverjs.net/pi'];
}
if (undefined===req.user || null==pi || undefined==pi) {
return res.status(401).send('invalid user');
}
pi=pi.toLowerCase();
if (pi===gPI || pi===config.defaultPI.toLowerCase()) {
next();
return;
}
// convert *'s to /'s in path
var targetPath=req.path.replace(/\*/g,'\/');;
for (var i=0;i<config.otherPI.length;i++) {
if (targetPath.indexOf(config.otherPI[i][0])>=0 &&
pi===config.otherPI[i][1].toLocaleLowerCase()) {
next();
return;
}
}
// else if we get here then the authorization failed
var userID=req.user['https://leverjs.net/email'];
res.status(403).send('leverServer: authorization denied for user='+userID
+' with pi='+pi);
ljsLog.warn('user '+userID+' not authorized: pi='+pi);
});
return;
}
// if we get here, it should be a jwt from e.g. matlab
try {
publicCert = fs.readFileSync('./digitalKeys/leverjsPublicKey.pem','utf-8'); // get public key
}
catch(err){
ljsLog.error('LWT: public key file not found '+err.message);
res.status(401).send('no key file');
return;
}
// use our public key file to verify this token
jwt.verify(token, publicCert, function(err, decoded) {
//ljsLog.log(JSON.stringify(decoded)) //
if (err) {
// token did not verify
res.status(401).send('invalid token: '+err);
return;
}
// if we got here, token was a-ok
req.user=decoded;
next();
});
} // checkLWT
function checkLocalOrLWT(req, res, next)
{
if ( req.ip === '127.0.0.1' || req.ip === '::1' )
{
next();
}
else
{
checkLWT(req,res, next);
}
} // checkLocalOrLWT
app.param('LEVER', function (req, res, next, leverFile) {
req.ROOT=ROOT;
req.awRoot=awRoot;
req.params.LEVER=decodeURI(req.params.LEVER);
req.params.LEVER=req.params.LEVER.replace(/\*/g,'\/');
req.leverFile=path.join(req.ROOT,req.params.LEVER);
next();
});
// called by split,undo,resegAll,resegNext,resegPause
function prepareCommand(req,res,command,params)
{
const process=require('./leverjs/process.js');
var leverFile=req.leverFile;
var user='NA';
if (undefined!==req.user)
user=req.user['https://leverjs.net/email'];
else {
var osUser=require('os').userInfo().username;
username='server:'+osUser;
}
var leverCommand={leverFile:leverFile, command:command, time:req.params.time,
params:params, user:user};
var editID=process.addToQ(leverCommand);
res.send(JSON.stringify(editID));
} // prepareCommand
// --------------------- routing table ----------------------------------------
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json({limit:'1gb'});
var rawParser = bodyParser.raw({type:'*/*',limit:'1gb'});
app.use(express.static('./leverjs'));
app.get('*/stats',function(req,res){
const path=require('path');
var target=path.join(ROOT,path.dirname(req.path));
const helper=require('./leverjs/serverHelper');
helper.getStats(target,res);
});
app.get('/:LEVER/editStats/:tMax',function(req,res) {
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
var tMax=req.params.tMax;
leverDB.getEditStats(tMax,function(editStats){
res.send(editStats);
});
});
app.get('/log',function(req,res) {
if (undefined===global.logFile) {
res.send('sorry, logging not enabled');
return;
}
// else
res.setHeader('Content-Language','en-us');
const path=require('path');
var logFile=path.resolve(global.logFile);
res.sendFile(logFile,{},function(err){
if (err) {
ljsLog.error('app.get log file: '+err);
}
});
});
app.get('/info',function(req,res) {
res.send(JSON.stringify({leverjs: 'server'}));
});
app.get('/API',function(req,res) {
const helper=require('./leverjs/serverHelper');
var html=helper.getAPI();
res.send(html);
});
app.get('/secure', checkLWT, function(req,res){
ljsLog.log('secure')
res.send("no, you're secure");
});
app.get('/hiFriend', function(req,res){
ljsLog.log('hifriend')
res.send('hi');
});
app.get('/:LEVER/trackList/:tMin',function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
var tMin=req.params.tMin;
leverDB.trackList(tMin,function(trackList){
res.send(trackList);
});
})
app.post('/:LEVER/clone/:destFile',checkLWT,function(req,res) {
const cl=require('./leverjs/cloneLever.js');
const path=require('path');
var leverFile=req.leverFile;
var destFile=req.params.destFile;
destFile=decodeURI(destFile);
destFile=destFile.replace(/\*/g,'\/');
destFile=path.join(req.ROOT,destFile);
cl.cloneLever(leverFile,destFile,function(){
res.send('done');
});
});
app.post('/:LEVER/updateSurface/:cellID',checkLWT, jsonParser,function(req,res) {
var command='updateSurface';
var params={cellID:req.params.cellID, surface:req.body};
prepareCommand(req,res,command,params);
});
app.get('/:LEVER/trackOptions/:cellID',function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
var cellID=req.params.cellID;
leverDB.getTrackOptions(cellID,function(trackOptions){
res.send(trackOptions);
});
})
app.get('/:LEVER/cellPhenotypes/:cellID',function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
var cellID=req.params.cellID;
leverDB.getCellPhenotypes(cellID,function(cellPhenotypes){
res.send(cellPhenotypes);
});
})
app.get('/:LEVER/vertices/:cellID',function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
var cellID=req.params.cellID;
leverDB.getVertices(cellID,function(vertices){
res.send(vertices);
leverDB.close();
});
})
app.post('/:LEVER/createCells/',checkLWT, jsonParser,function(req,res) {
var command='createCells';
var params={cells:req.body};
prepareCommand(req,res,command,params);
});
app.post('/allRenderParams/',checkLWT, jsonParser, function(req,res) {
var renderParams=req.body;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB;
leverDB.allRenderParams(ROOT,renderParams);
res.send('ok');
});
app.post('/:LEVER/killProcess/',checkLWT, function(req,res) {
const process=require('./leverjs/process.js');
process.pauseOrKillAll(true,req.leverFile);
res.send('ok');
});
app.post('/pauseProcessAll/',checkLWT, function(req,res) {
const process=require('./leverjs/process.js');
process.pauseOrKillAll(false);
res.send('ok');
});
app.post('/killProcessAll/',checkLWT, function(req,res) {
const process=require('./leverjs/process.js');
process.pauseOrKillAll(true);
res.send('ok');
});
app.get('/processQ', function(req,res) {
const process=require('./leverjs/process.js');
const path=require('path');
var rootStd=path.resolve(ROOT); // '/' not '\\'
var Q=process.getQ(function(Q) {
// remove root from each
for (var i=0;i<Q.inProcessQ.length;i++) {
var lf=path.resolve(Q.inProcessQ[i].leverFile);
if (lf.indexOf(rootStd)>=0)
Q.inProcessQ[i].leverFile=Q.inProcessQ[i].leverFile.substring(ROOT.length+1);
}
for (var i=0;i<Q.toProcessQ.length;i++) {
var lf=path.resolve(Q.toProcessQ[i].leverFile);
if (lf.indexOf(rootStd)>=0)
Q.toProcessQ[i].leverFile=Q.toProcessQ[i].leverFile.substring(ROOT.length+1);
}
res.send(JSON.stringify(Q))
});
});
app.post('/:LEVER/split/:cellID/:K/:time/:checkValue', checkLWT,function(req,res) {
var command='split';
var params={cellID:req.params.cellID, K:req.params.K, checkValue:req.params.checkValue};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/merge/:rgCellIDs/:time/:checkValue', checkLWT,function(req,res) {
var command='merge';
var params={rgCellIDs:req.params.rgCellIDs,checkValue:req.params.checkValue};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/mergeTracks/:rgTrackIDs/:time', checkLWT,function(req,res) {
var command='mergeTracks';
var params={rgTrackIDs:req.params.rgTrackIDs};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/changeTrackID/:cellID/:newTrackID/:oldTrackID/:time/', checkLWT,function(req,res) {
var command='changeTrackID';
var params={cellID:req.params.cellID, newTrackID:req.params.newTrackID, oldTrackID:req.params.oldTrackID};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/addMitosis/:child1/:child2/:time', checkLWT, function(req,res) {
var command='addMitosis';
var params={child1:req.params.child1, child2:req.params.child2};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/removeMitosis/:child_cellID', checkLWT, function(req,res) {
var command='removeMitosis';
var params={child_cellID:req.params.child_cellID};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/cellPhenotype/:cellID/:phenotype/:bPhenotype/:time', checkLWT, function(req,res) {
var command='cellPhenotype';
var params={cellID:req.params.cellID,phenotype:req.params.phenotype,bPhenotype:req.params.bPhenotype};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/changeTrackColor/:trackID/:newColor', checkLWT, function(req,res) {
var command='changeTrackColor';
// we took off the # to keep the URI valid...put it back here.
var newColor='#'+req.params.newColor;
var params={trackID:req.params.trackID, newColor:newColor};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/undo/:undoEditID/:time/:undoCommand', checkLWT,function(req,res) {
var command='undo';
var params={undoEditID:req.params.undoEditID,undoCommand:req.params.undoCommand};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/resegAll/:time', checkLWT,function(req,res) {
var command='resegAll';
var params={};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/resegNext/:time', checkLWT,function(req,res) {
var command='resegNext';
var params={};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/resegPause/:time', checkLWT,function(req,res) {
// this goes straight into the commandTable -- no processQ
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
var leverCommand={leverFile:leverFile,command:"resegPause",time:req.params.time};
leverDB.addCommandToDB(leverCommand,function(){
leverDB.close();
});
res.send('OK');
});
app.post('/:LEVER/eraseAll', checkLWT,function(req,res) {
var command='eraseAll';
var params={};
prepareCommand(req,res,command,params);
});
app.post('/experimentCommand',checkLWT,jsonParser,function(req,res) {
const expHelper=require('./leverjs/experimentHelper.js');
var leverExpCommand=req.body;
var leverFileList=req.body.leverFileList;
const path=require('path');
for (var i=0;i<leverFileList.length;i++) {
leverFileList[i]=leverFileList[i].replace(/\*/g,'\/');
leverFileList[i]=path.join(ROOT,leverFileList[i]);
}
expHelper.experimentExecCmd(leverFileList,leverExpCommand,function(code,szStatus){
if (undefined==code)
res.status(200).send("OK");
else
res.status(code).send(szStatus);
})
});
app.post('/:LEVER/removeFromExtFamily/:trackID', checkLWT, function(req,res) {
var command='removeFromExtFamily';
var params={trackID:req.params.trackID};
prepareCommand(req,res,command,params);
});
app.get('/:LEVER/addToExtFamilies/:trackID/:time', function(req,res) {
console.log('got it!')
});
app.post('/:LEVER/addToExtFamilies/:trackID/:time', checkLWT, function(req,res) {
var command='addToExtFamily';
var params={trackID:req.params.trackID};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/addAllMitoses', checkLWT, function(req,res) {
var command='addAllMitoses';
var params={};
prepareCommand(req,res,command,params);
});
app.post('/:LEVER/CONSTANTS/', checkLWT, jsonParser, function(req,res) {
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
var CONSTANTS=req.body;
leverDB.setConstants(CONSTANTS,function() {
leverDB.close();
});
res.send('ok');
});
app.get('/:LEVER/trackFeatures/:trackID', function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
var trackID=JSON.parse(req.params.trackID);
leverDB.getTrackFeatures(trackID,function(trackFeatures) {
res.send(trackFeatures);
leverDB.close();
});
})
app.get('/:LEVER/algorithms', function(req,res) {
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
leverDB.getAlgorithms(function(err,algorithms) {
res.send(algorithms);
});
});
app.get('/:LEVER/featureExtrema', function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
leverDB.getConstants(function(err,CONSTANTS) {
leverDB.getFeatureExtrema(CONSTANTS,function(rgMinMax) {
res.send(rgMinMax);
});
});
});
app.get('/:LEVER/constants', function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
leverDB.getConstants(function(err,CONSTANTS) {
// tag on autowrangler status
if (err) {
res.send(err.message);
return;
}
CONSTANTS.ui.autoWrangler=(undefined!==awRoot);
res.send(CONSTANTS);
leverDB.close();
});
});
app.get('/editStatus/:editID', function(req,res) {
const process=require('./leverjs/process.js');
var editID=JSON.parse(req.params.editID);
var status=process.getStatus(editID);
if ('idle'===status)
res.send(status); // idle
else
res.status(202).send(status); // busy
});
app.get('/algorithms', function(req,res) {
const helper=require('./leverjs/serverHelper.js');
helper.getAvailableAlgorithms(req,res)
});
app.post('/:LEVER/addAlgorithm/', checkLWT, jsonParser, function(req,res) {
const helper=require('./leverjs/serverHelper.js');
helper.setAlgorithmInDB(req,res);
});
app.post('/:LEVER/removeAlgorithm/:algName', checkLWT, function(req,res) {
const helper=require('./leverjs/serverHelper.js');
helper.removeAlgorithmFromDB(req,res,false);
});
app.post('/:LEVER/removeAllAlgorithms/', checkLWT, function(req,res) {
const helper=require('./leverjs/serverHelper.js');
helper.removeAlgorithmFromDB(req,res,true);
});
app.get('/:LEVER/cellPixels/:cellID', function(req,res) {
const helper=require('./leverjs/serverHelper.js');
helper.getCellPixels(req,res);
});
app.get('/:LEVER/cellCentroids/:time', function(req,res) {
const helper=require('./leverjs/serverHelper.js');
helper.getCellCentroids(req,res);
});
app.get('/:LEVER/cellSurface/:time', function(req,res) {
const helper=require('./leverjs/serverHelper.js');
helper.getCellCentroids(req,res,true);
});
app.get('/:LEVER/editList', function(req,res) {
const helper=require('./leverjs/serverHelper.js');
helper.getEditList(req,res);
});
app.get('/:LEVER/colorTable', function(req,res){
const helper=require('./leverjs/serverHelper.js');
helper.getColorTable(req,res);
});
app.get('/:LEVER/image/:time/p_:pack/l_:mrLevel/v_:mrChunk', function(req,res){
const helper=require('./leverjs/serverHelper.js');
helper.getImage(req,res);
});
app.get('/:LEVER/image/:time', function(req,res){
const helper=require('./leverjs/serverHelper.js');
helper.getImage(req,res);
});
app.get('/:LEVER/image/:time/:channel', function(req,res){
const helper=require('./leverjs/serverHelper.js');
helper.getImage(req,res);
});
app.get(['/:LEVER/cells/:time/c_:channelList','/:LEVER/cellsAW/:time/c_:channelList/:awid'],
function(req,res){
const helper=require('./leverjs/serverHelper.js');
helper.getCells(req,res);
});
app.get(['/:LEVER/cells/:time','/:LEVER/cellsAW/:time/:awid'],function(req,res){
const helper=require('./leverjs/serverHelper.js');
helper.getCells(req,res);
});
app.get('/:LEVER/families', function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
leverDB.readLineage(function(leverStruct) {
res.send(leverStruct);
leverDB.close();
});
});
app.get('/:LEVER/lineage', function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB(leverFile);
leverDB.readLineage(function(leverStruct) {
res.send(leverStruct);
leverDB.close();
});
});
app.get('/:LEVER/awParams', function(req,res){
var leverFile=req.leverFile;
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB();
leverDB.awParams(awRoot,leverFile,function(params) {
res.send(params);
});
});
app.get('*lever/', function(req,res){
const LeverDB=require('./leverjs/lever.js');
const path=require('path');
var targetPath=req.path;
if (undefined!=req.headers.ljsroot)
targetPath=path.join(req.headers.ljsroot,targetPath);
targetPath=targetPath.replace(/\\/g,'/');
if ('/' !== targetPath[targetPath.length-1])
targetPath=targetPath+'/';
var rgPath=targetPath.split('/');
var extPath='';
for (var n=0;n<rgPath.length-2; n++)
extPath=path.join(extPath,rgPath[n]);
require('./leverjs/lever.js');
var leverDB=new LeverDB();
leverDB.leverGetFileList(ROOT,function(leverFileList){
res.send(leverFileList);
}, extPath)
});
app.post('/loadfig/:fignum', rawParser, checkLocalOrLWT, function (req, res)
{
const helper = require('./leverjs/serverHelper.js');
// Figure number must be an integer
var fignum = parseInt(req.params.fignum);
if ( fignum === undefined || isNaN(fignum) || fignum > 20 )
{
res.status(400).send('Invalid figure number');
return;
}
helper.loadFigData(ROOT, req.body,fignum,function ()
{
res.status(200).send({response: 'Figure ' + fignum + ' loaded!'});
});
});
app.get('/showfig/:fignum', function (req, res)
{
if ( undefined !== req.params.fignum )
res.redirect('../ImageWindow.html?'+'_fig'+req.params.fignum+'.LEVER');
});
// serve the dataset :LEVER javascript / client page
app.get('/:LEVER/lever', function (req, res) {
const LeverDB=require('./leverjs/lever.js');
var leverDB=new LeverDB();
var leverFile=decodeURI(req.params.LEVER);
leverFile = path.join(ROOT,leverFile);
leverDB.leverRead(leverFile,0,ROOT,function(err,leverStruct){
if(err) {
res.status(400).send(JSON.stringify(err));
}
else {
res.send(JSON.stringify(leverStruct));
}
});
});
// serve the dataset :LEVER javascript / client page
app.get('/:LEVER(/*)?', function (req, res) {
const path=require('path');
if (undefined===req.params.LEVER) {
res.redirect('ExperimentWindow.html?');
}
else {
if (path.extname(req.params.LEVER)!='LEVER')
res.redirect('ExperimentWindow.html?'+req.params.LEVER);
else
res.redirect('ImageWindow.html?'+req.params.LEVER);
}
})
// serve the root javascript / client page
app.get('/', function (req, res) {
//res.send('Hello World!')
res.redirect('ExperimentWindow.html?');
})
// this middleware will not allow the request to go beyond it
app.use(function(req, res, next) {
// try to parse this as a subfolder with depth > 1 (/:LEVER above handles depth 1)
// NOTE express js does not do absolute paths with reverse proxy correctly
// so if we get /a/b/c we need to redirect to ../../experimentwindow
// since ./experimentwindow drops the proxy path
// build the relative path
const path=require('path');
var reqPath;
if (undefined!==req.headers.ljsroot)
reqPath=path.join(req.headers.ljsroot,req.path);
else
reqPath=req.path;
reqPath=reqPath.replace(/\\/g,'/');
var nfolders = ( req.path.match(/\//g) || []).length - 1; // counts '/' in req.path
var redirectPath='ExperimentWindow.html?'+req.path;
for (var i=0;i<nfolders;i++) {
redirectPath='../'+redirectPath;
}
res.redirect(redirectPath);
});
// need to define error handling middleware last
// this handles login failurs
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError' || err.name==='JsonWebTokenError') {
res.status(401).send('leverServer: invalid credentials');
}
});
// this starts the server
app.listen(PORT, function () {
ljsLog.log('leverjsServer: listening on port: ' + PORT + ' serving folder: '+ROOT);
})