Установите файл cookie запроса в промежуточном программном обеспечении NextJS v14

Я хочу установить/обновить файл cookie для входящего запроса в файле промежуточного программного обеспечения до того, как страница или макет прочитает файл cookie, но, похоже, он не работает. Возможно, это невозможно..

Я сделал демо-проект, который вы можете клонировать с github: https://github.com/TJBlackman/nextjs-middleware-set-cookies-test

// middleware.ts
import type { NextRequest } from "next/server";

export async function middleware(request: NextRequest) {
  console.info(`running middleware....`, request.method, request.url);
  request.cookies.set("x-middleware-test", "some test value?!"); // <- this line should set a cookie that can be read by layout/page??
}
// layout.tsx
import { cookies } from "next/headers";

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const cookieStore = cookies();
  const testCookie = cookieStore.get("x-middleware-test");

  return (
    <html lang = "en">
      <body>
        <h1>Layout cookie: {testCookie?.value || "Not Found"}</h1>
        {children}
      </body>
    </html>
  );
}
// page.tsx
import { cookies } from "next/headers";

export default function Home() {
  const cookieStore = cookies();
  const testCookie = cookieStore.get("x-middleware-test");
  return (
    <main>
      <h2>Page cookie: {testCookie?.value || "Not Found"}</h2>
    </main>
  );
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
165
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Проблема в том, что вам следует использовать NextResponseNextRequest предназначен только для чтения и является входящим запросом, а ответ — это то, что отправляется дальше.

Так

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  console.info(`running middleware....`, request.method, request.url);

  const response = NextResponse.next();
  response.cookies.set("x-middleware-test", "some test value?!");

  return response;
}

Избавление от асинхронности — хорошая идея, если только вам не нужно чего-то ждать в промежуточном программном обеспечении.

Обработка на стороне клиента

 useEffect(() => {
    if (!Cookies.get('x-middleware-test')) {
      Cookies.set('x-middleware-test', 'some test value?!');
    }

Если значения файлов cookie должны быть безопасными, используйте вместо них RSC.

Дополнительная информация — https://nextjs.org/docs/app/building-your-application/routing/middleware#using-cookies

Это не работает. При рендеринге начальной страницы файл cookie все еще не читается. При этом в ответ клиенту (браузеру) устанавливается файл cookie, который сохраняет файлы cookie и включает их при будущих загрузках страниц, но при самой первой загрузке страницы он все еще недоступен.

TJBlackman 13.06.2024 03:35

Вы правы, но обрабатывается через эффект на стороне клиента if (!Cookies.get('x-middleware-test')) { Cookies.set('x-middleware-test', 'какое-то тестовое значение?!'); } Если значение файла cookie не должно раскрываться клиенту, используйте RSC nextjs.org/docs/app/building-your-application/rendering/…

Ramakay 13.06.2024 18:22
Ответ принят как подходящий

У меня это сработало в NextJS v14.2.4:

export async function middleware(request: NextRequest) {
  request.cookies.set("x-middleware-test", "some test value?!");

  return NextResponse.next({
    request, // <- overwrite the request object!! yay! :D
  });
}

Я обновил репозиторий примера, чтобы продемонстрировать эту работу. Документация NextJS довольно неясна, по моему мнению...

Обновлено: Еще немного информации: вам нужно установить файлы cookie запроса ПЕРЕД передачей объекта запроса методу NextResponse.next(). Например, это НЕ будет работать...

// example of what does NOT work!!
export async function middleware(request: NextRequest) {
  const request = NextResponse.next({
    request, // set this object as it is NOW, not including future changes
  });

  request.cookies.set("x-middleware-test", "some test value?!");

  return response; // won't include set-cookie changes :(
}

NextRequest основан на спецификации API веб-запросов (Developer.mozilla.org/en-US/docs/Web/API/Request), где подобъекты запроса доступны только для чтения, и обычно перезапись считается антишаблоном, но если простая вещь, и вы хотите, чтобы все объекты запроса имели этот файл cookie, тогда это может быть нормально, пока Next не сделает его доступным только для чтения.

Ramakay 13.06.2024 18:48

Если бы NextJS реализовал реальное промежуточное программное обеспечение (например, express, fastify, sveltekit и т. д.), то все было бы хорошо, но они реализуют промежуточное программное обеспечение как полностью изолированную функцию (тупую). Вариант использования — когда запрос имеет действительный RefreshToken, и я хочу использовать его для получения/установки нового действительного токена доступа на оставшуюся часть срока действия запроса.

TJBlackman 13.06.2024 21:33

Другие вопросы по теме