Skip to content

Commit

Permalink
[INV-3662] Create Error Handler, move middleware to named files, crea…
Browse files Browse the repository at this point in the history
…te common Database caller (#3696)

* create error handling middleware

* Create commonDbRequest function to handle setup/teardown

* Move bearer logic to separate file

* move cors logic to separate file, create index for imports

* refactor App.ts to use the imported functions

* Remove common Db Request
  • Loading branch information
LocalNewsTV authored Nov 20, 2024
1 parent 4a1d06e commit 929f6e8
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 58 deletions.
62 changes: 4 additions & 58 deletions api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import compression from 'compression';
import { initialize } from 'express-openapi';
import { api_doc } from 'sharedAPI/src/openapi/api-doc/api-doc';
import { applyApiDocSecurityFilters } from 'utils/api-doc-security-filter';
import { authenticate, InvasivesRequest } from 'utils/auth-utils';
import { getLogger } from 'utils/logger';
import { MDC, MDCAsyncLocal } from 'mdc';
import * as middleware from './middleware';

const defaultLog = getLogger('app');

Expand All @@ -30,30 +29,7 @@ function shouldCompress(req, res) {
}

// Enable CORS
app.use(function (req: any, res: any, next: any) {
//
// if (req.url !== '/api/misc/version') {
// // filter out health check for log brevity
// MDC
// }

res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader(
'Access-Control-Allow-Headers',
'X-Requested-With, Content-Type, Authorization, responseType, Access-Control-Allow-Origin, If-None-Match, filterForSelectable'
);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD');
res.setHeader('Access-Control-Allow-Origin', '*');

// create a context if there isn't one
let mdc = MDCAsyncLocal.getStore();
if (!mdc) {
mdc = new MDC();
MDCAsyncLocal.run(mdc, next);
} else {
next();
}
});
app.use(middleware.cors);

// Initialize express-openapi framework
initialize({
Expand All @@ -69,43 +45,13 @@ initialize({
'application/x-www-form-urlencoded': bodyParser.urlencoded({ limit: '50mb', extended: true })
},
securityHandlers: {
Bearer: async function (req) {
try {
let mdc = MDCAsyncLocal.getStore();
if (!mdc) {
mdc = new MDC();
await MDCAsyncLocal.run(mdc, authenticate, <InvasivesRequest>req);
} else {
await authenticate(<InvasivesRequest>req);
}
} catch (e) {
defaultLog.error({ error: e });
return false;
}
// await applyApiDocSecurityFilters(<InvasivesRequest>(<unknown>req));
return true;
}
Bearer: middleware.bearerHandler
},

securityFilter: applyApiDocSecurityFilters,
errorMiddleware: middleware.globalErrorHandler,
errorTransformer: function (openapiError: object, ajvError: object): object {
// Transform openapi-request-validator and openapi-response-validator errors
defaultLog.error({ label: 'errorTransformer', message: 'ajvError', ajvError });
return ajvError;
},
// If `next` is not included express will silently skip calling the `errorMiddleware` entirely.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
errorMiddleware: function (error, req, res, next) {
defaultLog.error({
label: 'errorHandler',
message: 'unexpected error',
error: error?.message + error?.stack || error
});
if (!res.headersSent) {
// streaming responses cannot alter headers after dispatch
res.status(error.status || error.code || 500).json(error);
} else {
}
}
});

Expand Down
21 changes: 21 additions & 0 deletions api/src/middleware/bearerHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { MDC, MDCAsyncLocal } from 'mdc';
import { authenticate, InvasivesRequest } from 'utils/auth-utils';
import { getLogger } from 'utils/logger';

const bearerHandler = async (req) => {
const logger = getLogger('Error');
try {
let mdc = MDCAsyncLocal.getStore();
if (!mdc) {
mdc = new MDC();
await MDCAsyncLocal.run(mdc, authenticate, <InvasivesRequest>req);
} else {
await authenticate(<InvasivesRequest>req);
}
} catch (e) {
logger.error({ error: e });
return false;
}
return true;
};
export default bearerHandler;
21 changes: 21 additions & 0 deletions api/src/middleware/cors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { MDC, MDCAsyncLocal } from 'mdc';

const cors = (_: any, res: any, next) => {
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader(
'Access-Control-Allow-Headers',
'X-Requested-With, Content-Type, Authorization, responseType, Access-Control-Allow-Origin, If-None-Match, filterForSelectable'
);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD');
res.setHeader('Access-Control-Allow-Origin', '*');

// create a context if there isn't one
let mdc = MDCAsyncLocal.getStore();
if (!mdc) {
mdc = new MDC();
MDCAsyncLocal.run(mdc, next);
} else {
next();
}
};
export default cors;
27 changes: 27 additions & 0 deletions api/src/middleware/globalErrorHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { NextFunction, Request, Response } from 'express';
import { getLogger } from 'utils/logger';

export class CustomError extends Error {
code: number;
constructor(message?: string, code?: number) {
super(message);
this.code = code;
}
}
const globalErrorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => {
const logger = getLogger('Error');
const code = err instanceof CustomError ? err.code : 500;
const errorResponse = {
req: req.body,
error: err.message || 'Internal Server Error',
method: req.method,
namespace: req.url
};
logger.error(errorResponse);
if (!res.headersSent) {
res.status(code).json(errorResponse);
}
next();
};

export default globalErrorHandler;
3 changes: 3 additions & 0 deletions api/src/middleware/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as globalErrorHandler } from './globalErrorHandler';
export { default as bearerHandler } from './bearerHandler';
export { default as cors } from './cors';

0 comments on commit 929f6e8

Please sign in to comment.