From b030f839ee27bd0c741c615cc9a981b887d9964e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Huvar?= Date: Sun, 14 Jul 2019 16:22:37 +0200 Subject: [PATCH] Example for API routes with middleware --- examples/api-routes-middleware/README.md | 42 +++++++++++++++++++ examples/api-routes-middleware/package.json | 17 ++++++++ .../pages/api/cookies.js | 8 ++++ examples/api-routes-middleware/pages/index.js | 12 ++++++ .../api-routes-middleware/utils/cookies.js | 27 ++++++++++++ packages/next/README.md | 2 + 6 files changed, 108 insertions(+) create mode 100644 examples/api-routes-middleware/README.md create mode 100644 examples/api-routes-middleware/package.json create mode 100644 examples/api-routes-middleware/pages/api/cookies.js create mode 100644 examples/api-routes-middleware/pages/index.js create mode 100644 examples/api-routes-middleware/utils/cookies.js diff --git a/examples/api-routes-middleware/README.md b/examples/api-routes-middleware/README.md new file mode 100644 index 0000000000000..e46bc083eac56 --- /dev/null +++ b/examples/api-routes-middleware/README.md @@ -0,0 +1,42 @@ +# API routes with middleware + +## How to use + +### Using `create-next-app` + +Execute [`create-next-app`](https://github.com/segmentio/create-next-app) with [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) or [npx](https://github.com/zkat/npx#readme) to bootstrap the example: + +```bash +npx create-next-app --example api-routes-middleware api-routes-middleware-app +# or +yarn create next-app --example api-routes-middleware api-routes-middleware-app +``` + +### Download manually + +Download the example: + +```bash +curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/api-routes-middleware +cd api-routes-middleware +``` + +Install it and run: + +```bash +npm install +npm run dev +# or +yarn +yarn dev +``` + +Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download)) + +```bash +now +``` + +## The idea behind the example + +Next.js ships with [API routes](https://github.com/zeit/next.js#api-routes), which provide an easy solution to build your own `API`. This example shows how to implement simple `middleware` to wrap around your `API` endpoints. diff --git a/examples/api-routes-middleware/package.json b/examples/api-routes-middleware/package.json new file mode 100644 index 0000000000000..d817c48fa0cb9 --- /dev/null +++ b/examples/api-routes-middleware/package.json @@ -0,0 +1,17 @@ +{ + "name": "api-routes-middleware", + "version": "1.0.0", + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "cookie": "0.4.0", + "isomorphic-unfetch": "3.0.0", + "next": "latest", + "react": "^16.8.6", + "react-dom": "^16.8.6" + }, + "license": "ISC" +} diff --git a/examples/api-routes-middleware/pages/api/cookies.js b/examples/api-routes-middleware/pages/api/cookies.js new file mode 100644 index 0000000000000..d31fa9d36d01f --- /dev/null +++ b/examples/api-routes-middleware/pages/api/cookies.js @@ -0,0 +1,8 @@ +import cookies from '../../utils/cookies' + +const handler = (req, res) => { + res.cookie('Next.js', 'api-middleware!') + res.end('Hello Next.js middleware!') +} + +export default cookies(handler) diff --git a/examples/api-routes-middleware/pages/index.js b/examples/api-routes-middleware/pages/index.js new file mode 100644 index 0000000000000..2e7c283d6b728 --- /dev/null +++ b/examples/api-routes-middleware/pages/index.js @@ -0,0 +1,12 @@ +import fetch from 'isomorphic-unfetch' + +const Index = ({ cookie }) =>
{`Cookie from response: ${cookie}`}
+ +Index.getInitialProps = async () => { + const response = await fetch('http://localhost:3000/api/cookies') + const cookie = response.headers.get('set-cookie') + + return { cookie } +} + +export default Index diff --git a/examples/api-routes-middleware/utils/cookies.js b/examples/api-routes-middleware/utils/cookies.js new file mode 100644 index 0000000000000..6409c7361726e --- /dev/null +++ b/examples/api-routes-middleware/utils/cookies.js @@ -0,0 +1,27 @@ +import { serialize } from 'cookie' + +/** + * This sets `cookie` on `res` object + */ +const cookie = (res, name, value, options = {}) => { + const stringValue = + typeof value === 'object' ? 'j:' + JSON.stringify(value) : String(value) + + if ('maxAge' in options) { + options.expires = new Date(Date.now() + options.maxAge) + options.maxAge /= 1000 + } + + res.setHeader('Set-Cookie', serialize(name, String(stringValue), options)) +} + +/** + * Adds `cookie` function on `res.cookie` to set cookies for response + */ +const cookies = handler => (req, res) => { + res.cookie = (name, value, options) => cookie(res, name, value, options) + + return handler(req, res) +} + +export default cookies diff --git a/packages/next/README.md b/packages/next/README.md index 9ee058b7f0a65..ed738df9b9a2e 100644 --- a/packages/next/README.md +++ b/packages/next/README.md @@ -1060,6 +1060,8 @@ export default withRouter(MyLink)