Skip to content
Permalink
Browse files

Lint for routes.js

  • Loading branch information...
wpjunior committed Sep 30, 2016
1 parent 682d944 commit 4920c1e6e37d84afc75f35ce9bfbc132a2756f9e
Showing with 227 additions and 223 deletions.
  1. +1 −1 .eslintrc
  2. +15 −0 lib/http/SchemaResponse.js
  3. +97 −107 lib/http/routes.js
  4. +52 −53 lib/support/config.js
  5. +62 −62 test/integration/http/routes.test.js
@@ -1,3 +1,3 @@
extends: airbnb
rules:
arrow-body-style: ["error", "as-needed"]
no-param-reassign: [error, { props: false }]
@@ -0,0 +1,15 @@
class SchemaResponse {
constructor(req, res, schemaName) {
this.req = req;
this.res = res;
this.schemaName = schemaName;
}

json(data) {
const absUrl = `${this.req.protocol}://${this.req.get('Host')}`;
this.res.set('Content-Type', `application/json; charset=utf-8; profile=${absUrl}/_schemas/${this.schemaName}`);
this.res.end(JSON.stringify(data));
}
}

module.exports = SchemaResponse;
@@ -10,6 +10,7 @@ const log = require('../support/log');
const config = require('../support/config');
const Storage = require('../domain/storage/redis');
const Sandbox = require('../domain/sandbox').Sandbox;
const SchemaResponse = require('./SchemaResponse');

const defaultSandbox = new Sandbox();
const defaultStorage = new Storage();
@@ -19,134 +20,123 @@ routes.use(morgan('tiny'));
routes.disable('x-powered-by');

routes.get('/', (req, res) => {
let name = 'Backstage functions';
let commit = config.commit;
jsonSchemaResponse(req, res, 'root', {name, commit});
new SchemaResponse(req, res, 'root')
.json({
name: 'Backstage functions',
commit: config.commit,
});
});

routes.get('/functions', (req, res) => {
let warning = 'List is not implemented yet man!';
let items = [];
jsonSchemaResponse(req, res, 'functions/list', {warning, items});
new SchemaResponse(req, res, 'functions/list')
.json({
items: [],
warning: 'List is not implemented yet man!',
});
});

routes.put('/functions/:namespace/:id', bodyParser.json(), (req, res) => {
let validationResult = new Validator().validate(req.body, schemas['functions/item']);

if (!validationResult.valid) {
let error = 'Invalid instance';
let details = validationResult.errors.map((e) => e.toString());

res.status(400).json({error, details});
return;
}

let namespace = req.params.namespace;
let id = req.params.id;
let code = req.body.code;
let hash;

let invalid = defaultSandbox.testSyntaxError(namespace, id, code);
if (invalid) {
log.error('Failed to post code, code id:', id, 'error: ', invalid.error);
res.status(400).json(invalid);
return;
}

hash = codeHash(code);
let data = {id, code, hash};
defaultStorage.putCode(namespace, id, data).then(() => {
res.set({ETag: data.hash});
jsonSchemaResponse(req, res, 'code', data);
}, (err) => {
log.error(err);
let error = err.message;
res.status(500).json({error});
});
const validationResult = new Validator().validate(req.body, schemas['functions/item']);

if (!validationResult.valid) {
const error = 'Invalid instance';
const details = validationResult.errors.map(e => e.toString());

res.status(400).json({ error, details });
return;
}

const namespace = req.params.namespace;
const id = req.params.id;
const code = req.body.code;

const invalid = defaultSandbox.testSyntaxError(namespace, id, code);
if (invalid) {
log.error('Failed to post code, code id:', id, 'error: ', invalid.error);
res.status(400).json(invalid);
return;
}

const hash = crypto.createHash('sha1').update(code).digest('hex');
const data = { id, code, hash };

defaultStorage.putCode(namespace, id, data).then(() => {
res.set({ ETag: data.hash });
new SchemaResponse(req, res, 'code').json(data);
}, (err) => {
log.error(err);
res.status(500).json({ error: err.message });
});
});

routes.get('/functions/:namespace/:id', (req, res) => {
defaultStorage.getCode(req.params.namespace, req.params.id).then((code) => {
if (!code) {
let error = 'Code not found';
res.status(404).json({error});
return;
}

res.set({ETag: code.hash});
jsonSchemaResponse(req, res, 'code', code);
}, (err) => {
log.error(err);
let error = err.message;
res.status(500).json({error});
});
defaultStorage.getCode(req.params.namespace, req.params.id).then((code) => {
if (!code) {
const error = 'Code not found';
res.status(404).json({ error });
return;
}

res.set({ ETag: code.hash });
new SchemaResponse(req, res, 'code').json(code);
}, (err) => {
log.error(err);
res.status(500).json({ error: err.message });
});
});

routes.delete('/functions/:namespace/:id', (req, res) => {
defaultStorage.deleteCode(req.params.namespace, req.params.id).then(() => {
res.status(204).end();
}, (err) => {
log.error('Failed to delete code id', req.params.id);
log.error(err);
let error = err.message;
res.status(500).json({error});
});
defaultStorage.deleteCode(req.params.namespace, req.params.id).then(() => {
res.status(204).end();
}, (err) => {
log.error('Failed to delete code id', req.params.id);
log.error(err);
res.status(500).json({ error: err.message });
});
});

routes.get('/healthcheck', (req, res) => {
defaultStorage.ping().then(() => {
res.send('WORKING');
}, (err) => {
log.errror(err);
res.status(500).send('ERR');
});
defaultStorage.ping().then(() => {
res.send('WORKING');
}, (err) => {
log.errror(err);
res.status(500).send('ERR');
});
});

routes.get('/_schemas/*', (req, res) => {
let name = req.params[0];
if (schemas[name]) {
res.json(schemas[name]);
} else {
res.status(404).json({error: 'Schema not found'});
}
const name = req.params[0];
if (schemas[name]) {
res.json(schemas[name]);
} else {
res.status(404).json({ error: 'Schema not found' });
}
});

routes.put('/functions/:namespace/:id/run', bodyParser.json(), (req, res) => {
let namespace = req.params.namespace;
let id = req.params.id;

defaultStorage
.getCodeByCache(namespace, id, {
preCache: (code) => {
code.script = defaultSandbox.compileCode(namespace, id, code);
return code;
}
})
.then((code) => {
if (!code) {
throw new Error(`Code '${namespace}/${id}' not is found`);
}
return defaultSandbox.runScript(namespace, id, code.script, req.body.args);

})
.then((result) => {
res.json({result});
}, (err) => {
log.error('Failed to get code from cache');
log.error(err);
let error = err.message;
res.status(500).json({error});
});
const namespace = req.params.namespace;
const id = req.params.id;

defaultStorage
.getCodeByCache(namespace, id, {
preCache: (code) => {
code.script = defaultSandbox.compileCode(namespace, id, code);
return code;
},
})
.then((code) => {
if (!code) {
throw new Error(`Code '${namespace}/${id}' not is found`);
}
return defaultSandbox.runScript(namespace, id, code.script, req.body.args);
})
.then((result) => {
res.json({ result });
}, (err) => {
log.error('Failed to get code from cache');
log.error(err);
res.status(500).json({ error: err.message });
});
});

function jsonSchemaResponse(req, res, schemaName, data) {
let host = req.protocol + '://' + req.get('Host');
res.set('Content-Type', `application/json; charset=utf-8; profile=${host}/_schemas/${schemaName}`);
res.end(JSON.stringify(data));
}

function codeHash(code) {
return crypto.createHash('sha1').update(code).digest('hex');
}

module.exports = routes;
@@ -1,64 +1,63 @@
const fs = require('fs');
const numCPUs = require('os').cpus().length;
const commit = fs
.readFileSync('.git/refs/heads/master')
.toString()
.trim();


module.exports = {
commit,
port: getInt('PORT', 8100),
numCPUs: getInt('NUM_CPUS', numCPUs),
syncTimeout: getInt('CODE_SYNC_TIMEOUT', 100),
asyncTimeout: getInt('CODE_ASYNC_TIMEOUT', 5000),
redis: parseRedisOptions(),
};


function parseRedisOptions() {
let endpoint = getPossibleString(
['REDIS_ENDPOINT', 'DBAAS_SENTINEL_ENDPOINT'],
'sentinel://:@127.0.0.1:16380,127.0.0.1:16381,127.0.0.1:16382/service_name:redis-cluster'
);
let options = {};

if (endpoint.startsWith('sentinel')) {
let match = endpoint.match(/^sentinel:\/\/(.*)@(.*)\/(.*)/);
let auth = match[1].split(':');
let hosts = match[2].split(',');
let path = match[3];

options.sentinels = hosts
.map((h) => {
let host = h.split(':');
return {host: host[0], port: host[1]};
});
options.password = auth[1];
options.sentinelName = path.split(':')[1];
} else {
options.url = endpoint;
}

options.keyPrefix = process.env['REDIS_KEY_PREFIX'] || 'local';
options.heartBeatSeconds = getInt('REDIS_HEARTBEAT_SECS', 60);

return options;
}
const commit = fs
.readFileSync('.git/refs/heads/master')
.toString()
.trim();

function getInt(name, defaultValue) {
if (process.env[name]) {
return parseInt(process.env[name]);
}
if (process.env[name]) {
return parseInt(process.env[name], 10);
}

return defaultValue;
return defaultValue;
}

function getPossibleString(possibleKeys, defaultValue) {
for (let key of possibleKeys) {
if (process.env[key]) {
return process.env[key];
}
for (const key of possibleKeys) {
if (process.env[key]) {
return process.env[key];
}
return defaultValue;
}
return defaultValue;
}

function parseRedisOptions() {
const endpoint = getPossibleString(
['REDIS_ENDPOINT', 'DBAAS_SENTINEL_ENDPOINT'],
'sentinel://:@127.0.0.1:16380,127.0.0.1:16381,127.0.0.1:16382/service_name:redis-cluster'
);
const options = {};

if (endpoint.startsWith('sentinel')) {
const match = endpoint.match(/^sentinel:\/\/(.*)@(.*)\/(.*)/);
const auth = match[1].split(':');
const hosts = match[2].split(',');
const path = match[3];

options.sentinels = hosts
.map((h) => {
const host = h.split(':');
return { host: host[0], port: host[1] };
});
options.password = auth[1];
options.sentinelName = path.split(':')[1];
} else {
options.url = endpoint;
}

options.keyPrefix = process.env.REDIS_KEY_PREFIX || 'local';
options.heartBeatSeconds = getInt('REDIS_HEARTBEAT_SECS', 60);

return options;
}

module.exports = {
commit,
port: getInt('PORT', 8100),
numCPUs: getInt('NUM_CPUS', numCPUs),
syncTimeout: getInt('CODE_SYNC_TIMEOUT', 100),
asyncTimeout: getInt('CODE_ASYNC_TIMEOUT', 5000),
redis: parseRedisOptions(),
};

0 comments on commit 4920c1e

Please sign in to comment.
You can’t perform that action at this time.