mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-05-08 11:58:12 +00:00
Merge pull request #1095 from balena-io/roman/error-handling
Unify API errors processing
This commit is contained in:
commit
b6498fe25a
@ -935,7 +935,7 @@ export class APIBinder {
|
|||||||
router.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));
|
router.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));
|
||||||
router.use(bodyParser.json({ limit: '10mb' }));
|
router.use(bodyParser.json({ limit: '10mb' }));
|
||||||
|
|
||||||
router.post('/v1/update', (req, res) => {
|
router.post('/v1/update', (req, res, next) => {
|
||||||
apiBinder.eventTracker.track('Update notification');
|
apiBinder.eventTracker.track('Update notification');
|
||||||
if (apiBinder.readyForUpdates) {
|
if (apiBinder.readyForUpdates) {
|
||||||
this.config
|
this.config
|
||||||
@ -953,15 +953,7 @@ export class APIBinder {
|
|||||||
res.sendStatus(202);
|
res.sendStatus(202);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(next);
|
||||||
const msg =
|
|
||||||
err.message != null
|
|
||||||
? err.message
|
|
||||||
: err != null
|
|
||||||
? err
|
|
||||||
: 'Unknown error';
|
|
||||||
res.status(503).send(msg);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
res.sendStatus(202);
|
res.sendStatus(202);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ exports.createV1Api = (router, applications) ->
|
|||||||
|
|
||||||
{ eventTracker } = applications
|
{ eventTracker } = applications
|
||||||
|
|
||||||
router.post '/v1/restart', (req, res) ->
|
router.post '/v1/restart', (req, res, next) ->
|
||||||
appId = checkInt(req.body.appId)
|
appId = checkInt(req.body.appId)
|
||||||
force = checkTruthy(req.body.force)
|
force = checkTruthy(req.body.force)
|
||||||
eventTracker.track('Restart container (v1)', { appId })
|
eventTracker.track('Restart container (v1)', { appId })
|
||||||
@ -18,10 +18,9 @@ exports.createV1Api = (router, applications) ->
|
|||||||
doRestart(applications, appId, force)
|
doRestart(applications, appId, force)
|
||||||
.then ->
|
.then ->
|
||||||
res.status(200).send('OK')
|
res.status(200).send('OK')
|
||||||
.catch (err) ->
|
.catch(next)
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
|
||||||
|
|
||||||
v1StopOrStart = (req, res, action) ->
|
v1StopOrStart = (req, res, next, action) ->
|
||||||
appId = checkInt(req.params.appId)
|
appId = checkInt(req.params.appId)
|
||||||
force = checkTruthy(req.body.force)
|
force = checkTruthy(req.body.force)
|
||||||
if !appId?
|
if !appId?
|
||||||
@ -47,16 +46,14 @@ exports.createV1Api = (router, applications) ->
|
|||||||
return service
|
return service
|
||||||
.then (service) ->
|
.then (service) ->
|
||||||
res.status(200).json({ containerId: service.containerId })
|
res.status(200).json({ containerId: service.containerId })
|
||||||
.catch (err) ->
|
.catch(next)
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
|
||||||
|
|
||||||
router.post '/v1/apps/:appId/stop', (req, res) ->
|
createV1StopOrStartHandler = (action) -> _.partial(v1StopOrStart, _, _, _, action)
|
||||||
v1StopOrStart(req, res, 'stop')
|
|
||||||
|
|
||||||
router.post '/v1/apps/:appId/start', (req, res) ->
|
router.post('/v1/apps/:appId/stop', createV1StopOrStartHandler('stop'))
|
||||||
v1StopOrStart(req, res, 'start')
|
router.post('/v1/apps/:appId/start', createV1StopOrStartHandler('start'))
|
||||||
|
|
||||||
router.get '/v1/apps/:appId', (req, res) ->
|
router.get '/v1/apps/:appId', (req, res, next) ->
|
||||||
appId = checkInt(req.params.appId)
|
appId = checkInt(req.params.appId)
|
||||||
eventTracker.track('GET app (v1)', { appId })
|
eventTracker.track('GET app (v1)', { appId })
|
||||||
if !appId?
|
if !appId?
|
||||||
@ -82,10 +79,9 @@ exports.createV1Api = (router, applications) ->
|
|||||||
appToSend.commit = status.commit
|
appToSend.commit = status.commit
|
||||||
res.json(appToSend)
|
res.json(appToSend)
|
||||||
)
|
)
|
||||||
.catch (err) ->
|
.catch(next)
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
|
||||||
|
|
||||||
router.post '/v1/purge', (req, res) ->
|
router.post '/v1/purge', (req, res, next) ->
|
||||||
appId = checkInt(req.body.appId)
|
appId = checkInt(req.body.appId)
|
||||||
force = checkTruthy(req.body.force)
|
force = checkTruthy(req.body.force)
|
||||||
if !appId?
|
if !appId?
|
||||||
@ -94,6 +90,4 @@ exports.createV1Api = (router, applications) ->
|
|||||||
doPurge(applications, appId, force)
|
doPurge(applications, appId, force)
|
||||||
.then ->
|
.then ->
|
||||||
res.status(200).json(Data: 'OK', Error: '')
|
res.status(200).json(Data: 'OK', Error: '')
|
||||||
.catch (err) ->
|
.catch(next)
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import * as Bluebird from 'bluebird';
|
import * as Bluebird from 'bluebird';
|
||||||
import { Request, Response, Router } from 'express';
|
import { NextFunction, Request, Response, Router } from 'express';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import { fs } from 'mz';
|
import { fs } from 'mz';
|
||||||
|
|
||||||
@ -22,21 +22,10 @@ import { checkInt, checkTruthy } from '../lib/validation';
|
|||||||
export function createV2Api(router: Router, applications: ApplicationManager) {
|
export function createV2Api(router: Router, applications: ApplicationManager) {
|
||||||
const { _lockingIfNecessary, deviceState } = applications;
|
const { _lockingIfNecessary, deviceState } = applications;
|
||||||
|
|
||||||
const messageFromError = (err?: Error | string | null): string => {
|
|
||||||
let message = 'Unknown error';
|
|
||||||
if (err != null) {
|
|
||||||
if (_.isError(err) && err.message != null) {
|
|
||||||
message = err.message;
|
|
||||||
} else {
|
|
||||||
message = err as string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleServiceAction = (
|
const handleServiceAction = (
|
||||||
req: Request,
|
req: Request,
|
||||||
res: Response,
|
res: Response,
|
||||||
|
next: NextFunction,
|
||||||
action: any,
|
action: any,
|
||||||
): Bluebird<void> => {
|
): Bluebird<void> => {
|
||||||
const { imageId, serviceName, force } = req.body;
|
const { imageId, serviceName, force } = req.body;
|
||||||
@ -85,15 +74,16 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
res.status(200).send('OK');
|
res.status(200).send('OK');
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(next);
|
||||||
res.status(503).send(messageFromError(err));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createServiceActionHandler = (action: string) =>
|
||||||
|
_.partial(handleServiceAction, _, _, _, action);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/v2/applications/:appId/purge',
|
'/v2/applications/:appId/purge',
|
||||||
(req: Request, res: Response) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
const { force } = req.body;
|
const { force } = req.body;
|
||||||
const { appId } = req.params;
|
const { appId } = req.params;
|
||||||
|
|
||||||
@ -101,45 +91,28 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
res.status(200).send('OK');
|
res.status(200).send('OK');
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(next);
|
||||||
let message;
|
|
||||||
if (err != null) {
|
|
||||||
message = err.message;
|
|
||||||
if (message == null) {
|
|
||||||
message = err;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message = 'Unknown error';
|
|
||||||
}
|
|
||||||
res.status(503).send(message);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/v2/applications/:appId/restart-service',
|
'/v2/applications/:appId/restart-service',
|
||||||
(req: Request, res: Response) => {
|
createServiceActionHandler('restart'),
|
||||||
return handleServiceAction(req, res, 'restart');
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/v2/applications/:appId/stop-service',
|
'/v2/applications/:appId/stop-service',
|
||||||
(req: Request, res: Response) => {
|
createServiceActionHandler('stop'),
|
||||||
return handleServiceAction(req, res, 'stop');
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/v2/applications/:appId/start-service',
|
'/v2/applications/:appId/start-service',
|
||||||
(req: Request, res: Response) => {
|
createServiceActionHandler('start'),
|
||||||
return handleServiceAction(req, res, 'start');
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/v2/applications/:appId/restart',
|
'/v2/applications/:appId/restart',
|
||||||
(req: Request, res: Response) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
const { force } = req.body;
|
const { force } = req.body;
|
||||||
const { appId } = req.params;
|
const { appId } = req.params;
|
||||||
|
|
||||||
@ -147,14 +120,14 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
res.status(200).send('OK');
|
res.status(200).send('OK');
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(next);
|
||||||
res.status(503).send(messageFromError(err));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Support dependent applications when this feature is complete
|
// TODO: Support dependent applications when this feature is complete
|
||||||
router.get('/v2/applications/state', async (_req: Request, res: Response) => {
|
router.get(
|
||||||
|
'/v2/applications/state',
|
||||||
|
async (_req: Request, res: Response, next: NextFunction) => {
|
||||||
// It's kinda hacky to access the services and db via the application manager
|
// It's kinda hacky to access the services and db via the application manager
|
||||||
// maybe refactor this code
|
// maybe refactor this code
|
||||||
Bluebird.join(
|
Bluebird.join(
|
||||||
@ -224,21 +197,24 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
|
|
||||||
res.status(200).json(response);
|
res.status(200).json(response);
|
||||||
},
|
},
|
||||||
|
).catch(next);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
|
||||||
|
|
||||||
router.get(
|
router.get(
|
||||||
'/v2/applications/:appId/state',
|
'/v2/applications/:appId/state',
|
||||||
(_req: Request, res: Response) => {
|
(_req: Request, res: Response, next: NextFunction) => {
|
||||||
// Get all services and their statuses, and return it
|
// Get all services and their statuses, and return it
|
||||||
applications.getStatus().then(apps => {
|
applications
|
||||||
|
.getStatus()
|
||||||
|
.then(apps => {
|
||||||
res.status(200).json(apps);
|
res.status(200).json(apps);
|
||||||
});
|
})
|
||||||
|
.catch(next);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
router.get('/v2/local/target-state', async (_req, res) => {
|
router.get('/v2/local/target-state', async (_req, res) => {
|
||||||
try {
|
|
||||||
const localMode = await deviceState.config.get('localMode');
|
const localMode = await deviceState.config.get('localMode');
|
||||||
if (!localMode) {
|
if (!localMode) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
@ -292,18 +268,11 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
status: 'success',
|
status: 'success',
|
||||||
state: target,
|
state: target,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
res.status(503).send({
|
|
||||||
status: 'failed',
|
|
||||||
message: messageFromError(err),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post('/v2/local/target-state', async (req, res) => {
|
router.post('/v2/local/target-state', async (req, res) => {
|
||||||
// let's first ensure that we're in local mode, otherwise
|
// let's first ensure that we're in local mode, otherwise
|
||||||
// this function should not do anything
|
// this function should not do anything
|
||||||
try {
|
|
||||||
const localMode = await deviceState.config.get('localMode');
|
const localMode = await deviceState.config.get('localMode');
|
||||||
if (!localMode) {
|
if (!localMode) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
@ -328,19 +297,11 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
message: e.message,
|
message: e.message,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
const message = 'Could not apply target state: ';
|
|
||||||
res.status(503).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: message + messageFromError(e),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/v2/local/device-info', async (_req, res) => {
|
router.get('/v2/local/device-info', async (_req, res) => {
|
||||||
// Return the device type and slug so that local mode builds can use this to
|
// Return the device type and slug so that local mode builds can use this to
|
||||||
// resolve builds
|
// resolve builds
|
||||||
try {
|
|
||||||
// FIXME: We should be mounting the following file into the supervisor from the
|
// FIXME: We should be mounting the following file into the supervisor from the
|
||||||
// start-resin-supervisor script, changed in meta-resin - but until then, hardcode it
|
// start-resin-supervisor script, changed in meta-resin - but until then, hardcode it
|
||||||
const data = await fs.readFile(
|
const data = await fs.readFile(
|
||||||
@ -356,13 +317,6 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
deviceType: deviceInfo.slug,
|
deviceType: deviceInfo.slug,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
const message = 'Could not fetch device information: ';
|
|
||||||
res.status(503).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: message + messageFromError(e),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/v2/local/logs', async (_req, res) => {
|
router.get('/v2/local/logs', async (_req, res) => {
|
||||||
@ -392,15 +346,11 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/v2/containerId', async (req, res) => {
|
router.get('/v2/containerId', async (req, res) => {
|
||||||
try {
|
|
||||||
const services = await applications.services.getAll();
|
const services = await applications.services.getAll();
|
||||||
|
|
||||||
if (req.query.serviceName != null || req.query.service != null) {
|
if (req.query.serviceName != null || req.query.service != null) {
|
||||||
const serviceName = req.query.serviceName || req.query.service;
|
const serviceName = req.query.serviceName || req.query.service;
|
||||||
const service = _.find(
|
const service = _.find(services, svc => svc.serviceName === serviceName);
|
||||||
services,
|
|
||||||
svc => svc.serviceName === serviceName,
|
|
||||||
);
|
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
@ -421,12 +371,6 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
.value(),
|
.value(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
res.status(503).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: messageFromError(e),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/v2/state/status', async (_req, res) => {
|
router.get('/v2/state/status', async (_req, res) => {
|
||||||
@ -481,60 +425,36 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get('/v2/device/name', async (_req, res) => {
|
router.get('/v2/device/name', async (_req, res) => {
|
||||||
try {
|
|
||||||
const deviceName = await applications.config.get('name');
|
const deviceName = await applications.config.get('name');
|
||||||
res.json({
|
res.json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
deviceName,
|
deviceName,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
res.status(503).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: messageFromError(e),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/v2/device/tags', async (_req, res) => {
|
router.get('/v2/device/tags', async (_req, res) => {
|
||||||
try {
|
|
||||||
const tags = await applications.apiBinder.fetchDeviceTags();
|
const tags = await applications.apiBinder.fetchDeviceTags();
|
||||||
return res.json({
|
return res.json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
tags,
|
tags,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
res.status(503).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: messageFromError(e),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/v2/cleanup-volumes', async (_req, res) => {
|
router.get('/v2/cleanup-volumes', async (_req, res) => {
|
||||||
try {
|
|
||||||
const targetState = await applications.getTargetApps();
|
const targetState = await applications.getTargetApps();
|
||||||
const referencedVolumes: string[] = [];
|
const referencedVolumes: string[] = [];
|
||||||
_.each(targetState, app => {
|
_.each(targetState, app => {
|
||||||
_.each(app.volumes, vol => {
|
_.each(app.volumes, vol => {
|
||||||
referencedVolumes.push(
|
referencedVolumes.push(Volume.generateDockerName(vol.appId, vol.name));
|
||||||
Volume.generateDockerName(vol.appId, vol.name),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await applications.volumes.removeOrphanedVolumes(referencedVolumes);
|
await applications.volumes.removeOrphanedVolumes(referencedVolumes);
|
||||||
res.json({
|
res.json({
|
||||||
status: 'success',
|
status: 'success',
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
res.status(503).json({
|
|
||||||
status: 'failed',
|
|
||||||
message: messageFromError(e),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post('/v2/journal-logs', (req, res) => {
|
router.post('/v2/journal-logs', (req, res) => {
|
||||||
try {
|
|
||||||
const all = checkTruthy(req.body.all) || false;
|
const all = checkTruthy(req.body.all) || false;
|
||||||
const follow = checkTruthy(req.body.follow) || false;
|
const follow = checkTruthy(req.body.follow) || false;
|
||||||
const count = checkInt(req.body.count, { positive: true }) || undefined;
|
const count = checkInt(req.body.count, { positive: true }) || undefined;
|
||||||
@ -551,15 +471,5 @@ export function createV2Api(router: Router, applications: ApplicationManager) {
|
|||||||
journald.stdout.unpipe();
|
journald.stdout.unpipe();
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
log.error('There was an error reading the journalctl process', e);
|
|
||||||
if (res.headersSent) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res.json({
|
|
||||||
status: 'failed',
|
|
||||||
message: messageFromError(e),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { NextFunction, Request, Response } from 'express';
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import { Server } from 'http';
|
import { Server } from 'http';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
@ -102,15 +103,11 @@ export class SupervisorAPI {
|
|||||||
this.api.use(expressLogger);
|
this.api.use(expressLogger);
|
||||||
|
|
||||||
this.api.get('/v1/healthy', async (_req, res) => {
|
this.api.get('/v1/healthy', async (_req, res) => {
|
||||||
try {
|
|
||||||
const healths = await Promise.all(this.healthchecks.map(fn => fn()));
|
const healths = await Promise.all(this.healthchecks.map(fn => fn()));
|
||||||
if (!_.every(healths)) {
|
if (!_.every(healths)) {
|
||||||
throw new Error('Unhealthy');
|
throw new Error('Unhealthy');
|
||||||
}
|
}
|
||||||
return res.sendStatus(200);
|
return res.sendStatus(200);
|
||||||
} catch (e) {
|
|
||||||
res.sendStatus(500);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.api.get('/ping', (_req, res) => res.send('OK'));
|
this.api.get('/ping', (_req, res) => res.send('OK'));
|
||||||
@ -127,19 +124,44 @@ export class SupervisorAPI {
|
|||||||
// Expires the supervisor's API key and generates a new one.
|
// Expires the supervisor's API key and generates a new one.
|
||||||
// It also communicates the new key to the balena API.
|
// It also communicates the new key to the balena API.
|
||||||
this.api.post('/v1/regenerate-api-key', async (_req, res) => {
|
this.api.post('/v1/regenerate-api-key', async (_req, res) => {
|
||||||
try {
|
|
||||||
const secret = await this.config.newUniqueKey();
|
const secret = await this.config.newUniqueKey();
|
||||||
await this.config.set({ apiSecret: secret });
|
await this.config.set({ apiSecret: secret });
|
||||||
res.status(200).send(secret);
|
res.status(200).send(secret);
|
||||||
} catch (e) {
|
|
||||||
res.status(503).send(e != null ? e.message : e || 'Unknown error');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// And assign all external routers
|
// And assign all external routers
|
||||||
for (const router of this.routers) {
|
for (const router of this.routers) {
|
||||||
this.api.use(router);
|
this.api.use(router);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error handling.
|
||||||
|
|
||||||
|
const messageFromError = (err?: Error | string | null): string => {
|
||||||
|
let message = 'Unknown error';
|
||||||
|
if (err != null) {
|
||||||
|
if (_.isError(err) && err.message != null) {
|
||||||
|
message = err.message;
|
||||||
|
} else {
|
||||||
|
message = err as string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.api.use(
|
||||||
|
(err: Error, req: Request, res: Response, next: NextFunction) => {
|
||||||
|
if (res.headersSent) {
|
||||||
|
// Error happens while we are writing the response - default handler closes the connection.
|
||||||
|
next(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.error(`Error on ${req.method} ${req.path}: `, err);
|
||||||
|
res.status(503).send({
|
||||||
|
status: 'failed',
|
||||||
|
message: messageFromError(err),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async listen(
|
public async listen(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user