Skip to content

Commit 22ca1a2

Browse files
feat(core): add pre-parser route hook for raw body access
Routes matching `*.preroute.js` are mounted before body parsing and CSRF middleware, allowing handlers like Stripe webhooks to access the raw request body for signature verification. Closes #3242
1 parent 4699810 commit 22ca1a2

4 files changed

Lines changed: 16 additions & 1 deletion

File tree

config/assets.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export default {
44
allYaml: 'modules/*/doc/*.yml',
55
mongooseModels: 'modules/*/models/*.mongoose.js',
66
sequelizeModels: 'modules/*/models/*.sequelize.js',
7+
preRoutes: 'modules/*/routes/*.preroute.js',
78
routes: 'modules/*/routes/*.js',
89
config: 'modules/*/*.init.js',
910
policies: 'modules/*/policies/*.js',

lib/helpers/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ const initGlobalConfigFiles = async (assets) => {
9595
files.swagger = await getGlobbedPaths(assets.allYaml); // Setting Globbed module yaml files
9696
files.mongooseModels = await getGlobbedPaths(assets.mongooseModels); // Setting Globbed mongoose model files
9797
files.sequelizeModels = await getGlobbedPaths(assets.sequelizeModels); // Setting Globbed sequelize model files
98+
files.preRoutes = await getGlobbedPaths(assets.preRoutes); // Setting Globbed pre-parser route files
9899
files.routes = await getGlobbedPaths(assets.routes); // Setting Globbed route files
99100
files.configs = await getGlobbedPaths(assets.config); // Setting Globbed config files
100101
// files.sockets = getGlobbedPaths(assets.sockets); // Setting Globbed socket files

lib/services/express.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ const initLocalVariables = (app) => {
6262
});
6363
};
6464

65+
/**
66+
* Initialize pre-parser routes (mounted before body parsing and CSRF)
67+
*/
68+
const initPreParserRoutes = async (app) => {
69+
for (const routePath of config.files.preRoutes) {
70+
const route = await import(path.resolve(routePath));
71+
route.default(app);
72+
}
73+
};
74+
6575
/**
6676
* Initialize application middleware.
6777
* @param {object} app - express application instance
@@ -187,6 +197,8 @@ const init = async () => {
187197
initSwagger(app);
188198
// Initialize local variables
189199
initLocalVariables(app);
200+
// Initialize pre-parser routes (before body parsing and CSRF)
201+
await initPreParserRoutes(app);
190202
// Initialize Express middleware
191203
initMiddleware(app);
192204
// Initialize Helmet security headers
@@ -209,6 +221,7 @@ const init = async () => {
209221
export default {
210222
initSwagger,
211223
initLocalVariables,
224+
initPreParserRoutes,
212225
initMiddleware,
213226
initModulesConfiguration,
214227
initHelmetHeaders,

modules/core/tests/core.unit.tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ describe('Core unit tests:', () => {
5656
});
5757

5858
it('assets should contain the correct keys', () => {
59-
const expectedKeys = ['allJS', 'allYaml', 'mongooseModels', 'sequelizeModels', 'routes', 'config', 'policies'];
59+
const expectedKeys = ['allJS', 'allYaml', 'mongooseModels', 'sequelizeModels', 'preRoutes', 'routes', 'config', 'policies'];
6060

6161
expectedKeys.forEach((key) => {
6262
expect(assets).toHaveProperty(key);

0 commit comments

Comments
 (0)