Pourya Tak
Pourya Tak

Reputation: 96

URL-Encoding Issue When Storing Stringified Objects in Cookies in Next.js Middleware (v13.4)

I'm trying to save a stringified object in cookies within a middleware, but the value is being URL-encoded. For example, {name:123} turns into: %7Bname%3A123%7D.

I don't encounter any issues when saving objects in the client, as they are saved as strings without any problems. I'm using Nextjs version 13.4 app-router.

Here is my middleware.ts:

import { NextRequest, NextResponse } from "next/server"
import { getSettings } from "@/functions/api/settings"

const fetchSettings = async () => {
    const response = await getSettings()
    if (response) {
        const nextResponse = NextResponse.next()
        const settings = {
            lang: response.lang,
            calender: response.calender,
            currency: response.currency,
        }
        nextResponse.cookies.set("settings", JSON.stringify(settings))
        return nextResponse
    }
}

export async function middleware(request: NextRequest) {
    const hasSettings = request.cookies.has("settings")
    if (hasSettings) {
        return NextResponse.next()
    }
    return await fetchSettings()
}

export const config = {
    matcher: ["/((?!api|_next/static|_next/image|favicon.ico|manifest.json).*)"],
}

Upvotes: 0

Views: 267

Answers (1)

jufergom
jufergom

Reputation: 1

It seems that by default, the ResponseCookie class creates cookies applying an encoding to the cookie value, and this class do not expose the encode option to prevent this behavior. The ResponseCookie definition is this one.

type ResponseCookie = CookieListItem & Pick<CookieSerializeOptions, 'httpOnly' | 'maxAge' | 'priority'>;

With the encode option available, we might be able to do something like this to prevent the encoding.

cookies().set({
    name: 'name',
    value: 'lee',
    httpOnly: true,
    path: '/',
    encode: v => v,
  })

Unfortunately, this is not possible because the encoding option cannot be used from the ResponseCookie class.

There is an open issue on Next.js GitHub repository requesting to include this option in the ResponseCookie class.

In this same GitHub issue, one of the answers mentions that he was able to work around this issue by manually appending the Set-Cookie header instead of using response.cookies.set(). So in the meantime, we can solve this problem by doing something like this.

nextResponse.headers.append(
          "Set-Cookie",
          `${cookie.name}=${cookie.value}; Path=/; HttpOnly; Secure; SameSite=None;`,
        );

Upvotes: 0

Related Questions