apps: add detail to http error messages

This commit is contained in:
Girish Ramakrishnan
2019-09-01 17:44:24 -07:00
parent d2f38c1abc
commit d59c1f53b9
4 changed files with 67 additions and 86 deletions

View File

@@ -37,12 +37,32 @@ var apps = require('../apps.js'),
util = require('util'),
WebSocket = require('ws');
function toHttpError(appError) {
switch (appError.reason) {
case AppsError.NOT_FOUND:
return new HttpError(404, appError);
case AppsError.ALREADY_EXISTS:
case AppsError.PORT_RESERVED:
case AppsError.PORT_CONFLICT:
return new HttpError(409, appError);
case AppsError.BAD_FIELD:
case AppsError.BAD_CERTIFICATE:
return new HttpError(400, appError);
case AppsError.PLAN_LIMIT:
return new HttpError(402, appError);
case AppsError.EXTERNAL_ERROR:
return new HttpError(424, appError);
case AppsError.INTERNAL_ERROR:
default:
return new HttpError(500, appError);
}
}
function getApp(req, res, next) {
assert.strictEqual(typeof req.params.id, 'string');
apps.get(req.params.id, function (error, app) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(200, apps.removeInternalFields(app)));
});
@@ -52,7 +72,7 @@ function getApps(req, res, next) {
assert.strictEqual(typeof req.user, 'object');
apps.getAllByUser(req.user, function (error, allApps) {
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
allApps = allApps.map(apps.removeRestrictedFields);
@@ -63,15 +83,11 @@ function getApps(req, res, next) {
function getAppIcon(req, res, next) {
assert.strictEqual(typeof req.params.id, 'string');
if (!req.query.original) {
const userIconPath = `${paths.APP_ICONS_DIR}/${req.params.id}.user.png`;
if (safe.fs.existsSync(userIconPath)) return res.sendFile(userIconPath);
}
apps.getIconPath(req.params.id, { original: req.query.original }, function (error, iconPath) {
if (error) return next(toHttpError(error));
const appstoreIconPath = `${paths.APP_ICONS_DIR}/${req.params.id}.png`;
if (safe.fs.existsSync(appstoreIconPath)) return res.sendFile(appstoreIconPath);
return next(new HttpError(404, 'No such icon'));
res.sendFile(iconPath);
});
}
function installApp(req, res, next) {
@@ -127,15 +143,7 @@ function installApp(req, res, next) {
debug('Installing app :%j', data);
apps.install(data, req.user, auditSource.fromRequest(req), function (error, result) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, error.message));
if (error && error.reason === AppsError.ALREADY_EXISTS) return next(new HttpError(409, error.message));
if (error && error.reason === AppsError.PORT_RESERVED) return next(new HttpError(409, 'Port ' + error.message + ' is reserved.'));
if (error && error.reason === AppsError.PORT_CONFLICT) return next(new HttpError(409, 'Port ' + error.message + ' is already in use.'));
if (error && error.reason === AppsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error && error.reason === AppsError.PLAN_LIMIT) return next(new HttpError(402, error.message));
if (error && error.reason === AppsError.BAD_CERTIFICATE) return next(new HttpError(400, error.message));
if (error && error.reason === AppsError.EXTERNAL_ERROR) return next(new HttpError(424, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(202, { id: result.id, taskId: result.taskId }));
});
@@ -190,14 +198,7 @@ function configureApp(req, res, next) {
debug('Configuring app id:%s data:%j', req.params.id, data);
apps.configure(req.params.id, data, req.user, auditSource.fromRequest(req), function (error, result) {
if (error && error.reason === AppsError.ALREADY_EXISTS) return next(new HttpError(409, error.message));
if (error && error.reason === AppsError.PORT_RESERVED) return next(new HttpError(409, 'Port ' + error.message + ' is reserved.'));
if (error && error.reason === AppsError.PORT_CONFLICT) return next(new HttpError(409, 'Port ' + error.message + ' is already in use.'));
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error && error.reason === AppsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error && error.reason === AppsError.BAD_CERTIFICATE) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(202, { taskId: result.taskId }));
});
@@ -215,11 +216,7 @@ function restoreApp(req, res, next) {
if (data.backupId !== null && typeof data.backupId !== 'string') return next(new HttpError(400, 'backupId must be string or null'));
apps.restore(req.params.id, data, auditSource.fromRequest(req), function (error, result) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error && error.reason === AppsError.EXTERNAL_ERROR) return next(new HttpError(424, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(202, { taskId: result.taskId }));
});
@@ -239,16 +236,7 @@ function cloneApp(req, res, next) {
if (('portBindings' in data) && typeof data.portBindings !== 'object') return next(new HttpError(400, 'portBindings must be an object'));
apps.clone(req.params.id, data, req.user, auditSource.fromRequest(req), function (error, result) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.PORT_RESERVED) return next(new HttpError(409, 'Port ' + error.message + ' is reserved.'));
if (error && error.reason === AppsError.PORT_CONFLICT) return next(new HttpError(409, 'Port ' + error.message + ' is already in use.'));
if (error && error.reason === AppsError.ALREADY_EXISTS) return next(new HttpError(409, error.message));
if (error && error.reason === AppsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error && error.reason === AppsError.PLAN_LIMIT) return next(new HttpError(402, error.message));
if (error && error.reason === AppsError.BAD_CERTIFICATE) return next(new HttpError(400, error.message));
if (error && error.reason === AppsError.EXTERNAL_ERROR) return next(new HttpError(424, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(201, { id: result.id, taskId: result.taskId }));
});
@@ -260,10 +248,7 @@ function backupApp(req, res, next) {
debug('Backup app id:%s', req.params.id);
apps.backup(req.params.id, function (error, result) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error && error.reason === AppsError.EXTERNAL_ERROR) return next(new HttpError(424, error));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(202, { taskId: result.taskId }));
});
@@ -275,10 +260,7 @@ function uninstallApp(req, res, next) {
debug('Uninstalling app id:%s', req.params.id);
apps.uninstall(req.params.id, auditSource.fromRequest(req), function (error, result) {
if (error && error.reason === AppsError.EXTERNAL_ERROR) return next(new HttpError(424, error));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(202, { taskId: result.taskId }));
});
@@ -290,9 +272,7 @@ function startApp(req, res, next) {
debug('Start app id:%s', req.params.id);
apps.start(req.params.id, function (error) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(202, { }));
});
@@ -304,9 +284,7 @@ function stopApp(req, res, next) {
debug('Stop app id:%s', req.params.id);
apps.stop(req.params.id, function (error) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(202, { }));
});
@@ -328,10 +306,7 @@ function updateApp(req, res, next) {
debug('Update app id:%s to manifest:%j', req.params.id, data.manifest);
apps.update(req.params.id, req.body, auditSource.fromRequest(req), function (error, result) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(202, { taskId: result.taskId }));
});
@@ -357,9 +332,7 @@ function getLogStream(req, res, next) {
};
apps.getLogs(req.params.id, options, function (error, logStream) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(412, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
res.writeHead(200, {
'Content-Type': 'text/event-stream',
@@ -394,9 +367,7 @@ function getLogs(req, res, next) {
};
apps.getLogs(req.params.id, options, function (error, logStream) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(412, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
res.writeHead(200, {
'Content-Type': 'application/x-logs',
@@ -450,9 +421,7 @@ function exec(req, res, next) {
var tty = req.query.tty === 'true' ? true : false;
apps.exec(req.params.id, { cmd: cmd, rows: rows, columns: columns, tty: tty }, function (error, duplexStream) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
if (req.headers['upgrade'] !== 'tcp') return next(new HttpError(404, 'exec requires TCP upgrade'));
@@ -492,9 +461,7 @@ function execWebSocket(req, res, next) {
var tty = req.query.tty === 'true' ? true : false;
apps.exec(req.params.id, { cmd: cmd, rows: rows, columns: columns, tty: tty }, function (error, duplexStream) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error && error.reason === AppsError.BAD_STATE) return next(new HttpError(409, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
debug('Connected to terminal');
@@ -534,8 +501,7 @@ function listBackups(req, res, next) {
if (!perPage || perPage < 0) return next(new HttpError(400, 'per_page query param has to be a postive number'));
apps.listBackups(page, perPage, req.params.id, function (error, result) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, 'No such app'));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
next(new HttpSuccess(200, { backups: result }));
});
@@ -550,8 +516,7 @@ function uploadFile(req, res, next) {
if (!req.files.file) return next(new HttpError(400, 'file must be provided as multipart'));
apps.uploadFile(req.params.id, req.files.file.path, req.query.file, function (error) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
debug('uploadFile: done');
@@ -567,8 +532,7 @@ function downloadFile(req, res, next) {
if (typeof req.query.file !== 'string' || !req.query.file) return next(new HttpError(400, 'file query argument must be provided'));
apps.downloadFile(req.params.id, req.query.file, function (error, stream, info) {
if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, error.message));
if (error) return next(new HttpError(500, error));
if (error) return next(toHttpError(error));
var headers = {
'Content-Type': 'application/octet-stream',