maticzav / nookies

🍪 A set of cookie helpers for Next.js
2.26k stars 76 forks source link

How to use "parseCookies" function inside _.middleware.ts page in NextJS? #561

Open Harukisatoh opened 2 years ago

Harukisatoh commented 2 years ago

Hey, I'm running into some trouble trying to figure out how to use nookies inside a NextJS middleware. Inside of it, I have no access to the request context, but the function is still executed on the server-side. My code looks something like this:

// _middleware.ts
import { NextResponse } from 'next/server'
import { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {

  const { myCookie } = parseCookies(request); // This gives me a typescript error

  const response = NextResponse.next();
  return response
}

How can I get my cookie inside of the middleware function?

trungthecelestial commented 1 year ago

any update on this question?

Harukisatoh commented 1 year ago

any update on this question?

Unfortunately no, as for my case middlewares weren't really needed, I just stopped using them. But if you find a way to solve this problem, please let me know.

bombillazo commented 1 year ago

@maticzav If I work on a PR to add nookies support for pages middleware, is that something that can be merged into the library?

Also, a note in the repo README specifying that nookies does not work in middleware would be helpful for devs to know.

aamir-mns commented 1 year ago

Any update on this? At the moment we have to add some custom solutions like this.

import type { CookieParseOptions } from 'cookie';
import type { NextRequest } from 'next/server';
import nookies from 'nookies';

import { getCookieNameByPrefix } from './cookie-helpers';

type Ctx = Parameters<typeof nookies.get>[0];
type CtxWithNextRequest = Pick<NonNullable<{ req: NextRequest } | Ctx>, 'req'>;

const isNextJsMiddlewareReq = (
  req: CtxWithNextRequest['req']
): req is NextRequest =>
  Boolean(req && 'cookies' in req && 'getAll' in req.cookies);

const getCookiesListFromMiddlewareReq = (req: CtxWithNextRequest['req']) => {
  if (!isNextJsMiddlewareReq(req)) {
    return;
  }

  const cookies = req?.cookies?.getAll().reduce(
    (result: Parameters<typeof getCookieNameByPrefix>[0], { name, value }) => ({
      ...result,
      [name]: value,
    }),
    {}
  );

  return cookies;
};

export const getServerCookie = (
  cookieNamePrefix: string,
  ctx: CtxWithNextRequest,
  options: CookieParseOptions
) => {
  const cookiesToUse =
    getCookiesListFromMiddlewareReq(ctx.req) ||
    nookies.get(ctx as Ctx, options);

  const cookieName = getCookieNameByPrefix(cookiesToUse, cookieNamePrefix);

  return cookieName && cookiesToUse[cookieName];
};