Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add endpoint context API #1731

Merged
merged 15 commits into from
Oct 13, 2022
10 changes: 5 additions & 5 deletions src/pages/en/core-concepts/endpoints.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ In statically-generated sites, your custom endpoints are called at build time to
## Static File Endpoints
To create a custom endpoint, add a `.js` or `.ts` file to the `/pages` directory. The `.js` or `.ts` extension will be removed during the build process, so the name of the file should include the extension of the data you want to create. For example, `src/pages/data.json.ts` will build a `/data.json` endpoint.

Endpoints export a `get` function (optionally `async`) that receives an object with two properties (`params` and `request`) as its only argument. It returns an object with a `body`, and Astro will call this at build time and use the contents of the body to generate the file.
Endpoints export a `get` function (optionally `async`) that receives a [context object](/en/reference/api-reference/#endpoint-context) with properties similar to the `Astro` global. It returns an object with a `body`, and Astro will call this at build time and use the contents of the body to generate the file.

```js
// Example: src/pages/builtwith.json.ts
Expand Down Expand Up @@ -93,7 +93,7 @@ export const get: APIRoute = ({ params, request }) => {
```

## Server Endpoints (API Routes)
Everything described in the static file endpoints section can also be used in SSR mode: files can export a `get` function which receives an object with `params` and `request` properties.
Everything described in the static file endpoints section can also be used in SSR mode: files can export a `get` function which receives a [context object](/en/reference/api-reference/#endpoint-context) with properties similar to the `Astro` global.

But, unlike in `static` mode, when you configure `server` mode, the endpoints will be built when they are requested. This unlocks new features that are unavailable at build time, and allows you to build API routes that listen for requests and securely execute code on the server at runtime.

Expand Down Expand Up @@ -190,12 +190,12 @@ export const post: APIRoute = async ({ request }) => {
```

### Redirects
Since `Astro.redirect` is not available in API Routes you can use [`Response.redirect`](https://developer.mozilla.org/en-US/docs/Web/API/Response/redirect) to redirect:
The endpoint context exports a `redirect()` utility similar to `Astro.redirect`:

```js title="src/pages/links/[id].js" {14}
import { getLinkUrl } from '../db';

export async function get({ params }) {
export async function get({ params, redirect }) {
const { id } = params;
const link = await getLinkUrl(id);

Expand All @@ -206,7 +206,7 @@ export async function get({ params }) {
});
}

return Response.redirect(link, 307);
return redirect(link, 307);
}
```

Expand Down
143 changes: 143 additions & 0 deletions src/pages/en/reference/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,27 @@ import Heading from '../components/Heading.astro';

📚 Learn how to add [Typescript type definitions for your props](/en/guides/typescript/#component-props).

### `Astro.params`

`Astro.params` is an object passed from `getStaticPaths()` used to prerender [dynamic routes](/en/core-concepts/routing/#dynamic-routes).

```astro title="src/pages/posts/[id].astro"
---
export function getStaticPaths() {
return [
{ params: { id: '1' } },
{ params: { id: '2' } },
{ params: { id: '3' } }
];
}

const { id } = Astro.params;
---
<h1>{id}</h1>
```

See also: [`params`](#params)

### `Astro.request`

`Astro.request` is a standard [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. It can be used to get the `url`, `headers`, `method`, and even body of the request.
Expand Down Expand Up @@ -357,6 +378,126 @@ And would render HTML like this:
</ul>
```

## Endpoint Context

[Endpoint functions](/en/core-concepts/endpoints/) receive a context object as the first parameter. It mirrors many of the `Astro` global properties.

```ts title="endpoint.json.ts"
import { APIContext } from 'astro';

export function get(context: APIContext) {
// ...
}
```

### `context.params`

`context.params` is an object passed from `getStaticPaths()` used to prerender [dynamic routes](/en/core-concepts/routing/#dynamic-routes).

```ts title="src/pages/posts/[id].json.ts"
import { APIContext } from 'astro';

export function getStaticPaths() {
return [
{ params: { id: '1' } },
{ params: { id: '2' } },
{ params: { id: '3' } }
];
}

export function get({ params }: APIContext) {
return {
body: JSON.stringify({ id: params.id })
};
}
```

See also: [`params`](#params)

### `context.request`

A standard [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) object. It can be used to get the `url`, `headers`, `method`, and even body of the request.

```ts
import { APIContext } from 'astro';

export function get({ request }: APIContext) {
return {
body: `Hello ${request.url}`
}
}
```

See also: [Astro.request](#astrorequest)

### `context.cookies`

`context.cookies` contains utilities for reading and manipulating cookies.

See also: [Astro.cookies](#astrocookies)

### `context.url`

A [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) object constructed from the current `context.request.url` URL string value.

See also: [Astro.url](#astrourl)

### `context.clientAddress`

Specifies the [IP address](https://en.wikipedia.org/wiki/IP_address) of the request. This property is only available when building for SSR (server-side rendering) and should not be used for static sites.

```ts
import { APIContext } from 'astro';

export function get({ clientAddress }: APIContext) {
return {
body: `Your IP address is: ${clientAddress}`
}
}
```

See also: [Astro.clientAddress](#astroclientaddress)


### `context.site`

`context.site` returns a `URL` made from `site` in your Astro config. If undefined, this will return a URL generated from `localhost`.

See also: [Astro.site](#astrosite)

### `context.generator`

`context.generator` is a convenient way to add a [`<meta name="generator">`](https://html.spec.whatwg.org/multipage/semantics.html#meta-generator) tag with your current version of Astro. It follows the format `"Astro v1.x.x"`.

```ts
import { APIContext } from 'astro';

export function get({ generator }: APIContext) {
return new Redponse(JSON.stringify({
generator,
id: '1'
}), {
status: 200
});
}
```

See also: [Astro.generator](#astrogenerator)

### `context.redirect()`

`context.redirect()` returns a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) object that allows you to redirect to another page. This function is only available when building for SSR (server-side rendering) and should not be used for static sites.

```ts
import { APIContext } from 'astro';

export function get({ redirect }: APIContext) {
return redirect('/login', 302);
}
```

See also: [Astro.redirect](/en/guides/server-side-rendering/#astroredirect)

## `getStaticPaths()`

If a page uses dynamic params in the filename, that component will need to export a `getStaticPaths()` function.
Expand All @@ -379,6 +520,8 @@ export async function getStaticPaths() {

The `getStaticPaths()` function should return an array of objects to determine which paths will be pre-rendered by Astro.

It can also be used in [static file endpoints](/en/core-concepts/endpoints/#static-file-endpoints) and [server endpoints](/en/core-concepts/endpoints/#server-endpoints-api-routes) in `server` mode.

:::caution
The `getStaticPaths()` function executes in its own isolated scope once, before any page loads. Therefore you can't reference anything from its parent scope, other than file imports. The compiler will warn if you break this requirement.
:::
Expand Down