Skip to content

Commit

Permalink
refactor: migrate from fastify v3 to v4 (#933)
Browse files Browse the repository at this point in the history
* refactor: return req in `preValidation` hooks

* refactor: return payload in `onSend` hooks

* refactor: await register of plugins

* refactor: make routes async

* refactor: migrate from fastify v3 to v4

* test(server): error handling
  • Loading branch information
Fdawgs authored Jul 27, 2022
1 parent de32fc1 commit c8a879e
Show file tree
Hide file tree
Showing 45 changed files with 1,094 additions and 1,319 deletions.
1,857 changes: 802 additions & 1,055 deletions package-lock.json

Large diffs are not rendered by default.

32 changes: 16 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"jest": "jest",
"jest:coverage": "jest --coverage",
"lint": "eslint . --cache --ext js,jsx,ts,tsx --ignore-path .gitignore",
"lint:licenses": "license-checker --direct --excludePackages=\"caniuse-lite@1.0.30001366;duck@0.1.12;language-subtag-registry@0.3.22;tesseract.js-core@2.2.0;url-template@2.0.8\" --onlyAllow=\"0BSD;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;MIT;Python-2.0;Unlicense\" --production --summary",
"lint:licenses": "license-checker --direct --excludePackages=\"caniuse-lite@1.0.30001370;duck@0.1.12;language-subtag-registry@0.3.22;tesseract.js-core@2.2.0;url-template@2.0.8\" --onlyAllow=\"0BSD;Apache-2.0;BSD-2-Clause;BSD-3-Clause;ISC;MIT;Python-2.0;Unlicense\" --production --summary",
"lint:prettier": "prettier . -w -u",
"lint:prettier:ci": "prettier . -c -u",
"prepare": "husky install",
Expand Down Expand Up @@ -81,27 +81,28 @@
"license-checker": "^25.0.1",
"nodemon": "^2.0.19",
"pino-pretty": "^8.1.0",
"playwright": "^1.23.4",
"playwright": "^1.24.1",
"prettier": "^2.7.1"
},
"dependencies": {
"@fastify/accepts": "^3.0.0",
"@fastify/accepts": "^4.0.0",
"@fastify/autoload": "^5.1.0",
"@fastify/bearer-auth": "^7.0.2",
"@fastify/compress": "^5.0.0",
"@fastify/cors": "^7.0.0",
"@fastify/helmet": "^8.1.0",
"@fastify/rate-limit": "^6.0.1",
"@fastify/sensible": "^4.1.0",
"@fastify/static": "^5.0.2",
"@fastify/swagger": "^6.1.0",
"@fastify/bearer-auth": "^8.0.1",
"@fastify/compress": "^6.1.0",
"@fastify/cors": "^8.0.0",
"@fastify/helmet": "^9.1.0",
"@fastify/rate-limit": "^7.3.0",
"@fastify/sensible": "^5.1.0",
"@fastify/static": "^6.4.1",
"@fastify/swagger": "^7.4.1",
"@fastify/under-pressure": "^7.0.0",
"cssesc": "^3.0.0",
"cssom": "^0.5.0",
"dotenv": "^16.0.1",
"env-schema": "^5.0.0",
"fastify": "^3.29.1",
"fastify-disablecache": "^2.0.8",
"fastify-floc-off": "^1.0.7",
"fastify": "^4.3.0",
"fastify-disablecache": "^3.0.0",
"fastify-floc-off": "^2.0.0",
"fastify-plugin": "^4.0.0",
"file-stream-rotator": "^0.6.1",
"file-type": "^16.5.4",
Expand All @@ -115,12 +116,11 @@
"node-poppler": "^5.1.6",
"node-unrtf": "^2.0.9",
"physical-cpu-count": "^2.0.0",
"pino": "^8.2.0",
"pino": "^8.3.0",
"raw-body": "^2.5.1",
"redoc": "^2.0.0-rc.72",
"secure-json-parse": "^2.4.0",
"tesseract.js": "^2.1.5",
"under-pressure": "^5.8.1",
"upath": "^2.0.1"
}
}
3 changes: 1 addition & 2 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ const main = async () => {
const config = await getConfig();

const server = Fastify(config.fastifyInit);
server.register(startServer, config);
await server.listen(config.fastify);
await server.register(startServer, config).listen(config.fastify);

["SIGINT", "SIGTERM"].forEach((signal) => {
// Use once() so that double signals exits the app
Expand Down
10 changes: 8 additions & 2 deletions src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ async function getConfig() {

const config = {
fastify: {
host: env.SERVICE_HOST,
port: env.SERVICE_PORT,
},
fastifyInit: {
Expand Down Expand Up @@ -183,6 +182,9 @@ async function getConfig() {
},
/* istanbul ignore next: pino functions not explicitly tested */
res(res) {
// Required for the statusCode to be logged
// https://github.com/pinojs/pino-std-serializers/blob/9da36144d43aabc7933f0504b02fef5a341583c2/lib/res.js#L37
res.headersSent = true;
return pino.stdSerializers.res(res);
},
},
Expand All @@ -203,7 +205,6 @@ async function getConfig() {
},
rateLimit: {
continueExceeding: true,
// Ensure rate limit also applies to 4xx and 5xx responses
hook: "onSend",
max: env.RATE_LIMIT_MAX_CONNECTIONS_PER_MIN || 1000,
timeWindow: 60000,
Expand Down Expand Up @@ -318,6 +319,11 @@ async function getConfig() {
},
};

// Ensure API listens on both IPv4 and IPv6 addresses
if (env.SERVICE_HOST) {
config.fastify.host = env.SERVICE_HOST;
}

if (env.LOG_ROTATION_FILENAME) {
// Rotation options: https://github.com/rogerc/file-stream-rotator/#options
config.fastifyInit.logger.stream = rotatingLogStream.getStream({
Expand Down
7 changes: 4 additions & 3 deletions src/plugins/docx-to-html/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const mammoth = require("mammoth");
async function plugin(server) {
server.addHook("onRequest", async (req) => {
req.conversionResults = { body: undefined };
return req;
});

server.addHook("preHandler", async (req, res) => {
Expand Down Expand Up @@ -42,13 +43,13 @@ async function plugin(server) {
* Mammoth will throw if the .docx file provided
* by client is malformed, thus client error code
*/
throw res.badRequest();
throw server.httpErrors.badRequest();
}
});
}

module.exports = fp(plugin, {
fastify: "3.x",
fastify: "4.x",
name: "docx-to-html",
dependencies: ["fastify-sensible"],
dependencies: ["@fastify/sensible"],
});
4 changes: 2 additions & 2 deletions src/plugins/docx-to-html/plugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ describe("DOCX-to-HTML Conversion Plugin", () => {
}
);

server.register(sensible).register(plugin);
await server.register(sensible).register(plugin);

server.post("/", async (req, res) => {
res.header("content-type", "application/json");
res.send(req.conversionResults);
return req.conversionResults;
});

await server.ready();
Expand Down
7 changes: 4 additions & 3 deletions src/plugins/docx-to-txt/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const mammoth = require("mammoth");
async function plugin(server) {
server.addHook("onRequest", async (req) => {
req.conversionResults = { body: undefined };
return req;
});

server.addHook("preHandler", async (req, res) => {
Expand All @@ -23,13 +24,13 @@ async function plugin(server) {
* Mammoth will throw if the .docx file provided
* by client is malformed, thus client error code
*/
throw res.badRequest();
throw server.httpErrors.badRequest();
}
});
}

module.exports = fp(plugin, {
fastify: "3.x",
fastify: "4.x",
name: "docx-to-txt",
dependencies: ["fastify-sensible"],
dependencies: ["@fastify/sensible"],
});
4 changes: 2 additions & 2 deletions src/plugins/docx-to-txt/plugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ describe("DOCX-to-TXT Conversion Plugin", () => {
}
);

server.register(sensible).register(plugin);
await server.register(sensible).register(plugin);

server.post("/", async (req, res) => {
res.header("content-type", "application/json");
res.send(req.conversionResults);
return req.conversionResults;
});

await server.ready();
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/embed-html-images/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ async function plugin(server, options) {
}

module.exports = fp(plugin, {
fastify: "3.x",
fastify: "4.x",
name: "embed-html-images",
});
18 changes: 8 additions & 10 deletions src/plugins/embed-html-images/plugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ describe("Embed-HTML-Images Plugin", () => {
test("Should embed images into HTML", async () => {
const altConfig = await getConfig();
altConfig.poppler.tempDirectory = "./test_resources/test_files/";
server.post("/", async (req, res) => {
res.send(await server.embedHtmlImages(req.body));
server.post("/", async (req) => {
const result = await server.embedHtmlImages(req.body);
return result;
});
server.register(plugin, altConfig.poppler);

await server.ready();
await server.register(plugin, altConfig.poppler).ready();

const response = await server.inject({
method: "POST",
Expand All @@ -58,12 +57,11 @@ describe("Embed-HTML-Images Plugin", () => {
});

test("Should throw error if it cannot find images to embed in specified directory", async () => {
server.post("/", async (req, res) => {
res.send(await server.embedHtmlImages(req.body));
server.post("/", async (req) => {
const result = await server.embedHtmlImages(req.body);
return result;
});
server.register(plugin, config.poppler);

await server.ready();
await server.register(plugin, config.poppler).ready();

const response = await server.inject({
method: "POST",
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/image-to-txt/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ async function plugin(server, options) {
});
}

module.exports = fp(plugin, { fastify: "3.x", name: "image-to-txt" });
module.exports = fp(plugin, { fastify: "4.x", name: "image-to-txt" });
4 changes: 2 additions & 2 deletions src/plugins/image-to-txt/plugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("Image-To-TXT Conversion Plugin", () => {
return res;
});

server.register(plugin, config.tesseract);
await server.register(plugin, config.tesseract);

server.post("/", async (req, res) => {
res.header("content-type", "text/plain, charset=utf-8");
Expand All @@ -29,7 +29,7 @@ describe("Image-To-TXT Conversion Plugin", () => {
data: { text },
} = await server.tesseract.addJob("recognize", req.body);

res.send(text);
return text;
});

await server.ready();
Expand Down
11 changes: 6 additions & 5 deletions src/plugins/pdf-to-html/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ const parseString = require("../../utils/parse-string");
async function plugin(server, options) {
server.addHook("onRequest", async (req) => {
req.conversionResults = { body: undefined };
return req;
});

// "onSend" hook used instead of "onResponse" ensures
// cancelled request temp data is also removed
server.addHook("onSend", async (req, res) => {
server.addHook("onSend", async (req, res, payload) => {
if (req?.conversionResults?.docLocation) {
// Remove files from temp directory after response sent
const files = glob.sync(
Expand All @@ -47,7 +48,7 @@ async function plugin(server, options) {
await Promise.all(files.map((file) => fs.unlink(file)));
}

return res;
return payload;
});

server.addHook("preHandler", async (req, res) => {
Expand Down Expand Up @@ -132,7 +133,7 @@ async function plugin(server, options) {
*/
/* istanbul ignore else: unable to test unknown errors */
if (/Syntax Error:/.test(err)) {
throw res.badRequest();
throw server.httpErrors.badRequest();
} else {
throw err;
}
Expand Down Expand Up @@ -168,7 +169,7 @@ async function plugin(server, options) {
}

module.exports = fp(plugin, {
fastify: "3.x",
fastify: "4.x",
name: "pdf-to-html",
dependencies: ["fastify-sensible"],
dependencies: ["@fastify/sensible"],
});
4 changes: 2 additions & 2 deletions src/plugins/pdf-to-html/plugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ describe("PDF-to-HTML Conversion Plugin", () => {
return res;
});

server.register(sensible).register(plugin, config.poppler);
await server.register(sensible).register(plugin, config.poppler);

server.post("/", async (req, res) => {
res.header("content-type", "application/json");
res.send(req.conversionResults);
return req.conversionResults;
});

await server.ready();
Expand Down
15 changes: 8 additions & 7 deletions src/plugins/pdf-to-txt/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ const parseString = require("../../utils/parse-string");
async function plugin(server, options) {
server.addHook("onRequest", async (req) => {
req.conversionResults = { body: undefined };
return req;
});

// "onSend" hook used instead of "onResponse" ensures
// cancelled request temp data is also removed
server.addHook("onSend", async (req, res) => {
server.addHook("onSend", async (req, res, payload) => {
if (req?.conversionResults?.docLocation) {
// Remove files from temp directory after response sent
const files = glob.sync(
Expand All @@ -44,7 +45,7 @@ async function plugin(server, options) {
await Promise.all(files.map((file) => fs.unlink(file)));
}

return res;
return payload;
});

server.addHook("preHandler", async (req, res) => {
Expand All @@ -53,7 +54,7 @@ async function plugin(server, options) {
* and produces results, so catch them here
*/
if (req.body === undefined || Object.keys(req.body).length === 0) {
throw res.badRequest();
throw server.httpErrors.badRequest();
}

// Define any default settings the plugin should have to get up and running
Expand Down Expand Up @@ -131,7 +132,7 @@ async function plugin(server, options) {
*/
/* istanbul ignore else: unable to test unknown errors */
if (/Syntax Error:/.test(err)) {
throw res.badRequest();
throw server.httpErrors.badRequest();
} else {
throw err;
}
Expand Down Expand Up @@ -193,7 +194,7 @@ async function plugin(server, options) {
*/
/* istanbul ignore else: unable to test unknown errors */
if (/Syntax Error:/.test(err)) {
throw res.badRequest();
throw server.httpErrors.badRequest();
} else {
throw err;
}
Expand All @@ -216,7 +217,7 @@ async function plugin(server, options) {
}

module.exports = fp(plugin, {
fastify: "3.x",
fastify: "4.x",
name: "pdf-to-txt",
dependencies: ["fastify-sensible"],
dependencies: ["@fastify/sensible"],
});
4 changes: 2 additions & 2 deletions src/plugins/pdf-to-txt/plugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ describe("PDF-to-TXT Conversion Plugin", () => {
return res;
});

server
await server
.register(imageToTxt, config.tesseract)
.register(sensible)
.register(plugin, config.poppler);

server.post("/", async (req, res) => {
res.header("content-type", "application/json");
res.send(req.conversionResults);
return req.conversionResults;
});

await server.ready();
Expand Down
Loading

0 comments on commit c8a879e

Please sign in to comment.