Aller au contenu

Points de terminaison

Astro vous permet de créer des points de terminaison (ou « endpoint » en anglais) personnalisés pour servir tout type de données. Vous pouvez les utiliser pour générer des images, exposer un document RSS ou les utiliser comme routes d’API pour créer une API complète pour votre site.

Pour les sites générés statiquement, vos points de terminaison personnalisés sont appelés au moment de la compilation de votre site, afin de produire des fichiers statiques. Si vous optez pour le mode de rendu SSR, les points de terminaison personnalisés se transforment en points de terminaison de serveur qui sont appelés à chaque requête. Les points de terminaison statiques et SSR sont définis de manière similaire, mais les points de terminaison SSR prennent en charge des fonctionnalités supplémentaires.

Pour créer des points de terminaison personnalisés, ajoutez un fichier .js ou .ts à votre dossier /pages. L’extension .js ou .ts sera supprimée pendant le processus de compilation, donc le nom du fichier doit inclure l’extension des données que vous souhaitez créer. Par exemple, src/pages/data.json.ts générera un point de terminaison /data.json.

Les points de terminaison exportent une fonction GET (optionnellement async) qui reçoit un objet de contexte avec des propriétés similaires à celles de l’objet global Astro. Ici, elle retourne un objet Response avec un champ name et url, et Astro l’appellera au moment de la compilation et utilisera le contenu du body pour générer le fichier.

src/pages/builtwith.json.ts
// Sortie : /builtwith.json
export function GET({ params, request }) {
return new Response(
JSON.stringify({
name: "Astro",
url: "https://astro.build/",
}),
);
}

Depuis Astro v3.0, l’objet Response retourné n’a plus besoin d’inclure la propriété encoding. Par exemple, pour produire une image .png binaire :

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",
);
return new Response(await response.arrayBuffer());
}

Vous pouvez également définir le type de vos fonctions de point de terminaison à l’aide du type APIRoute :

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

Les points de terminaison prennent en charge les même fonctions de routage dynamique que celles des pages. Nommez votre fichier avec un nom de paramètre entre crochets et exportez une fonction getStaticPaths(). Vous pouvez ensuite accéder au paramètre en utilisant la propriété params passée à la fonction du point de terminaison :

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

Cela va générer 4 points de terminaison JSON au moment de la compilaton : /api/0.json, /api/1.json, /api/2.json et /api/3.json. Le routage dynamique avec les points de terminaison fonctionne de la même manière qu’avec les pages, mais parce que le point de terminaison est une fonction et non un composant, les props ne sont pas prises en charge.

Tous les points de terminaison reçoivent une propriété request, mais dans le mode statique, vous n’avez accès qu’à request.url. Cela renvoie l’URL complète du point de terminaison actuel et fonctionne de la même manière que Astro.request.url pour les pages.

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,
}),
);
};

Tout ce qui est décrit dans la section sur les points de terminaison des fichiers statiques peut également être utilisé en mode SSR : les fichiers peuvent exporter une fonction GET qui reçoit un objet de contexte avec des propriétés similaires à celles de l’objet global Astro.

Mais, contrairement au mode static, lorsque vous activez le mode de rendu à la demande pour une route, le point de terminaison sera généré lorsqu’il sera demandé. Cela débloque de nouvelles fonctionnalités qui ne sont pas disponibles au moment de la compilation, et vous permet de créer des routes d’API qui écoutent les requêtes et exécutent du code de manière sécurisée sur le serveur au moment de l’exécution.

Vos routes seront affichées à la demande par défaut dans le mode server. En mode static, vous devez désactiver le pré-rendu pour chaque point de terminaison personnalisé avec export const prerender = false.

Les points de terminaison du serveur peuvent accéder à params sans exporter getStaticPaths, et ils peuvent retourner un objet Response, vous permettant de définir les codes d’état et les en-têtes :

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: "Not found",
});
}
return new Response(JSON.stringify(product), {
status: 200,
headers: {
"Content-Type": "application/json",
},
});
}

Cela répondra à toute requête qui correspond à la route dynamique. Par exemple, si nous naviguons vers /helmet.json, params.id sera défini sur helmet. Si helmet existe dans la base de données de produits fictifs, le point de terminaison utilisera un objet Response pour répondre en JSON et renvoyer un code d’état HTTP (Anglais) de succès. Sinon, il utilisera un objet Response pour répondre avec une erreur 404.

En mode SSR, certains fournisseurs exigent l’en-tête Content-Type pour renvoyer une image. Dans ce cas, utilisez un objet Response pour spécifier une propriété headers. Par exemple, pour produire une image binaire .png :

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" },
});
}

En plus de la fonction GET, vous pouvez exporter une fonction avec le nom de n’importe quelle méthode HTTP. Lorsqu’une requête arrive, Astro vérifie la méthode et appelle la fonction correspondante.

Vous pouvez également exporter une fonction ALL pour correspondre à n’importe quelle méthode qui n’a pas de fonction exportée correspondante. Si une requête ne correspond à aucune méthode, elle sera redirigée vers la page 404 de votre site.

src/pages/methods.json.ts
export const GET: APIRoute = ({ params, request }) => {
return new Response(
JSON.stringify({
message: "C'était un GET !",
}),
);
};
export const POST: APIRoute = ({ request }) => {
return new Response(
JSON.stringify({
message: "C'était un POST !",
}),
);
};
export const DELETE: APIRoute = ({ request }) => {
return new Response(
JSON.stringify({
message: "C'était un DELETE !",
}),
);
};
export const ALL: APIRoute = ({ request }) => {
return new Response(
JSON.stringify({
message: `C'était un ${request.method} !`,
}),
);
};

Si vous définissez une fonction GET mais pas de fonction HEAD, Astro gérera automatiquement les requêtes HEAD en appelant la fonction GET et en supprimant le corps de la réponse.

En mode de rendu SSR, la propriété request renvoie un objet Request entièrement utilisable qui fait référence à la requête en cours. Cela vous permet d’accepter des données et de vérifier les en-têtes :

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: "Votre nom était : " + name,
}),
{
status: 200,
},
);
}
return new Response(null, { status: 400 });
};

Le contexte du point de terminaison exporte un utilitaire redirect() similaire à 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: "Not found",
});
}
return redirect(link, 307);
}
Contribuer Communauté Parrainer