vercel / next.js

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

Response headers not accessible on api routes in Vercel #40275

Open pascuflow opened 2 years ago

pascuflow commented 2 years ago

Verify canary release

Provide environment information

Operating System: Platform: linux Arch: x64 Version: #202207312230~1660780566~22.04~9d60db1 SMP PREEMPT_DYNAMIC Thu A Binaries: Node: 16.15.0 npm: 8.5.5 Yarn: 1.22.18 pnpm: N/A Relevant packages: next: 12.2.5 eslint-config-next: 12.1.0 react: 17.0.2 react-dom: 17.0.2

What browser are you using? (if relevant)

Chrome

How are you deploying your application? (if relevant)

Vercel, Netlify

Describe the Bug

Trying to access response headers on pages/api routes not working in production on Vercel. On my middleware.ts I set some cookie like: response.cookies.set('userId', 'blah')

and on my next.config.js I set headers like:

async headers() {
        return [
            {
                // Apply these headers to all routes in your application.
                source: '/:path*',
                headers: [
                {
                    key: 'X-DNS-Prefetch-Control',
                    value: 'on'
                },
                {
                    key: 'Strict-Transport-Security',
                    value: 'max-age=63072000; includeSubDomains; preload'
                },
                {
                    key: 'X-XSS-Protection',
                    value: '1; mode=block'
                },
                {
                    key: 'SameSite',
                    value: 'none'
                }
               ],
            },
        ]
    }

Now when I try to log the headers on pages/api/someroute like:

export default function handler(req, res) {
          console.log(res.getHeaders())
     ....
  }

Locally In Development and Production:

[Object: null prototype] {
  'x-dns-prefetch-control': 'on',
  'strict-transport-security': 'max-age=63072000; includeSubDomains; preload',
  'x-xss-protection': '1; mode=block',
  samesite: 'none',
  'access-control-allow-origin': '*',
  'set-cookie': [ 'userId=blah; Path=/' ]
}

In Vercel:

[Object: null prototype] {}

Why are headers not accessible on api routes in Vercel?

Expected Behavior

When I set headers in response on middleware like indicated here

https://nextjs.org/docs/advanced-features/middleware#using-cookies

I should be able to access them in routes when deployed to Vercel according to docs https://nextjs.org/docs/api-routes/response-helpers and https://nodejs.org/api/http.html#http_class_http_serverresponse

Link to reproduction

N/A

To Reproduce

  1. Create a basic Next project and a middleware.ts file along with an api route.
  2. Set a cookie on the response in middleware or some headers in config
  3. Console.log headers on the response on the api route using res.getHeaders() and verify it works locally.
  4. Deploy to Vercel and check the console.log from step 3 on realtime logs of the Functions.
gahabeen commented 1 year ago

I seem to have encountered the same issue. While it works locally, it doesn't on the platform.

When updating headers in middleware.ts like so:

export default async function middleware(request: NextRequest) {
  return rewrite(request.nextUrl, {
          headers: {
              "test": "please",
          }
      })
};

export const config = {
    matcher: '/api/:path*',
    runtime: 'experimental-edge',
};

In any api route, I cannot get the headers I've set:

import type { NextApiRequest, NextApiResponse } from 'next'

export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse
) {
    res.getHeader('test') // doesn't exists
}
cindyyu commented 1 year ago

I am running into a similar issue... I update the headers in middleware.ts like so:

export async function middleware(request: NextRequest) {
  ...
  const response = NextResponse.next();
  const user = data[0];
  response.headers.set('Authenticated-User', user.id);
  return response;
}

but when I try to access it from the API, the value is null and the Vercel logs print res.getHeaders() as [Object: null prototype] {} like @pascuflow mentioned.

async function handler(req: NextApiRequest, res: NextApiResponse) {
  const userId = res.getHeader('Authenticated-User');
  console.log('headers printed', res.getHeaders());
  ...

This is only happening when the app is deployed to Vercel. I am able to access the updated response headers just fine locally.

Thinkscape commented 10 months ago

Possibly duplicate of #49442 - have a look at the workaround we have there. It might not work when deployed to Vercel though, prob because of differences between the actual runtime vs "simulated one" of next dev.

omgovich commented 2 weeks ago

I have the same issue. When calling res.getHeader in getServerSideProps it returns undefined who the header is set in the middleware and returned to the browser.