question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Presence of middleware prevents access to raw request bodies greater than or equal to 16,384 bytes (16 KiB)

See original GitHub issue

Verify canary release

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

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 21.6.0: Sat Jun 18 17:07:22 PDT 2022; root:xnu-8020.140.41~1/RELEASE_ARM64_T6000
    Binaries:
      Node: 18.7.0
      npm: 8.15.0
      Yarn: 1.22.19
      pnpm: 7.8.0
    Relevant packages:
      next: 12.2.4-canary.9
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0

What browser are you using? (if relevant)

N/A

How are you deploying your application? (if relevant)

N/A

Describe the Bug

When attempting to upload a file over a few kilobytes (e.g. sending a POST request with a binary body and a Content-Type of multipart/form-data) via fetch or curl, the request stalls, then fails with the error:

error - Error: aborted
    at connResetException (node:internal/errors:704:14)
    at abortIncoming (node:_http_server:700:17)
    at socketOnClose (node:_http_server:694:3)
    at Socket.emit (node:events:525:35)
    at TCP.<anonymous> (node:net:757:14) {
  middleware: true
}

This occurs only for API pages with…

export const config = {
  api: {
    bodyParser: {
      bodyParser: false,
    },
  },
}

and only when middleware is present; even something as basic as:

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

export async function middleware(req: NextRequest) {
    return NextResponse.next()
}

Removing the middleware fixes the issue. Of note, very small request bodies (e.g. < 1kb files) work even in the presence of middleware.

Expected Behavior

Sending a POST request to an API endpoint with a Content-Type of multipart/form-data along with a reasonably sized (~200kB) binary payload should work and not stall.

Link to reproduction

https://github.com/jhahn/nextjs-upload-issue

To Reproduce

pages/index.tsx

import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'

const Home: NextPage = () => {
  const uploadFile = async (files: FileList | null) => {
    if (!files) return
    const formData = new FormData()
    formData.append("file", files[0])
    const response = await fetch("/api/hello", {
      method: "POST",
      body: formData,
    })
    console.log(await response.json())
  }

  return <input type="file" onChange={(e) => uploadFile(e.target.files)} />
}

export default Home

pages/api/hello.ts:

import type { Readable } from 'node:stream';
import type { NextApiRequest, NextApiResponse } from 'next'

export const config = {
  api: {
    bodyParser: {
      bodyParser: false,
    },
  },
}

async function buffer(readable: Readable) {
  const chunks = [];
  for await (const chunk of readable) {
    chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
  }
  return Buffer.concat(chunks);
}

export default async function (req: NextApiRequest, res: NextApiResponse) {
  if (req.method === 'POST') {
    const buf = await buffer(req.body);
    const rawBody = buf.toString('utf8');

    // Can do something here...
    res.json({ rawBody });
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
}

The code for pages/api/hello.ts was adapted from https://vercel.com/support/articles/how-do-i-get-the-raw-body-of-a-serverless-function. However, I had to change const buf = await buffer(req); to const buf = await buffer(req.body);

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:21
  • Comments:44 (4 by maintainers)

github_iconTop GitHub Comments

10reactions
ambrauercommented, Aug 29, 2022

Building on the workaround found by @Gawdfrey (🙏), if you simply wanted to exclude all api routes from middleware, seems you could do something like this:

export const config = {
  matcher: ['/', '/((?!api/).*)'],
};
6reactions
aprendendofelipecommented, Oct 8, 2022

I proposed a solution (#41270). Any collaboration or suggestion is welcome.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to write independent/isolated express middleware with ...
Is it possible to: use middlewares in the manner I am attempting here (i.e. using more than one in succession)? get hold of...
Read more >
Messages (common) · MAVLink Developer Guide
MAVLINK Common Message Set. The MAVLink common message set contains standard definitions that are managed by the MAVLink project.
Read more >
Configuration Reference Red Hat OpenStack Platform 16.2
This document describes the options available in the configuration files for each of the major services in Red Hat OpenStack Platform.
Read more >
e10143.pdf - Oracle Help Center
Oracle Fusion Middleware Administrator's Guide for Oracle Web Cache, ... Configuring Root Privilege for Privileged Ports and More than 1,024 File ...
Read more >
1 INTRODUCTION TO COMPUTER
16. Describe the second generation computer based on the (a) Hardware (b) Software (c) ... include testing for greater than, less than or...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found