UNPKG

next

Version:

The React Framework

117 lines (116 loc) 5.73 kB
import { FLIGHT_HEADERS } from '../../client/components/app-router-headers'; import { HeadersAdapter } from '../web/spec-extension/adapters/headers'; import { MutableRequestCookiesAdapter, RequestCookiesAdapter, responseCookiesToRequestCookies, wrapWithMutableAccessCheck } from '../web/spec-extension/adapters/request-cookies'; import { ResponseCookies, RequestCookies } from '../web/spec-extension/cookies'; import { DraftModeProvider } from './draft-mode-provider'; import { splitCookiesString } from '../web/utils'; function getHeaders(headers) { const cleaned = HeadersAdapter.from(headers); for (const header of FLIGHT_HEADERS){ cleaned.delete(header.toLowerCase()); } return HeadersAdapter.seal(cleaned); } function getMutableCookies(headers, onUpdateCookies) { const cookies = new RequestCookies(HeadersAdapter.from(headers)); return MutableRequestCookiesAdapter.wrap(cookies, onUpdateCookies); } /** * If middleware set cookies in this request (indicated by `x-middleware-set-cookie`), * then merge those into the existing cookie object, so that when `cookies()` is accessed * it's able to read the newly set cookies. */ function mergeMiddlewareCookies(req, existingCookies) { if ('x-middleware-set-cookie' in req.headers && typeof req.headers['x-middleware-set-cookie'] === 'string') { const setCookieValue = req.headers['x-middleware-set-cookie']; const responseHeaders = new Headers(); for (const cookie of splitCookiesString(setCookieValue)){ responseHeaders.append('set-cookie', cookie); } const responseCookies = new ResponseCookies(responseHeaders); // Transfer cookies from ResponseCookies to RequestCookies for (const cookie of responseCookies.getAll()){ existingCookies.set(cookie); } } } export function createRequestStoreForRender(req, res, url, rootParams, implicitTags, onUpdateCookies, previewProps, isHmrRefresh, serverComponentsHmrCache, renderResumeDataCache) { return createRequestStoreImpl(// Pages start in render phase by default 'render', req, res, url, rootParams, implicitTags, onUpdateCookies, renderResumeDataCache, previewProps, isHmrRefresh, serverComponentsHmrCache); } export function createRequestStoreForAPI(req, url, implicitTags, onUpdateCookies, previewProps) { return createRequestStoreImpl(// API routes start in action phase by default 'action', req, undefined, url, {}, implicitTags, onUpdateCookies, undefined, previewProps, false, undefined); } function createRequestStoreImpl(phase, req, res, url, rootParams, implicitTags, onUpdateCookies, renderResumeDataCache, previewProps, isHmrRefresh, serverComponentsHmrCache) { function defaultOnUpdateCookies(cookies) { if (res) { res.setHeader('Set-Cookie', cookies); } } const cache = {}; return { type: 'request', phase, implicitTags, // Rather than just using the whole `url` here, we pull the parts we want // to ensure we don't use parts of the URL that we shouldn't. This also // lets us avoid requiring an empty string for `search` in the type. url: { pathname: url.pathname, search: url.search ?? '' }, rootParams, get headers () { if (!cache.headers) { // Seal the headers object that'll freeze out any methods that could // mutate the underlying data. cache.headers = getHeaders(req.headers); } return cache.headers; }, get cookies () { if (!cache.cookies) { // if middleware is setting cookie(s), then include those in // the initial cached cookies so they can be read in render const requestCookies = new RequestCookies(HeadersAdapter.from(req.headers)); mergeMiddlewareCookies(req, requestCookies); // Seal the cookies object that'll freeze out any methods that could // mutate the underlying data. cache.cookies = RequestCookiesAdapter.seal(requestCookies); } return cache.cookies; }, set cookies (value){ cache.cookies = value; }, get mutableCookies () { if (!cache.mutableCookies) { const mutableCookies = getMutableCookies(req.headers, onUpdateCookies || (res ? defaultOnUpdateCookies : undefined)); mergeMiddlewareCookies(req, mutableCookies); cache.mutableCookies = mutableCookies; } return cache.mutableCookies; }, get userspaceMutableCookies () { if (!cache.userspaceMutableCookies) { const userspaceMutableCookies = wrapWithMutableAccessCheck(this.mutableCookies); cache.userspaceMutableCookies = userspaceMutableCookies; } return cache.userspaceMutableCookies; }, get draftMode () { if (!cache.draftMode) { cache.draftMode = new DraftModeProvider(previewProps, req, this.cookies, this.mutableCookies); } return cache.draftMode; }, renderResumeDataCache: renderResumeDataCache ?? null, isHmrRefresh, serverComponentsHmrCache: serverComponentsHmrCache || globalThis.__serverComponentsHmrCache }; } export function synchronizeMutableCookies(store) { // TODO: does this need to update headers as well? store.cookies = RequestCookiesAdapter.seal(responseCookiesToRequestCookies(store.mutableCookies)); } //# sourceMappingURL=request-store.js.map