Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* feat(gatsby): first pass at API functions docs * Lots of docs tweaks most notably rename API Functions to just Functions * tweak * tweaks * add cors example to integration test * Just call it one thing * Update routing.md (cherry picked from commit 88ca620) Co-authored-by: Kyle Mathews <mathews.kyle@gmail.com>
- Loading branch information
1 parent
d54510f
commit 6a6f46b
Showing
7 changed files
with
250 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
--- | ||
title: Getting Started | ||
--- | ||
|
||
Gatsby Functions help you build [Express-like](https://expressjs.com/) backends without running servers. | ||
|
||
## Hello World | ||
|
||
JavaScript and Typescript files in `src/api/*` are mapped to function routes like files in `src/pages/*` become pages. | ||
|
||
For example, the following Function is run when you visit the URL `/api/hello-world` | ||
|
||
```js:title=src/api/hello-world.js | ||
export default function handler(req, res) { | ||
res.status(200).json({ hello: `world` }) | ||
} | ||
``` | ||
|
||
A Function file must export a single function that takes two parameters: | ||
|
||
- req: An instance of [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) with some [automatically parsed data](/docs/how-to/functions/getting-started/#common-data-formats-are-automatically-parsed) | ||
- res: An instance of [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) with some [helper functions](/docs/how-to/functions/middleware-and-helpers/#res-helpers) | ||
|
||
Dynamic routing is supported for creating REST-ful APIs and other uses cases | ||
|
||
- `/api/users` => `src/api/users/index.js` | ||
- `/api/users/23` => `src/api/users/[id].js` | ||
|
||
[Learn more about dynamic routes](/docs/how-to/functions/routing#dynamic-routing) | ||
|
||
## Typescript | ||
|
||
Functions can be written in JavaScript or Typescript. | ||
|
||
```ts:title=src/api/typescript.ts | ||
import { GatsbyFunctionRequest, GatsbyFunctionResponse } from "gatsby" | ||
|
||
export default function handler( | ||
req: GatsbyFunctionRequest, | ||
res: GatsbyFunctionResponse | ||
) { | ||
res.send(`I am TYPESCRIPT`) | ||
} | ||
``` | ||
|
||
## Common data formats are automatically parsed | ||
|
||
Query strings and common body content types are automatically parsed and available at `req.query` and `req.body` | ||
|
||
Read more about [supported data formats](/docs/how-to/functions/middleware-and-helpers). | ||
|
||
```js:title=src/api/contact-form.js | ||
export default function contactFormHandler(req, res) { | ||
// "req.body" contains the data from a contact form | ||
} | ||
``` | ||
|
||
## Respond to HTTP Methods | ||
|
||
Sometimes you want to respond differently to GETs vs. POSTs or only respond | ||
to one method. | ||
|
||
```js:title=src/api/method-example.js | ||
export default function handler(req, res) { | ||
if (req.method === `POST`) { | ||
res.send(`I am POST`) | ||
} else { | ||
// Handle other methods or return error | ||
} | ||
} | ||
``` | ||
|
||
## Environment variables | ||
|
||
Site [environment variables](/docs/how-to/local-development/environment-variables) are used to pass secrets and environment-specific configuration to Functions. | ||
|
||
```js:title=src/api/users/[id].js | ||
import fetch from "node-fetch" | ||
|
||
export default async function postNewPersonHandler(req, res) { | ||
// POST data to an authenticated API | ||
const url = "https://example.com/people" | ||
|
||
const headers = { | ||
"Content-Type": "application/json", | ||
Authorization: `Bearer ${process.env.CLIENT_TOKEN}`, | ||
} | ||
|
||
const data = { | ||
name: req.body.name, | ||
occupation: req.body.occupation, | ||
age: req.body.age, | ||
} | ||
|
||
try { | ||
const result = await fetch(url, { | ||
method: "POST", | ||
headers: headers, | ||
body: data, | ||
}).then(res => { | ||
return res.json() | ||
}) | ||
|
||
res.json(result) | ||
} catch (error) { | ||
res.status(500).send(error) | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
--- | ||
title: Middleware and Helpers | ||
--- | ||
|
||
Gatsby Functions provides an [Express-like](https://expressjs.com/) architecture that simplifies building | ||
Node.js APIs. We include a number of middlewares to parse common request data as well as response helpers. | ||
|
||
## Data formats | ||
|
||
We parse commonly used data types. Available on the `req` object: | ||
|
||
- Cookies at `req.cookies` | ||
- URL Queries (e.g. `api/foo?query=foo`) at `req.query` | ||
- Form parameters and data at `req.body` | ||
- JSON POST bodies at `req.body` | ||
|
||
## Response helpers | ||
|
||
- `res.send(body)` — returns the response. The `body` can be a `string`, `object`, or `buffer` | ||
- `res.json(body)` — returns a JSON response. The `body` can be any value that can be seralized with `JSON.stringify()` | ||
- `res.status(statusCode)` — set the [HTTP status](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) for the response. Defaults to `200`. | ||
- `res.redirect([statusCode], url)` — Returns a redirect to a URL. Optionally set the statusCode which defaults to `302`. | ||
|
||
## Custom middleware | ||
|
||
Custom Connect/Express middleware are supported. | ||
|
||
An example of how to add CORS support to route: | ||
|
||
```js:title=src/api/cors.js | ||
import Cors from "cors" | ||
|
||
const cors = Cors() | ||
|
||
export default async function corsHandler(req, res) { | ||
// Run Cors middleware and handle errors. | ||
await new Promise((resolve, reject) => { | ||
cors(req, res, result => { | ||
if (result instanceof Error) { | ||
reject(result) | ||
} | ||
|
||
resolve(result) | ||
}) | ||
}) | ||
|
||
res.json(`Hi from Gatsby Functions`) | ||
} | ||
``` | ||
|
||
## Custom body parsing | ||
|
||
This is not yet supported. [Add a comment in the discussion if this is an | ||
important use case for you](https://github.com/gatsbyjs/gatsby/discussions/30735). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
--- | ||
title: Routing | ||
--- | ||
|
||
Function routing shares the same syntax as [page routing](/docs/reference/routing/file-system-route-api/). | ||
|
||
## Static Routing | ||
|
||
Both top-level and nested routes are supported. | ||
|
||
- `src/api/top-level.js` => `/api/top-level` | ||
- `src/api/directory/foo.js` => `/api/directory/foo` | ||
|
||
`index.js` files are routed at their directory path e.g. `src/api/users/index.js` => `/api/users` | ||
|
||
## Dynamic Routing | ||
|
||
_Note: Dynamic Routing is not yet supported on Gatsby Cloud. Expect it in another few weeks. It will work locally._ | ||
|
||
### Param routes | ||
|
||
Use square brackets (`[ ]`) in the file path to mark dynamic segments of the URL. | ||
|
||
So to create an Function for fetching user information by `userId`: | ||
|
||
```js:title=src/api/users/[id].js | ||
export default async function handler(req, res) { | ||
const userId = req.params.id | ||
|
||
// Fetch user | ||
const user = await getUser(userId) | ||
|
||
res.json(user) | ||
} | ||
``` | ||
|
||
Dynamic routes share syntax with [client-only routes](/docs/reference/routing/file-system-route-api/#creating-client-only-routes). | ||
|
||
### Splat routes | ||
|
||
Gatsby also supports splat (or wildcard) routes, which are routes that will match anything after the splat. These are less common, but still have use cases. | ||
|
||
```js:title=src/api/foo/[...].js | ||
export default function handler(req, res) { | ||
const params = req.params[`0`].split(`/`) | ||
|
||
// `src/api/foo/1/2 // params[0] === `1` | ||
// params[1] === `2` | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import Cors from "cors" | ||
|
||
const cors = Cors() | ||
|
||
export default async function corsHandler(req, res) { | ||
// Run Cors middleware and handle errors. | ||
await new Promise((resolve, reject) => { | ||
cors(req, res, result => { | ||
if (result instanceof Error) { | ||
reject(result) | ||
} | ||
|
||
resolve(result) | ||
}) | ||
}) | ||
|
||
res.json(`Hi from Gatsby Functions`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters