diff --git a/docs/content/api/cookies.mdx b/docs/content/api/cookies.mdx index c774d40..3cdd6aa 100644 --- a/docs/content/api/cookies.mdx +++ b/docs/content/api/cookies.mdx @@ -2,8 +2,31 @@ title: Cookies --- -We extend the request and response objects with cookie handlers using -[`cookies`](https://www.npmjs.com/package/cookies). +We've added the [`cookies`](https://npmjs.com/cookies) instance to the +`GetServerSidePropsContext`, and also extended the request and response objects +with cookie handlers. Which one to choose depends on your personal style +preference. They offer the same functionality. + +## context.cookies + +The simplest way to use cookies, is probably via the `context.cookies` +namespace. + +```js +export const getServerSideProps = handle({ + async get({ cookies }) { + const session = cookies.get('session'); + cookies.set('session', Date.now(), { expires: 300 }); + }, +}); +``` + +See +[pillarjs/cookies](https://github.com/pillarjs/cookies/tree/d2111627e8ff2e29f90e75d1f1cc4164c5a07a3f#api) +for more options. + +Alternatively, you might want to use the `getCookie` and `setCookie` helpers on +the request and response properties. ## req.getCookie diff --git a/src/__utils__/server.ts b/src/__utils__/server.ts index 4bb9f97..e9d7a94 100644 --- a/src/__utils__/server.ts +++ b/src/__utils__/server.ts @@ -6,8 +6,6 @@ import nodeFetch from 'node-fetch'; import listen from 'test-listen'; import { parse as parseUrl } from 'url'; -const fetcher = fetchCookie(nodeFetch); - type RequestOptions = { method?: string; headers?: Record; @@ -24,15 +22,18 @@ async function request( body = undefined, }: RequestOptions = {}, ) { + const cookie = Object.entries(cookies) + .map(([key, value]) => `${key}=${value}`) + .join(';'); + + const fetcher = fetchCookie(nodeFetch); const response = await fetcher(url, { method, headers: { // default to json, as that works easiest in tests 'content-type': 'application/json', accept: 'application/json', - cookie: Object.entries(cookies) - .map(([key, value]) => `${key}=${value}`) - .join('; '), + cookie, ...headers, }, body: diff --git a/src/responses.test.ts b/src/responses.test.ts index c6b7bbd..f7c4c70 100644 --- a/src/responses.test.ts +++ b/src/responses.test.ts @@ -120,3 +120,21 @@ test('can set response cookies', async () => { 'session=two; path=/; httponly', ); }); + +test('can handle cookies via context', async () => { + const fetch = await next( + handle({ + async get({ cookies }) { + return json({ cookie: String(Number(cookies.get('count')) + 2) }); + }, + }), + ); + + const response = await fetch('/', { + cookies: { + count: '2', + }, + }); + + expect(response.body).toEqual({ cookie: '4' }); +}); diff --git a/src/runtime/cookies.ts b/src/runtime/cookies.ts index 0342424..aff83cc 100644 --- a/src/runtime/cookies.ts +++ b/src/runtime/cookies.ts @@ -3,6 +3,7 @@ import Cookies from 'cookies'; import { GetServerSidePropsContext } from '../types/next'; export type CookieJar = { + cookies: InstanceType; req: { getCookie: InstanceType['get'] }; res: { setCookie: InstanceType['set'] }; }; @@ -10,7 +11,8 @@ export type CookieJar = { export function bindCookieJar( context: GetServerSidePropsContext, ): asserts context is GetServerSidePropsContext & CookieJar { - const cookies = new Cookies(context.req, context.res); - (context.req as any).getCookie = cookies.get.bind(cookies); - (context.res as any).setCookie = cookies.set.bind(cookies); + const ctx = context as GetServerSidePropsContext & CookieJar; + ctx.cookies = new Cookies(ctx.req, ctx.res); + ctx.req.getCookie = ctx.cookies.get.bind(ctx.cookies); + ctx.res.setCookie = ctx.cookies.set.bind(ctx.cookies); }