Skip to content

Commit

Permalink
feat: add cookies instance to the context (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
smeijer authored Oct 7, 2021
1 parent 87e2104 commit 7bb5e01
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 10 deletions.
27 changes: 25 additions & 2 deletions docs/content/api/cookies.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 6 additions & 5 deletions src/__utils__/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, string>;
Expand All @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions src/responses.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' });
});
8 changes: 5 additions & 3 deletions src/runtime/cookies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import Cookies from 'cookies';
import { GetServerSidePropsContext } from '../types/next';

export type CookieJar = {
cookies: InstanceType<typeof Cookies>;
req: { getCookie: InstanceType<typeof Cookies>['get'] };
res: { setCookie: InstanceType<typeof Cookies>['set'] };
};

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);
}

0 comments on commit 7bb5e01

Please sign in to comment.