Pular para o conteúdo

Endpoints

O Astro permite que você crie endpoints customizados para servir e processar todo tipo de dados. Isso pode ser usado para gerar imagens, expor um arquivo RSS ou os usar como rotas de API para construir uma API completa para o seu site.

Em sites gerados de forma estática, seus endpoints customizados são chamados durante a fase de build para produzir arquivos estáticos. Já em sites usando o modo SSR seus endpoints customizados se tornarão endpoints reais executados a cada requisição. Endpoints estáticos e SSR são definidos de maneira similar, mas os endpoints SSR suportam funcionalidades adicionais.

Para criar um endpoint customizado, adicione um arquivo .js ou .ts no diretório /pages. A extensão do arquivo será removida durante o processo de build, portanto o nome do arquivo deve conter a extensão que você deseja que os dados usem, por exemplo src/pages/data.json.ts se tornará a rota /data.json.

Seus endpoints devem exportar uma função GET (opcionalmente assíncrona) que recebe um objeto de contexto com propriedades similares a global Astro. Aqui, ele retorna um objeto Response com um name e url, que o Astro irá chamar durante a build e utilizar seu conteúdo para gerar o arquivo.

src/pages/builtwith.json.ts
// Se tornará: /builtwith.json
export async function GET({params, request}) {
return new Response(
JSON.stringify({
name: 'Astro',
url: 'https://astro.build/'
})
)
}

Desde o Astro v3.0, 0 objeto Response retornado não tem mais que incluir a propriedade encoding. Por exemplo, para produzir uma imagem binária png:

src/pages/builtwith.json.ts
export async function GET({ params, request }) {
const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
return new Response(await response.arrayBuffer());
}

Também é possível adicionar validação de tipo à sua função com o tipo APIRoute:

import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ params, request }) => {...}

Roteamento dinâmico e a propriedade params

Seção intitulada Roteamento dinâmico e a propriedade params

Os endpoints suportam as mesmas funcionalidades de roteamento dinâmico que as páginas. Nomeie seu arquivo com um nome de parâmetro entre colchetes e exporte uma função chamada getStaticPaths(). Assim será possível acessar o parâmetro utilizando a propriedade params passada para a função do endpoint.

src/pages/api/[id].json.ts
import type { APIRoute } from 'astro';
const usuarios = ["Sarah", "Chris", "Yan", "Elian"]
export const GET: APIRoute = ({ params, request }) => {
const id = params.id;
return new Response(
JSON.stringify({
name: usuarios[id]
})
)
}
export function getStaticPaths() {
return [
{ params: { id: "0"} },
{ params: { id: "1"} },
{ params: { id: "2"} },
{ params: { id: "3"} }
]
}

Isso irá gerar quatro endpoints JSON durante a build: /api/0.json, /api/1.json, /api/2.json e /api/3.json. O roteamento dinâmico com endpoints funciona da mesma forma que nas páginas, porém, como um endpoint é uma função e não uma página, props não são suportadas.

Todos os endpoints recebem uma propriedade request, porém no modo estático você só tem acesso a propriedade request.url. Ela retorna o URL completo do endpoint atual e funciona da mesma forma que Astro.request.url funciona em páginas.

src/pages/request-path.json.ts
import type { APIRoute } from 'astro';
export const GET: APIRoute = ({ params, request }) => {
return new Response(JSON.stringify({
path: new URL(request.url).pathname
})
)
}

Tudo descrito na seção de endpoints de arquivos estáticos também pode ser utilizado no modo SSR: arquivos podem exportar uma função GET que recebe um objeto de contexto com propriedades similares a global Astro.

Porém, diferente do modo static, quando você habilita a renderização sob demanda para uma rota, o endpoint será construído ao ser requisitado. Isso destrava novas funcionalidades que são indisponíveis em tempo de construção, e permite que você construa rotas de API que ouvem a requisições e executam código de maneira segura no servidor em tempo de execução.

Suas rotas serão renderizadas sob demanda por padrão no modo server. No modo hybrid, você deve desativar a pré-renderização para cada endpoint personalizado com export const prerender = false.

Receita relacionada: Chame endpoints do servidor

Os endpoints do servidor tem acesso a propriedade params sem exportar a função getStaticPaths e podem retornar um objeto Response, permitindo que você defina códigos de status e cabeçalhos HTTP.

src/pages/[id].json.js
import { getProduct } from '../db';
export async function GET({ params }) {
const id = params.id;
const product = await getProduct(id);
if (!product) {
return new Response(null, {
status: 404,
statusText: 'Não encontrado'
});
}
return new Response(
JSON.stringify(product), {
status: 200,
headers: {
"Content-Type": "application/json"
}
}
);
}

Esse código responderá a qualquer requisição que corresponda à rota dinâmica. Por exemplo, se navegarmos para /capacete.json, params.id será capacete. Se capacete existir no banco de dados, o endpoint irá criar um objeto Response para responder com JSON e retornar um código de status HTTP de sucesso. Caso contrário, ele usará o objeto Response para responder com um erro 404.

No modo SSR, certos provedores requerem que o cabeçalho Content-Type retorne uma imagem. Neste caso, utilize um objeto Response para especificar uma propriedade headers. Por exemplo, para produzir uma imagem .png binária:

src/pages/astro-logo.png.ts
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, {
headers: { "Content-Type": "image/png" },
});
}

Além da função GET, você pode exportar uma função com o nome de qualquer método HTTP. Assim, quando uma requisição for recebida, o Astro irá checar o método e chamar a função correspondente.

Também é possível exportar uma função ALL para corresponder a todos os métodos que já não tenham suas respectivas funções exportadas. Se houver uma requisição sem método correspondente, ela será redirecionada para a sua página de 404.

src/pages/methods.json.ts
export const GET: APIRoute = ({ params, request }) => {
return new Response(JSON.stringify({
message: "Isso foi um GET!"
})
)
}
export const POST: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: "Isso foi um POST!"
})
)
}
export const DELETE: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: "Isso foi um DELETE!"
})
)
}
export const ALL: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: `Isso foi um ${request.method}!`
})
)
}

No modo SSR, a propriedade request retorna um objeto Request completamente utilizável que se refere a requisição atual. Isso permite que você aceite dados e cheque cabeçalhos:

src/pages/test-post.json.ts
export const POST: APIRoute = async ({ request }) => {
if (request.headers.get("Content-Type") === "application/json") {
const body = await request.json();
const name = body.name;
return new Response(JSON.stringify({
message: "Seu nome é: " + name
}), {
status: 200
})
}
return new Response(null, { status: 400 });
}

O contexto do endpoint exporta um utilitário redirect() similar ao Astro.redirect:

src/pages/links/[id].js
import { getLinkUrl } from '../db';
export async function GET({ params, redirect }) {
const { id } = params;
const link = await getLinkUrl(id);
if (!link) {
return new Response(null, {
status: 404,
statusText: 'Não encontrado'
});
}
return redirect(link, 307);
}
Contribua

O que passa em sua cabeça?

Comunidade