From a04654a5a0fd16a8173ba4c563e529428c48aa22 Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Mon, 18 Sep 2023 18:49:52 +0100 Subject: [PATCH] Server: Upgraded Formidable parsing library --- packages/server/package.json | 4 +-- packages/server/src/utils/requestUtils.ts | 33 +++++++++++++++++++++-- renovate.json5 | 16 +++++------ yarn.lock | 21 +++++++-------- 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 46be163c88..9e7d67749f 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -33,7 +33,7 @@ "bulma-prefers-dark": "0.1.0-beta.1", "compare-versions": "3.6.0", "dayjs": "1.11.9", - "formidable": "2.1.2", + "formidable": "3.5.1", "fs-extra": "11.1.1", "html-entities": "1.4.0", "jquery": "3.7.1", @@ -60,7 +60,7 @@ "devDependencies": { "@joplin/tools": "~2.13", "@rmp135/sql-ts": "1.18.0", - "@types/formidable": "2.0.6", + "@types/formidable": "3.4.3", "@types/fs-extra": "11.0.1", "@types/jest": "29.5.4", "@types/jest-expect-message": "1.0.4", diff --git a/packages/server/src/utils/requestUtils.ts b/packages/server/src/utils/requestUtils.ts index 6bc3d1efa7..28132e3c4b 100644 --- a/packages/server/src/utils/requestUtils.ts +++ b/packages/server/src/utils/requestUtils.ts @@ -1,10 +1,12 @@ import { cookieGet } from './cookies'; import { ErrorForbidden } from './errors'; import { AppContext } from './types'; -import * as formidable from 'formidable'; +import * as formidableFn from 'formidable'; import { Fields, Files } from 'formidable'; import { IncomingMessage } from 'http'; +const formidable = require('formidable').default as typeof formidableFn; + export type BodyFields = Record; interface FormParseResult { @@ -24,6 +26,28 @@ interface FormParseRequest extends IncomingMessage { body: any; } +// Previously Formidable would return the files and fields as key/value pairs. +// With v3, the value however is always an array. This is unclear why they did +// this but for example a field `email=test@example.com` would come out as +// `email: ['test@example.com']`. Since all our code expect simple key/value +// pairs, we use this function to convert back to the old style. +// +// For the extra challenge, they made this change only if the content-type is +// "application/x-www-form-urlencoded". Other content types such as JSON are not +// modified. +const convertFieldsToKeyValue = (fields: Record) => { + const convertedFields: Record = {}; + for (const [k, v] of Object.entries(fields)) { + if (Array.isArray(v)) { + convertedFields[k] = v.length ? v[0] : undefined; + } else { + convertedFields[k] = v; + } + + } + return convertedFields; +}; + // Input should be Koa ctx.req, which corresponds to the native Node request export async function formParse(request: IncomingMessage): Promise { const req: FormParseRequest = request as any; @@ -40,6 +64,8 @@ export async function formParse(request: IncomingMessage): Promise