Skip to content

Commit

Permalink
Merge branch 'v3-upgrade-guide' into v3-recipes
Browse files Browse the repository at this point in the history
  • Loading branch information
yanthomasdev committed Aug 30, 2023
2 parents 1a45494 + 8d3db5f commit 44ea19b
Show file tree
Hide file tree
Showing 121 changed files with 3,149 additions and 1,735 deletions.
2 changes: 1 addition & 1 deletion src/content/docs/en/concepts/why-astro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ One of our favorite sayings is: **opt-in to complexity.** We designed Astro to r

**Astro is an all-in-one web framework that comes with everything you need to build a website.** Astro includes a component syntax, file-based routing, asset handling, a build process, bundling, optimizations, data-fetching, and more. You can build great websites without ever reaching outside of Astro's core feature set.

If you need more control, you can extend Astro with over [100+ integrations](https://astro.build/integrations/) like [React](https://www.npmjs.com/package/@astrojs/react), [Svelte](https://www.npmjs.com/package/@astrojs/svelte), [Vue](https://www.npmjs.com/package/@astrojs/vue), [Tailwind CSS](https://www.npmjs.com/package/@astrojs/tailwind), [MDX](https://www.npmjs.com/package/@astrojs/mdx), [image optimizations](https://www.npmjs.com/package/@astrojs/image), and more. [Connect your favorite CMS](/en/guides/cms/) or [deploy to your favorite host](/en/guides/deploy/) with just a single command.
If you need more control, you can extend Astro with over [100+ integrations](https://astro.build/integrations/) like [React](https://www.npmjs.com/package/@astrojs/react), [Svelte](https://www.npmjs.com/package/@astrojs/svelte), [Vue](https://www.npmjs.com/package/@astrojs/vue), [Tailwind CSS](https://www.npmjs.com/package/@astrojs/tailwind), [MDX](https://www.npmjs.com/package/@astrojs/mdx), and more. [Connect your favorite CMS](/en/guides/cms/) or [deploy to your favorite host](/en/guides/deploy/) with just a single command.

Astro is UI-agnostic, meaning you can **Bring Your Own UI Framework (BYOF)**. React, Preact, Solid, Svelte, Vue, and Lit are all officially supported in Astro. You can even mix and match different frameworks on the same page, making future migrations easier and preventing project lock-in to a single framework.
119 changes: 57 additions & 62 deletions src/content/docs/en/core-concepts/endpoints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,30 @@ Astro lets you create custom endpoints to serve any kind of data. You can use th
In statically-generated sites, your custom endpoints are called at build time to produce static files. If you opt in to [SSR](/en/guides/server-side-rendering/) mode, custom endpoints turn into live server endpoints that are called on request. Static and SSR endpoints are defined similarly, but SSR endpoints support additional features.

## 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 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.
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. Here, it returns an Response object with a `name` and `url`, and Astro will call this at build time and use the contents of the body to generate the file.

```ts
// Example: src/pages/builtwith.json.ts
// Outputs: /builtwith.json
export async function get({params, request}) {
return {
body: JSON.stringify({
export async function GET({params, request}) {
return new Response(
JSON.stringify({
name: 'Astro',
url: 'https://astro.build/',
}),
};
url: 'https://astro.build/'
})
)
}
```

The return object can also have an `encoding` property. It can be any valid [`BufferEncoding`](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/bdd02508ddb5eebcf701fdb8ffd6e84eabf47885/types/node/buffer.d.ts#L169) accepted by Node.js' `fs.writeFile` method. For example, to produce a binary png image:
Since Astro v3.0, the returned `Response` object doesn't have to include the `encoding` property anymore. For example, to produce a binary png image:

```ts title="src/pages/astro-logo.png.ts" {6}
export async function get({ params, request }) {
```ts title="src/pages/astro-logo.png.ts" {3}
export async function GET({ params, request }) {
const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
const buffer = Buffer.from(await response.arrayBuffer());
return {
body: buffer,
encoding: 'binary',
};
return new Response(await response.arrayBuffer());
}
```

Expand All @@ -45,8 +42,7 @@ You can also type your endpoint functions using the `APIRoute` type:
```ts
import type { APIRoute } from 'astro';

export const get: APIRoute = async ({ params, request }) => {
...
export const GET: APIRoute = async ({ params, request }) => {...}
```

### `params` and Dynamic routing
Expand All @@ -56,45 +52,47 @@ Endpoints support the same [dynamic routing](/en/core-concepts/routing/#dynamic-
```ts title="src/pages/api/[id].json.ts"
import type { APIRoute } from 'astro';

const usernames = ["Sarah", "Chris", "Dan"]
const usernames = ["Sarah", "Chris", "Yan", "Elian"]

export const get: APIRoute = ({ params, request }) => {
export const GET: APIRoute = ({ params, request }) => {
const id = params.id;
return {
body: JSON.stringify({
return new Response(
JSON.stringify({
name: usernames[id]
})
}
};
)
}

export function getStaticPaths () {
export function getStaticPaths() {
return [
{ params: { id: "0"} },
{ params: { id: "1"} },
{ params: { id: "2"} },
{ params: { id: "3"} }
]
}
```

This will generate three JSON endpoints at build time: `/api/0.json`, `/api/1.json`, `/api/2.json`. Dynamic routing with endpoints works the same as it does with pages, but because the endpoint is a function and not a component, [props](/en/reference/api-reference/#data-passing-with-props) aren't supported.
This will generate four JSON endpoints at build time: `/api/0.json`, `/api/1.json`, `/api/2.json` and `/api/3.json`. Dynamic routing with endpoints works the same as it does with pages, but because the endpoint is a function and not a component, [props](/en/reference/api-reference/#data-passing-with-props) aren't supported.

### `request`

All endpoints receive a `request` property, but in static mode, you only have access to `request.url`. This returns the full URL of the current endpoint and works the same as [Astro.request.url](/en/reference/api-reference/#astrorequest) does for pages.

```ts title="src/pages/request-path.json.ts"
import type { APIRoute } from 'astro';

export const get: APIRoute = ({ params, request }) => {
return {
body: JSON.stringify({
export const GET: APIRoute = ({ params, request }) => {
return new Response(JSON.stringify({
path: new URL(request.url).pathname
})
};
)
}
```

## 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 a [context object](/en/reference/api-reference/#endpoint-context) with properties similar to the `Astro` global.

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 All @@ -109,7 +107,7 @@ Server endpoints can access `params` without exporting `getStaticPaths`, and the
```js title="src/pages/[id].json.js"
import { getProduct } from '../db';

export async function get({ params }) {
export async function GET({ params }) {
const id = params.id;
const product = await getProduct(id);

Expand All @@ -120,12 +118,14 @@ export async function get({ params }) {
});
}

return new Response(JSON.stringify(product), {
status: 200,
headers: {
"Content-Type": "application/json"
return new Response(
JSON.stringify(product), {
status: 200,
headers: {
"Content-Type": "application/json"
}
}
});
);
}
```

Expand All @@ -134,7 +134,7 @@ This will respond to any request that matches the dynamic route. For example, if
In SSR mode, certain providers require the `Content-Type` header to return an image. In this case, use a `Response` object to specify a `headers` property. For example, to produce a binary `.png` image:

```ts title="src/pages/astro-logo.png.ts"
export async function get({ params, request }) {
export async function GET({ params, request }) {
const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
const buffer = Buffer.from(await response.arrayBuffer());
return new Response(buffer, {
Expand All @@ -144,55 +144,49 @@ export async function get({ params, request }) {
```

### HTTP methods
In addition to the `get` function, you can export a function with the name of any [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods). When a request comes in, Astro will check the method and call the corresponding function.

You can also export an `all` function to match any method that doesn't have a corresponding exported function. If there is a request with no matching method, it will redirect to your site's [404 page](/en/core-concepts/astro-pages/#custom-404-error-page).
In addition to the `GET` function, you can export a function with the name of any [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods). When a request comes in, Astro will check the method and call the corresponding function.

:::note
Since `delete` is a reserved word in JavaScript, export a `del` function to match the delete method.
:::
You can also export an `ALL` function to match any method that doesn't have a corresponding exported function. If there is a request with no matching method, it will redirect to your site's [404 page](/en/core-concepts/astro-pages/#custom-404-error-page).

```ts title="src/pages/methods.json.ts"
export const get: APIRoute = ({ params, request }) => {
return {
body: JSON.stringify({
export const GET: APIRoute = ({ params, request }) => {
return new Response(JSON.stringify({
message: "This was a GET!"
})
}
};
)
}

export const post: APIRoute = ({ request }) => {
return {
body: JSON.stringify({
export const POST: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: "This was a POST!"
})
}
)
}

export const del: APIRoute = ({ request }) => {
return {
body: JSON.stringify({
export const DELETE: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: "This was a DELETE!"
})
}
)
}

export const all: APIRoute = ({ request }) => {
return {
body: JSON.stringify({
export const ALL: APIRoute = ({ request }) => {
return new Resonse(JSON.stringify({
message: `This was a ${request.method}!`
})
}
)
}
```

<RecipeLinks slugs={["en/recipes/captcha", "en/recipes/build-forms-api" ]}/>

### `request`
### `request`

In SSR mode, the `request` property returns a fully usable [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object that refers to the current request. This allows you to accept data and check headers:

```ts title="src/pages/test-post.json.ts"
export const post: APIRoute = async ({ request }) => {
export const POST: APIRoute = async ({ request }) => {
if (request.headers.get("Content-Type") === "application/json") {
const body = await request.json();
const name = body.name;
Expand All @@ -207,12 +201,13 @@ export const post: APIRoute = async ({ request }) => {
```

### Redirects

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, redirect }) {
export async function GET({ params, redirect }) {
const { id } = params;
const link = await getLinkUrl(id);

Expand Down
4 changes: 0 additions & 4 deletions src/content/docs/en/core-concepts/project-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ Some files (like Astro components) are not even sent to the browser as written b
While this guide describes some popular conventions used in the Astro community, the only directories reserved by Astro are `src/pages/` and `src/content/`. You are free to rename and reorganize any other directories in a way that works best for you.
:::

### `src/assets`

The [`src/assets`](/en/guides/assets/) directory is the recommended folder to use for storing assets (e.g. images) that are processed by Astro. This is not required, and this is not a special reserved folder.

### `src/components`

**Components** are reusable units of code for your HTML pages. These could be [Astro components](/en/core-concepts/astro-components/), or [UI framework components](/en/core-concepts/framework-components/) like React or Vue. It is common to group and organize all of your project components together in this folder.
Expand Down
Loading

0 comments on commit 44ea19b

Please sign in to comment.