Я хочу установить/обновить файл 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>
);
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Проблема в том, что вам следует использовать NextResponse — NextRequest предназначен только для чтения и является входящим запросом, а ответ — это то, что отправляется дальше.
Так
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
Вы правы, но обрабатывается через эффект на стороне клиента if (!Cookies.get('x-middleware-test')) { Cookies.set('x-middleware-test', 'какое-то тестовое значение?!'); } Если значение файла cookie не должно раскрываться клиенту, используйте RSC nextjs.org/docs/app/building-your-application/rendering/…
У меня это сработало в 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 не сделает его доступным только для чтения.
Если бы NextJS реализовал реальное промежуточное программное обеспечение (например, express, fastify, sveltekit и т. д.), то все было бы хорошо, но они реализуют промежуточное программное обеспечение как полностью изолированную функцию (тупую). Вариант использования — когда запрос имеет действительный RefreshToken, и я хочу использовать его для получения/установки нового действительного токена доступа на оставшуюся часть срока действия запроса.
Это не работает. При рендеринге начальной страницы файл cookie все еще не читается. При этом в ответ клиенту (браузеру) устанавливается файл cookie, который сохраняет файлы cookie и включает их при будущих загрузках страниц, но при самой первой загрузке страницы он все еще недоступен.