aiw
aiw

Reputation: 85

How to modify request headers in Next.js

I have a need to add a header to each request to the server.

I do it this using _midleware like this:

export async function middleware(req: NextRequest): Promise<NextResponse> {
    req.headers.append('x-custom-header', '1337');
    return NextResponse.next();
}

If I do console.log(req.headers) I see that the request header has been added:

BaseHeaders [Headers] {
    [Symbol(map)]: {
      accept: [ '*/*' ],
      'accept-encoding': [ 'gzip, deflate, br' ],
      'accept-language': [ 'en-GB,en-US;q=0.9,en;q=0.8' ],
      'cache-control': [ 'no-cache' ],
      connection: [ 'keep-alive' ],
      cookie: ...,
      host: ...,
      pragma: [ 'no-cache' ],
      referer: ...,
      ...,
      'x-custom-header': [ '1337' ]
    }
  }

However, this does not modify the request: there is no request header in the browser.

Why is the request not modified? Are there alternative ways to modify request headers in Next.js?

Upvotes: 14

Views: 52496

Answers (4)

makeiteasy
makeiteasy

Reputation: 909

Looks like starting from Next.js v13.0.0 it is now possible to modify request headers: https://nextjs.org/docs/advanced-features/middleware#setting-headers

Here's a code snippet from the documentation:

// middleware.ts

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

export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-hello-from-middleware1`
  const requestHeaders = new Headers(request.headers)
  requestHeaders.set('x-hello-from-middleware1', 'hello')

  // You can also set request headers in NextResponse.rewrite
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  })

  // Set a new response header `x-hello-from-middleware2`
  response.headers.set('x-hello-from-middleware2', 'hello')
  return response
}

Upvotes: 13

EricLKH
EricLKH

Reputation: 55

This is what worked for me. The header is changed in middleware and reflected in getServerSideProps.

export async function middleware(request: NextRequest) : Promise<NextResponse> {
    const response = NextResponse.next()
    response.headers.append("key", "value")
    return response
}


//inside page
export const getServerSideProps = wrapper.getServerSideProps(store => async (context) => {
    //the headers are changed here
    console.log(context.res.getHeaders())
    return {
      props: {}
    }
  }
});

Upvotes: 3

Gary Archer
Gary Archer

Reputation: 29326

Interesting question actually, since although I've done a lot of work on SPA architectures I hadn't looked into nextjs and its SSR behavior.

CUSTOM HEADERS AND CROSS SITE REQUEST FORGERY

A good angle for solving your problem is to think about other common use cases for custom headers and look for a nextjs solution. A security related one is to send a Cross Site Request Forgery custom request header, eg example-csrf, in data changing API requests.

When I searched for nextjs ways to do that I found this next-csrf library and I suspect it will enable you to solve your problem. From what I can see, it works like this, though I think you'll understand the nextjs specifics better than me:

  • The middleware class runs on the website when a request is first received, and creates the request header value

  • The value is then provided to React components, which will run in the browser:

import { getCsrfToken } from '../lib/csrf';

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} csrfToken={getCsrfToken()} />
}
  • Also I think the React views you write can then send that value from the browser if required:
const response = await fetch('/api/protected', {
    'headers': {
        'XSRF-TOKEN': csrfToken,
    }
});

There are some issues / feedback posted on the CSRF GitHub repo also - reading some of those may help you with your own solution.

ARCHITECTURE THOUGHTS

It is interesting looking at this, since I know nextjs is highly respected and enables better SEO etc. It also reminds me of older website technologies where developers often struggled, due to having to switch between client side and server side code. Being in control of data requests is an important technical foundation.

Out of interest, at Curity we have some code resources focused on SPA security, CDN deployment and developer experience, in case any of this is ever useful, for future reference. We do not use SSR currently, but we may want to say more about SSR use cases in future:

Upvotes: 1

Hughes
Hughes

Reputation: 424

You can add custom headers in a similar way you would by adding security headers, by using headers in your next.config.js:

// next.config.js

// You can choose which headers to add to the list
// after learning more below.
const securityHeaders = []

module.exports = {
  async headers() {
    return [
      {
        // Apply these headers to all routes in your application.
        source: '/:path*',
        headers: securityHeaders,
      },
    ]
  },
}

Upvotes: -1

Related Questions