Skip to content

Commit

Permalink
[PFX-501]: Align express and fastify plugin setups (#775)
Browse files Browse the repository at this point in the history
* create server plugin

* move createApp to gasket/plugin-server

* change to @gasket/plugin-middleware

* move fastify and express hooks to separate files and fix tests

* fix express tests

* fix fastify tests

* cleanup middleware tests

* update readme documents

* update lock file

* add lint and typecheck to middleware scripts

* remove tests

* fix type error in middleware plugin

* remove commented out test
  • Loading branch information
bbetts-godaddy authored Jun 13, 2024
1 parent 4be9917 commit 0f84d29
Show file tree
Hide file tree
Showing 25 changed files with 826 additions and 640 deletions.
47 changes: 37 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 0 additions & 47 deletions packages/gasket-plugin-express/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,29 +60,6 @@ module.exports = {
}
```

### Middleware paths

The `gasket.config.js` can contain a `middleware` property, which is an array of
objects that map plugins to route or path patterns, allowing apps to tune which
middleware are triggered for which requests.

```js
middleware: [
{
plugin:'gasket-plugin-example', // Name of the Gasket plugin
paths: ['/api']
},
{
plugin:'@some/gasket-plugin-example',
paths: [/\/default/]
},
{
plugin: '@another/gasket-plugin-example',
paths: ['/proxy', /\/home/]
}
]
```

## Logging

This plugin attaches a `logger` object to the request object. This object has a `metadata` method that allows you to attach details to any log entry related to the request. For example, you can add the user ID to each log entry. When logging within the context of a request, use the `req.logger` object instead of the global `gasket.logger` so that contextual information is included in the log entry. Here is an example of how to attach metadata to `req.logger` object and how to use it:
Expand All @@ -101,30 +78,6 @@ function someOtherMiddleware(req, res, next) {

## Lifecycles

### middleware

Executed when the `express` server has been created, it will apply all returned
functions as middleware.

```js
module.exports = {
hooks: {
/**
* Add Express middleware
*
* @param {Gasket} gasket The Gasket API
* @param {Express} app - Express app instance
* @returns {function|function[]} middleware(s)
*/
middleware: function (gasket, app) {
return require('x-xss-protection')();
}
}
}
```

You may also return an `Array` to inject more than one middleware.

### express

Executed **after** the `middleware` event for when you need full control over
Expand Down
110 changes: 3 additions & 107 deletions packages/gasket-plugin-express/lib/create-servers.js
Original file line number Diff line number Diff line change
@@ -1,127 +1,23 @@
/* eslint-disable max-statements */
/// <reference types="@gasket/plugin-https" />
/// <reference types="@gasket/plugin-logger" />
const debug = require('diagnostics')('gasket:express');

/**
* Create the Express instance and setup the lifecycle hooks.
* @type {import('@gasket/core').HookHandler<'createServers'>}
*/
module.exports = async function createServers(gasket, serverOpts) {
const express = require('express');
const cookieParser = require('cookie-parser');
const compression = require('compression');

const { config, logger } = gasket;
const { config } = gasket;
const {
express: {
routes,
excludedRoutesRegex,
middlewareInclusionRegex,
compression: compressionConfig = true,
trustProxy = false
routes
} = {},
http2,
middleware: middlewareConfig
http2
} = config;

if (excludedRoutesRegex) {
// eslint-disable-next-line no-console
const warn = logger ? logger.warn : console.warn;
warn('DEPRECATED express config `excludedRoutesRegex` - use `middlewareInclusionRegex`');
}

const app = http2 ? require('http2-express-bridge')(express) : express();
const useForAllowedPaths = (...middleware) =>
middleware.forEach((mw) => {
if (excludedRoutesRegex) {
app.use(excludedRoutesRegex, mw);
} else {
app.use(mw);
}
});

if (trustProxy) {
app.set('trust proxy', trustProxy);
}

if (http2) {
app.use(
/*
* This is a patch for the undocumented _implicitHeader used by the
* compression middleware which is not present the http2 request object
* @see: https://github.com/expressjs/compression/pull/128
* and also, by the 'compiled' version in Next.js
* @see: https://github.com/vercel/next.js/issues/11669
*/
function http2Patch(req, res, next) {
// @ts-ignore
if (!res._implicitHeader) {
// @ts-ignore
res._implicitHeader = () => res.writeHead(res.statusCode);
}
return next();
}
);
}


// eslint-disable-next-line jsdoc/require-jsdoc
function attachLogEnhancer(req) {
req.logger.metadata = (metadata) => {
req.logger = req.logger.child(metadata);
attachLogEnhancer(req);
};
}

useForAllowedPaths((req, res, next) => {
req.logger = gasket.logger;
attachLogEnhancer(req);
next();
});
useForAllowedPaths(cookieParser());

const middlewarePattern = middlewareInclusionRegex || excludedRoutesRegex;
if (middlewarePattern) {
app.use(middlewarePattern, cookieParser());
} else {
app.use(cookieParser());
}

if (compressionConfig) {
app.use(compression());
}

const middlewares = [];
await gasket.execApply('middleware', async (plugin, handler) => {
const middleware = await handler(app);

if (middleware && (!Array.isArray(middleware) || middleware.length)) {
if (middlewareConfig) {
const pluginName = plugin && plugin.name ? plugin.name : '';
const mwConfig = middlewareConfig.find(mw => mw.plugin === pluginName);
if (mwConfig) {
middleware.paths = mwConfig.paths;
if (middlewarePattern) {
middleware.paths.push(middlewarePattern);
}
}
}
middlewares.push(middleware);
}
});

debug('applied %s middleware layers to express', middlewares.length);
middlewares.forEach((layer) => {
const { paths } = layer;
if (paths) {
app.use(paths, layer);
} else if (middlewarePattern) {
app.use(middlewarePattern, layer);
} else {
app.use(layer);
}
});

await gasket.exec('express', app);

Expand Down
Loading

0 comments on commit 0f84d29

Please sign in to comment.