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

feat: multipart/form-data support #543

Merged
merged 18 commits into from
Jan 22, 2021

Conversation

tkamenoko
Copy link
Contributor

@tkamenoko tkamenoko commented Jan 16, 2021

This PR fixes #215 .

It contains multipart/form-data parser that enable to parse a request body into an object.

It also has variables builder based on this spec .

In addition, rest-api can handles multipart/form-data now.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jan 16, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit f8e1957:

Sandbox Source
MSW React Configuration

>('UploadFile', async (req, res, ctx) => {
const { file1, file2, files, plainText } = req.variables
const filesResponse: string[] = []
for (const file of files ?? []) {
Copy link
Member

Choose a reason for hiding this comment

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

?? allows files to equal a falsy value (i.e. false). This would still break the for/of loop:

for (const file of false) // false is not iterable

I suggest we use || instead. Nullish coalescing operator (??) is useful when dealing with possibly falsy values, which isn't the case for files. If files is undefined or falsy we should always fallback to an empty array to not break the for/of loop.

}
>('UploadFile', async (req, res, ctx) => {
const { file1, file2, files, plainText } = req.variables
const filesResponse: string[] = []
Copy link
Member

Choose a reason for hiding this comment

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

What do you think if we use Promise.all and a plain files.map instead of the for/of loop?

const { files = [] } = req.variables
const filesResponse = await Promise.all(files.map(file => file.text())

It's going to be less code, making this example more focused. Promise.all would also be a more recommended approach so that you don't wait for each file to be processed individually, allowing parallel transformations to text.

I'm curious to hear your opinion.


const isMultipart = Boolean(map && fileContents)
const headers = isMultipart ? {} : { 'Content-Type': 'application/json' }
let body: string | FormData
Copy link
Member

Choose a reason for hiding this comment

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

I'd refactor this part as follows:

const body = isMultipartData ? getMultipartGraphQLBody(operations, ...) : operations

This will make executeOperations much easier to read by delegating the logic that creates a FormData into a separate utility function that we can also test separately.

Copy link
Member

@kettanaito kettanaito left a comment

Choose a reason for hiding this comment

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

Hey, @tkamenoko. Thank you for your hard work on this! It looks fantastic.

I've left a few review comments, could you please take a look? My main suggestions were:

  • Don't move runtime declarations to a beforeAll/afterAll hooks. I see this as an additional internal refactoring. Let's keep the changes of this pull request scoped.
  • A few naming and structuring suggestions.

I'm excited to see this landing in the next release. Once more, huge thanks!

kettanaito
kettanaito previously approved these changes Jan 18, 2021
Copy link
Member

@kettanaito kettanaito left a comment

Choose a reason for hiding this comment

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

This looks solid. Let me know if you think these changes are ready to be merged. I'll give them a test locally to get to know multipart data scenarios better.

Thank you for your work on this, @tkamenoko!

@tkamenoko
Copy link
Contributor Author

@kettanaito Thanks for reviewing! I think this PR is ready to merge. Please do it whenever you want.

Copy link
Member

@kettanaito kettanaito left a comment

Choose a reason for hiding this comment

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

This is an incredible addition. Thank you, @tkamenoko! Welcome to contributors 🎉

@kettanaito kettanaito merged commit c45cf14 into mswjs:master Jan 22, 2021
@otaciliolacerda
Copy link
Contributor

Wow, great addition. Thanks for the contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for GraphQL Upload/Multipart Spec
3 participants