From f635bdd6e74ce2eb3c254d9cdb2df4655865ae13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Huvar?= Date: Thu, 25 Jul 2019 16:39:27 +0200 Subject: [PATCH 1/4] HTTP methods docs and REST example --- examples/api-routes-rest/README.md | 42 +++++++++++++++++++ examples/api-routes-rest/package.json | 16 +++++++ .../api-routes-rest/pages/api/user/[id].js | 19 +++++++++ examples/api-routes-rest/pages/api/users.js | 13 ++++++ examples/api-routes-rest/pages/index.js | 23 ++++++++++ examples/api-routes-rest/pages/user/[id].js | 12 ++++++ packages/next/README.md | 13 ++++++ 7 files changed, 138 insertions(+) create mode 100644 examples/api-routes-rest/README.md create mode 100644 examples/api-routes-rest/package.json create mode 100644 examples/api-routes-rest/pages/api/user/[id].js create mode 100644 examples/api-routes-rest/pages/api/users.js create mode 100644 examples/api-routes-rest/pages/index.js create mode 100644 examples/api-routes-rest/pages/user/[id].js diff --git a/examples/api-routes-rest/README.md b/examples/api-routes-rest/README.md new file mode 100644 index 00000000000000..98e3d1d8c31ffa --- /dev/null +++ b/examples/api-routes-rest/README.md @@ -0,0 +1,42 @@ +# API routes with REST + +## 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-rest api-routes-rest-app +# or +yarn create next-app --example api-routes-rest api-routes-rest-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-rest +cd api-routes-rest +``` + +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 it can be used to create your [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) api. diff --git a/examples/api-routes-rest/package.json b/examples/api-routes-rest/package.json new file mode 100644 index 00000000000000..581d565303a4fb --- /dev/null +++ b/examples/api-routes-rest/package.json @@ -0,0 +1,16 @@ +{ + "name": "api-routes-rest", + "version": "1.0.0", + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "isomorphic-unfetch": "3.0.0", + "next": "latest", + "react": "^16.8.6", + "react-dom": "^16.8.6" + }, + "license": "ISC" +} diff --git a/examples/api-routes-rest/pages/api/user/[id].js b/examples/api-routes-rest/pages/api/user/[id].js new file mode 100644 index 00000000000000..5fbedffbcba454 --- /dev/null +++ b/examples/api-routes-rest/pages/api/user/[id].js @@ -0,0 +1,19 @@ +export default (req, res) => { + const { + query: { id, name }, + method, + } = req + + switch (method) { + case 'GET': + // Get data from your database + res.status(200).json({ id, name: `User ${id}` }) + break + case 'PUT': + // Update or create data in your database + res.status(200).json({ id, name: name ? name : `User ${id}` }) + default: + res.setHeader('Allow', ['GET', 'PUT']) + res.status(405).end(`Method ${method} Not Allowed`) + } +} diff --git a/examples/api-routes-rest/pages/api/users.js b/examples/api-routes-rest/pages/api/users.js new file mode 100644 index 00000000000000..f7714a89f219dd --- /dev/null +++ b/examples/api-routes-rest/pages/api/users.js @@ -0,0 +1,13 @@ +// Fake users data +const users = [ + { + id: 1 + }, + { id: 2 }, + { id: 3 } +] + +export default (req, res) => { + // Get data from your database + res.status(200).json(users) +} diff --git a/examples/api-routes-rest/pages/index.js b/examples/api-routes-rest/pages/index.js new file mode 100644 index 00000000000000..e7e53d1cafa39b --- /dev/null +++ b/examples/api-routes-rest/pages/index.js @@ -0,0 +1,23 @@ +import fetch from 'isomorphic-unfetch' +import Link from 'next/link' + +const Index = ({ users }) => ( + +) + +Index.getInitialProps = async () => { + const response = await fetch('http://localhost:3000/api/users') + const users = await response.json() + + return { users } +} + +export default Index diff --git a/examples/api-routes-rest/pages/user/[id].js b/examples/api-routes-rest/pages/user/[id].js new file mode 100644 index 00000000000000..5a52a78e6ac2ac --- /dev/null +++ b/examples/api-routes-rest/pages/user/[id].js @@ -0,0 +1,12 @@ +import fetch from 'isomorphic-unfetch' + +const User = ({ user }) =>
{user.name}
+ +User.getInitialProps = async ({ query: { id } }, res) => { + const response = await fetch(`http://localhost:3000/api/user/${id}`) + const user = await response.json() + + return { user } +} + +export default User diff --git a/packages/next/README.md b/packages/next/README.md index 4b3896952059dc..607fa650a09c4f 100644 --- a/packages/next/README.md +++ b/packages/next/README.md @@ -1041,6 +1041,7 @@ export default withRouter(MyLink)
  • API routes with micro
  • API routes with middleware
  • API routes with GraphQL server
  • +
  • API routes with REST
  • @@ -1064,6 +1065,18 @@ export default (req, res) => { - `res` refers to [NextApiResponse](https://github.com/zeit/next.js/blob/v9.0.0/packages/next-server/lib/utils.ts#L168-L178) which extends [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) +To handle different HTTP methods with your api calls you can handle it by `req.method` in your resolver function: + +```js +export default (req, res) => { + if (req.method === 'POST') { + // Process your POST request + } else { + // Handle the rest of your HTTP methods + } +} +``` + > **Note**: API Routes [do not specify CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), so they'll be **same-origin only** by default. > You can customize this behavior by wrapping your export with CORS middleware. > We provide an [example of this below](#api-middlewares). From fa1c535357cbaf26c295e83cec752c2f4763982e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Huvar?= Date: Thu, 25 Jul 2019 16:48:32 +0200 Subject: [PATCH 2/4] Update packages/next/README.md Co-Authored-By: Joe Haddad --- packages/next/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/next/README.md b/packages/next/README.md index 607fa650a09c4f..d9f96f6186b2bc 100644 --- a/packages/next/README.md +++ b/packages/next/README.md @@ -1065,7 +1065,7 @@ export default (req, res) => { - `res` refers to [NextApiResponse](https://github.com/zeit/next.js/blob/v9.0.0/packages/next-server/lib/utils.ts#L168-L178) which extends [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) -To handle different HTTP methods with your api calls you can handle it by `req.method` in your resolver function: +To handle different HTTP methods for API calls you can access `req.method` in your resolver function: ```js export default (req, res) => { From f5234cfccf9b12cea5a3bbd00f3e425e5f465d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Huvar?= Date: Thu, 25 Jul 2019 16:48:40 +0200 Subject: [PATCH 3/4] Update examples/api-routes-rest/README.md Co-Authored-By: Joe Haddad --- examples/api-routes-rest/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/api-routes-rest/README.md b/examples/api-routes-rest/README.md index 98e3d1d8c31ffa..6e3c1644a8a356 100644 --- a/examples/api-routes-rest/README.md +++ b/examples/api-routes-rest/README.md @@ -4,7 +4,7 @@ ### 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: +Execute [`create-next-app`](https://www.npmjs.com/package/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-rest api-routes-rest-app From 282eb8afeff0c5c59111e50fbadfd0d804dee357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Huvar?= Date: Thu, 25 Jul 2019 16:55:49 +0200 Subject: [PATCH 4/4] Fix standard --- examples/api-routes-rest/README.md | 19 +------------------ .../api-routes-rest/pages/api/user/[id].js | 5 +++-- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/examples/api-routes-rest/README.md b/examples/api-routes-rest/README.md index 6e3c1644a8a356..adfe929a0aecdc 100644 --- a/examples/api-routes-rest/README.md +++ b/examples/api-routes-rest/README.md @@ -12,24 +12,7 @@ npx create-next-app --example api-routes-rest api-routes-rest-app yarn create next-app --example api-routes-rest api-routes-rest-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-rest -cd api-routes-rest -``` - -Install it and run: - -```bash -npm install -npm run dev -# or -yarn -yarn dev -``` +### Deploy to Now Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download)) diff --git a/examples/api-routes-rest/pages/api/user/[id].js b/examples/api-routes-rest/pages/api/user/[id].js index 5fbedffbcba454..e06b755e4efe49 100644 --- a/examples/api-routes-rest/pages/api/user/[id].js +++ b/examples/api-routes-rest/pages/api/user/[id].js @@ -1,7 +1,7 @@ export default (req, res) => { const { query: { id, name }, - method, + method } = req switch (method) { @@ -11,7 +11,8 @@ export default (req, res) => { break case 'PUT': // Update or create data in your database - res.status(200).json({ id, name: name ? name : `User ${id}` }) + res.status(200).json({ id, name: name || `User ${id}` }) + break default: res.setHeader('Allow', ['GET', 'PUT']) res.status(405).end(`Method ${method} Not Allowed`)