Skip to content
This repository has been archived by the owner on May 3, 2024. It is now read-only.

Converted small middlewares into plugins #854

Conversation

giulianok
Copy link
Member

Description

Converted small ExpressJS middlewares into Fastify plugins. These are considered small since have relatively small code and they are (almost) completely abstract

Motivation and Context

By converting ExpressJS middlewares into Fastify plugins, we can migrate routes from Express to Fastify to improve app's performance

How Has This Been Tested?

Unit testing

Types of Changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation (adding or updating documentation)
  • Dependency update
  • Security update

Checklist:

  • My change requires a change to the documentation and I have updated the documentation accordingly.
  • These changes should be applied to a maintenance branch.
  • This change requires cross browser checks.
  • Performance tests should be ran against the server prior to merging.
  • This change impacts caching for client browsers.
  • This change impacts HTTP headers.
  • This change adds additional environment variable requirements for One App users.
  • I have added the Apache 2.0 license header to any new files created.

What is the Impact to Developers Using One App?

@github-actions
Copy link
Contributor

github-actions bot commented Nov 8, 2022

Size Change: 0 B

Total Size: 681 kB

ℹ️ View Unchanged
Filename Size
./build/app/app.js 165 kB
./build/app/app~vendors.js 387 kB
./build/app/runtime.js 7.07 kB
./build/app/service-worker-client.js 7.26 kB
./build/app/vendors.js 114 kB

compressed-size-action

if (matchedDomain) {
res.set('X-Frame-Options', `ALLOW-FROM ${referer}`);
}
done();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we call done here instead of next as previously done?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a fastify naming convention (see https://www.fastify.io/docs/latest/Reference/Plugins/), of course we can call it next if we want, but it's better to follow fastify's naming convention to keep everything more fastify-like and make it easier to read and associate.

you'll also see that i have renamed req -> request and res -> reply, same idea

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, I just thought that next and done where different in Fastify, good to know

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case, there isn't an equivalent in express since a plugin does more things than an middleware and a middleware gets executed on a request, but yeah they're similar

delete request.headers.correlation_id;
request.headers.unique_id = 'thunderstorms';
ensureCorrelationId(fastify, null, jest.fn());
expect(request.headers).toHaveProperty('correlation-id', 'thunderstorms');
});

it('adds a correlation-id header to a request without anything', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it('adds a correlation-id header to a request without anything', () => {
it('adds a unique correlation-id to request header if correlation-id is null', () => {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose adds a unique correlation-id to the request object since tests are assertions, things like without and if shouldn't be used. Also, these are the original test cases, maybe we should spend some time refreshing them 🤔

const csp = (fastify, _opts, done) => {
fastify.decorateRequest('scriptNonce', null);

fastify.addHook('onRequest', async (request, reply) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. Is async intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

* @param {import('fastify').FastifyPluginCallback} done plugin callback
*/
const forwardedHeaderParser = (fastify, _opts, done) => {
fastify.addHook('onRequest', async (request) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is async intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes


fastify.addHook('onRequest', async (request, reply) => {
reply.header('Strict-Transport-Security', 'max-age=15552000; includeSubDomains');
reply.header('x-dns-prefetch-control', 'off');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this include so many headers that were not there previously?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are headers required by the integration tests that are not widely present. For the case of x-dns-prefetch-control, it is added by Helmet (see https://github.com/helmetjs/helmet/blob/a2549bd4688d9e711aea64a7fdffb07f4136f6cf/middlewares/x-dns-prefetch-control/index.ts#L17). Helmet, in the Fastify implementation, is only used on routes that will render Html, it isn't needed for all urls. By doing so, we increase performance. Right now, there's an integration test that expects this header in a route that doesn't render html (see

test('Request: /_/report/security/csp-violation', async () => {
)

if we feel that we do not actually need them for all routes them we can delete them, they were added to support backwards compatibility

// eslint-disable-next-line unicorn/better-regex -- conflicts with unsafe-regex
.replace(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/g, '0.0.0.0');

describe('csp', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please restore the describe block


describe('conditionallyAllowCors', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restore the describe block

@@ -14,39 +14,100 @@
* permissions and limitations under the License.
*/

import addSecurityHeaders from '../../../src/server/middleware/addSecurityHeaders';

describe('addSecurityHeaders', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restore the describe block

});
});

test('adds frame options header', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our convention is to use it over test and for all tests to be contained in a described block

const res = { set: jest.fn((key, value) => value) };
const next = jest.fn();
addCacheHeaders(req, res, next);
test('adds cache headers', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use it and restore the describe block

@giulianok giulianok merged commit 36b61b6 into feature/fastify-migration Nov 28, 2022
@giulianok giulianok deleted the refactor/express-middlewares-to-fastify-plugins branch November 28, 2022 20:11
@giulianok giulianok mentioned this pull request Dec 5, 2022
14 tasks
@giulianok giulianok mentioned this pull request Mar 2, 2023
14 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants