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

Middleware throws TypeError when trying to parse FormData #36497

Closed
1 task done
lessp opened this issue Apr 27, 2022 · 7 comments
Closed
1 task done

Middleware throws TypeError when trying to parse FormData #36497

lessp opened this issue Apr 27, 2022 · 7 comments
Labels
bug Issue was opened via the bug report template. Runtime Related to Node.js or Edge Runtime with Next.js.

Comments

@lessp
Copy link

lessp commented Apr 27, 2022

Verify canary release

  • I verified that the issue exists in Next.js canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: x64
  Version: Darwin Kernel Version 21.4.0: Mon Feb 21 20:34:37 PST 2022; root:xnu-8020.101.4~2/RELEASE_X86_64
Binaries:
  Node: 16.13.2
  npm: 8.1.2
  Yarn: 1.22.15
  pnpm: N/A
Relevant packages:
  next: 12.1.6-canary.9
  react: 17.0.2

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

Not sure if I'm doing anything unexpected, but here goes:

request.formData() - throws

While trying to parse FormData in a middleware like so:

// pages/_middleware.ts
const handler = async (request: NextRequest, _nfe: NextFetchEvent) => {
    const data = await request.formData();
};

export default handler;

With the following request (application/x-www-form-urlencoded):

curl --request POST \
  --url http://localhost:3000/foo \    
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data foo=bar

or (multipart/form-data):

curl --request POST \
  --url http://localhost:3000/foo \
  --header 'Content-Type: multipart/form-data; boundary=---011000010111000001101001' \
  --form foo=bar

Next throws the following error:

TypeError: Unrecognized Content-Type header value. 
FormData can only parse the following MIME types: multipart/form-data, application/x-www-form-urlencoded.

request.json() - works

Making a similar request but with JSON, using the request.json()-method everything works as expected.

curl --request POST \
  --url http://localhost:3000/foo \
  --header 'Content-Type: application/json' \
  --data '{ "foo": "bar" }'

Expected Behavior

request.formData() to parse and return the data for multipart/form-data and application/x-www-form-urlencoded

To Reproduce

  1. Create a middleware in pages/_middleware.ts
const handler = async (request: NextRequest, _nfe: NextFetchEvent) => {
    const data = await request.formData();
};

export default handler;
  1. Make a request similar to one of these:
curl --request POST \
  --url http://localhost:3000/foo \    
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data foo=bar
curl --request POST \
  --url http://localhost:3000/foo \
  --header 'Content-Type: multipart/form-data; boundary=---011000010111000001101001' \
  --form foo=bar
  1. Next should throw the following error:
TypeError: Unrecognized Content-Type header value. 
FormData can only parse the following MIME types: multipart/form-data, application/x-www-form-urlencoded.
@lessp lessp added the bug Issue was opened via the bug report template. label Apr 27, 2022
@lessp lessp changed the title Middleware throwing TypeError when trying to parse FormData Middleware throws TypeError when trying to parse FormData Apr 27, 2022
@balazsorban44 balazsorban44 added the Middleware Related to Next.js Middleware label Apr 29, 2022
@nelopuchades
Copy link
Contributor

Is anyone working on this? Can I? Thanks 🙏🏻

@Schniz
Copy link
Contributor

Schniz commented Jun 24, 2022

hey @nelodev, I am not sure if you have any progress with it, so I'm going to check this out 🙏

@Schniz
Copy link
Contributor

Schniz commented Jun 24, 2022

summary of #37980: a url encoded body does work, but multipart form data does not. it's blocked on undici/the edge-runtime library to implement this. 🙏 lets do it

@javivelasco javivelasco added Runtime Related to Node.js or Edge Runtime with Next.js. and removed Next.js Middleware GA Middleware Related to Next.js Middleware labels Jun 29, 2022
@vaibhav2110
Copy link

Is there any way to convert the x-www-form-urlencoded data to JSON data, similar to bodyParser.urlencoded?

@Kikobeats
Copy link
Member

related: nodejs/undici#974

@Kikobeats
Copy link
Member

Kikobeats commented Oct 7, 2022

The latest Next.js canary should resolve this issue.

In fact, I built a little demo at https://with-edge.vercel.app/api/form-data :✨

// pages/api/form-data.ts

import { NextRequest, NextResponse } from 'next/server'

export const config = { runtime: 'experimental-edge' }

/**
 * Original source
 * https://gist.github.com/eligrey/8335f09276492e69b747fb4017e9570e
 * 
 * Get the cryptographic hash of an ArrayBuffer
 *
 * @param ab - ArrayBuffer to digest
 * @param algorithm - Cryptographic hash digest algorithm
 * @returns Hexadecimal hash digest string
 */
 export const hash = async (
  algorithm: string,
  ab: ArrayBuffer,
): Promise<string> =>
  new Uint8Array(await crypto.subtle.digest(algorithm, ab)).reduce(
    (memo, i) => memo + i.toString(16).padStart(2, '0'),
    '',
  );

const ENDPOINT = process.env.NODE_ENV === 'production' 
  ? 'https://with-edge.vercel.app'
  : 'http://localhost:3000'

export default async function handler(req: NextRequest) {
  if (req.method === 'GET') {
    return NextResponse.json({
      description: 'Upload a file as multipart.',
      usage: `curl -X POST ${ENDPOINT}/api/form-data -F "file=@/logo.png" | jq`
    })
  }

  const formData = await req.formData()
  const file = formData.get('file') as File
  const arrayBuffer = await file.arrayBuffer()

  return new Response(JSON.stringify({
    name: file.name,
    type: file.type,
    size: file.size,
    sha256: await hash('SHA-256', arrayBuffer),
    sha1: await hash('SHA-1', arrayBuffer),
    sha384: await hash('SHA-384', arrayBuffer),
    sha512: await hash('SHA-512', arrayBuffer)
  }))
}

Can you confirm is works for you using Next.js v12.3.2-canary.22 or above?

(if not, I will reopen the issue)

@github-actions
Copy link
Contributor

github-actions bot commented Nov 6, 2022

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. Runtime Related to Node.js or Edge Runtime with Next.js.
Projects
None yet
Development

No branches or pull requests

7 participants