Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upgrade formidable to v3 #10451

Merged
merged 1 commit into from
May 27, 2022
Merged

upgrade formidable to v3 #10451

merged 1 commit into from
May 27, 2022

Conversation

znewton
Copy link
Contributor

@znewton znewton commented May 27, 2022

Upgrade Formidable to v3

Taking over #10434, since there are more braking changes than expected.

Description

The currently used version of "formidable" package has a vulnerability bug which has been fixed in the latest version (3.2.4). Bumping up the version to the latest to address the vulnerability issue.

Steps to Reproduce Bug and Validate Solution

Only applicable if the work is to address a bug. Please remove this section if the work is for a feature or story
Provide details on the environment the bug is found, and detailed steps to recreate the bug.
This should be detailed enough for a team member to confirm that the bug no longer occurs

PR Checklist

Use the check-list below to ensure your branch is ready for PR. If the item is not applicable, leave it blank.

  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • My code follows the code style of this project.
  • I ran the lint checks which produced no new errors nor warnings for my changes.
  • I have checked to ensure there aren't other open Pull Requests for the same update/change.

Does this introduce a breaking change?

  • Yes
  • No

If this introduces a breaking change, please describe the impact and migration path for existing applications below.

Testing

  • Instructions for testing and validation of your code so the reviewer can follow those steps and validate code works as expected

Any relevant logs or outputs

  • Use this section to provide either screenshots or output of logs as code snippets

Other information or known dependencies

  • Any other information or known dependencies that is important to this PR.
  • TODO that are to be done after this PR.

@znewton znewton requested review from msfluid-bot and a team as code owners May 27, 2022 01:24
@github-actions github-actions bot added area: server Server related issues (routerlicious) base: main PRs targeted against main branch labels May 27, 2022
Copy link
Contributor

@hedasilv hedasilv left a comment

Choose a reason for hiding this comment

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

Thanks for taking care of this! Just left some comments which are really just curious questions to help me understand some details better 😄

RestLessFieldNames.Method
] as string;
request.method = methodOverride;
] as string[] | string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious, was changing the type of variables produced by reading fields to string[] | string something related to formidable/inclusion?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, Formidable now always returns fields[*] as an array as of v3.0.0

@@ -99,8 +108,9 @@ export class RestLessServer {
}

private async parseStreamRequestFormBody(request: IncomingMessageEx): Promise<void> {
const formidable = (await inclusion("formidable")).default;
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean that the formidable version we are bumping to does not allow what we used to have, like import formidable from "formidable";?

If that is the case, I'm curious: why do we need to use inclusion instead of doing something like

// eslint-disable-next-line @typescript-eslint/no-require-imports
import formidable = require("formidable");

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is due to Formidable switching to ESModules in v3.0.0. It's a really annoying problem, where packages that use ESModules cannot be imported using require(). You would think that import formidable as "formidable" would work, but Typescript is transpiling our code into CommonJS which uses require wherever there is an import (take a look at the dist/ folders locally). @tylerbutler helpfully pointed us to a forum thread with possible fixes (none worked) and the inclusion hack, which does work.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for all the details!

return new Promise<void>((resolve, reject) => {
const form = formidable({ multiples: true });
const form = formidable();
Copy link
Contributor

Choose a reason for hiding this comment

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

You mentioned in the other closed PR that multiples support was removed. How does that affect us?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Formidable now always returns an array, where it used to be dependent on the number of form fields with that field name (1 field name would return string, multiple fieldnames would return array). We made use of this expecting multiple Header fields and handling the array possibility. However, for body and method, we expected 1, so a string. You can see the type changes above in the code (where you commented already). We still need to handle string because if the body is parsed by bodyparser instead, it will be a string | string[]

// set up rudimentary authentication
const authMiddleware: () => express.RequestHandler = () => (req, res, next) => {
if (req.get("Authorization") !== `Bearer ${authToken}`) {
return res.sendStatus(403);
}
next();
};
app.use(authMiddleware());
if (restLessBeforeBodyParser) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Educate me: are we introducing these 2 modes of tests depending on the value of restLessBeforeBodyParser just to improve our test coverage, or is this also something related to formidable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is to improve test coverage. Only 1 path of RestLess server was being tested (the formidable path). So I added this alternate variation to test the bodyparser path. All of our services use the formidable path, which is good, because you can see here I had to make a change to urlencoded to allow it to recognize a restless form body.

@znewton znewton merged commit 87f2e36 into microsoft:main May 27, 2022
@znewton znewton deleted the upgrade-formidable branch May 27, 2022 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: server Server related issues (routerlicious) base: main PRs targeted against main branch
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants