vercel / next.js

The React Framework
https://nextjs.org
MIT License
125.96k stars 26.87k forks source link

Middleware and custom server randomly causes `uncaughtException` `error: aborted` when work with nginx using `error_page` #49587

Open nvh3011 opened 1 year ago

nvh3011 commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 21.3.0: Wed Jan  5 21:37:58 PST 2022; root:xnu-8019.80.24~20/RELEASE_ARM64_T8101
    Binaries:
      Node: 16.13.1
      npm: 8.1.2
      Yarn: 1.22.19
      pnpm: N/A
    Relevant packages:
      next: 13.4.2-canary.4
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: N/A

Which area(s) of Next.js are affected? (leave empty if unsure)

Middleware / Edge (API routes, runtime)

Link to the code that reproduces this issue

/

To Reproduce

  1. Set up nginx and run with config:

    server {
    listen 80;
    server_name _;
    
    location / {
      proxy_pass http://host.lima.internal:3000;
    
    }
    
    location /not_found {
      return 404 "The requested 1 resource was not found";
    }
    
    proxy_intercept_errors on;
    
    error_page 404 /not_found;
    }
  2. Add middleware.js file inside /src
    
    //middleware.js
    import { NextResponse } from 'next/server';

export async function middleware(req, event) { console.log([*] Request new: ${req.url}); return NextResponse.next(); }

3. Add custom server inside `/src`:
```js
//server.js
const express = require('express');
const next = require('next');

const dev = process.env.NODE_ENV !== 'production';
const hostname = 'localhost';
const port = 3000;

process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception log :', error);
})

const app = next({
  dev,
  hostname,
  port
});
const handler = app.getRequestHandler();

app.prepare().then(() => {
    const server = express();
    server.all('*', (req, res) => {
      return handler(req, res);
    });

    server.listen(3000, (err) => {
      if (err) {
        console.log(err);
        process.exit(1);
      }

      console.log(`> Listening on http://:3000`);
    });
});
  1. Set up script run custom server:
    "scripts": {
    "dev": "next dev",
    "start": "NODE_ENV=production node src/server.js",
    "start-next": "next start",
    "build": "next build",
    "lint": "next lint"
    },
  2. run nginx proxy in local machine
  3. run npm run build
  4. run npm run start
  5. run fetch requests in console window:
    for (let index = 0; index < 120; index++) {
    fetch(`http://localhost/hyusy/isisom${index}`, {
      "headers": {
        "accept": "application/json, text/plain, */*",
        "accept-language": "en-US,en;q=0.9",
        "cache-control": "no-cache",
        "content-type": "application/json",
        "sec-fetch-dest": "empty"
      },
      "referrerPolicy": "unsafe-url",
      "body": "{}",
      "method": "POST",
      "credentials": "include"
    });
    }
  6. Randomly cause an error Error: aborted
    Uncaught Exception log : Error: aborted
    at connResetException (node:internal/errors:691:14)
    at abortIncoming (node:_http_server:596:17)
    at socketOnClose (node:_http_server:590:3)
    at Socket.emit (node:events:402:35)
    at TCP.<anonymous> (node:net:687:12) {
    code: 'ECONNRESET'
    }

Describe the Bug

Expected Behavior

Nextjs should not throw the uncaughtException

Which browser are you using? (if relevant)

Chrome 112.0.5615.137

How are you deploying your application? (if relevant)

using custom server and local

masterkain commented 1 year ago

is this similar? https://github.com/vercel/next.js/issues/49623

nvh3011 commented 1 year ago

Hi @masterkain I believe the error showed similarities, but there are differences in how it is reproduced. Even I increase RAM, it is not solved

nvh3011 commented 1 year ago

I figure out the error throw randomly after running params.request.body.finalize(). ref: https://github.com/vercel/next.js/blob/7adb273b02404949784f9211438e1d5d32e3b6ee/packages/next/src/server/web/sandbox/sandbox.ts#L113

kbarrette commented 1 year ago

@nvh3011 did you ever find a solution for this? I think I'm seeing a similar problem.

woowa-boku commented 1 year ago

@nvh3011 I faced this issue after upgrading from version 12.3.0 to 12.3.4.

Yanquickom commented 1 year ago

Hi, I only work around with:

KianBrose commented 9 months ago

Still happening, nextjs 12.1

Edit by maintainers: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

magoz commented 5 months ago

Same here:

From: https://github.com/vercel/next.js/issues/56529#issuecomment-2081606279

When I use the middleware CORS example from the docs, I get the following error, even the request completes/succeeds.

Using Next 14.2.3.

Error:

Error: aborted
    at abortIncoming (node:_http_server:794:17)
    at socketOnClose (node:_http_server:788:3)
    at Socket.emit (node:events:531:35)
    at TCP.<anonymous> (node:net:337:12)
    at TCP.callbackTrampoline (node:internal/async_hooks:130:17) {
  code: 'ECONNRESET'
}
 ⨯ uncaughtException: Error: aborted
    at abortIncoming (node:_http_server:794:17)
    at socketOnClose (node:_http_server:788:3)
    at Socket.emit (node:events:531:35)
    at TCP.<anonymous> (node:net:337:12)
    at TCP.callbackTrampoline (node:internal/async_hooks:130:17) {
  code: 'ECONNRESET'
}
 ⨯ uncaughtException: Error: aborted
    at abortIncoming (node:_http_server:794:17)
    at socketOnClose (node:_http_server:788:3)
    at Socket.emit (node:events:531:35)
    at TCP.<anonymous> (node:net:337:12)
    at TCP.callbackTrampoline (node:internal/async_hooks:130:17) {
  code: 'ECONNRESET'

Middleware (using it as stated in the docs):

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

const allowedOrigins = ['https://acme.com', 'https://my-app.org']

const corsOptions = {
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}

export function middleware(request: NextRequest) {
  // Check the origin from the request
  const origin = request.headers.get('origin') ?? ''
  const isAllowedOrigin = allowedOrigins.includes(origin)

  // Handle preflighted requests
  const isPreflight = request.method === 'OPTIONS'

  if (isPreflight) {
    const preflightHeaders = {
      ...(isAllowedOrigin && { 'Access-Control-Allow-Origin': origin }),
      ...corsOptions,
    }
    return NextResponse.json({}, { headers: preflightHeaders })
  }

  // Handle simple requests
  const response = NextResponse.next()

  if (isAllowedOrigin) {
    response.headers.set('Access-Control-Allow-Origin', origin)
  }

  Object.entries(corsOptions).forEach(([key, value]) => {
    response.headers.set(key, value)
  })

  return response
}

export const config = {
  matcher: '/api/:path*',
}