Aller au contenu

Actions

Ajouté à la version : astro@4.15

Astro Actions vous permet de définir et d’appeler des fonctions backend avec sûreté du typage. Les actions effectuent la récupération des données, l’analyse JSON et la validation des entrées pour vous. Cela peut réduire considérablement la quantité de code standard nécessaire par rapport à l’utilisation d’un point de terminaison d’API.

Utilisez des actions à la place de points de terminaison d’API pour une communication transparente entre votre code client et votre code serveur et pour :

  • Valider automatiquement les entrées de données JSON et de formulaire à l’aide de la validation Zod.
  • Générer des fonctions avec sûreté du typage pour appeler votre backend à partir du client et même à partir des actions de formulaire HTML. Pas besoin d’appels manuels à fetch().
  • Standardiser les erreurs du backend avec l’objet ActionError.

Les actions sont définies dans un objet server exporté depuis src/actions/index.ts :

src/actions/index.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
export const server = {
myAction: defineAction({ /* ... */ })
}

Vos actions sont disponibles en tant que fonctions à partir du module astro:actions. Importez actions et appelez-les côté client dans un composant de framework UI, une requête POST de formulaire ou en utilisant une balise <script> dans un composant Astro.

Lorsque vous appelez une action, elle renvoie un objet avec soit data contenant le résultat sérialisé JSON, soit error contenant les erreurs renvoyées.

src/pages/index.astro
---
---
<script>
import { actions } from 'astro:actions';
async () => {
const { data, error } = await actions.myAction({ /* ... */ });
}
</script>

Suivez ces étapes pour définir une action et pour l’appeler dans une balise script de votre page Astro.

  1. Créez un fichier src/actions/index.ts et exportez un objet server.

    src/actions/index.ts
    export const server = {
    // déclarations d'action
    }
  2. Importez l’utilitaire defineAction() depuis astro:actions et l’objet z depuis astro:schema.

    src/actions/index.ts
    import { defineAction } from 'astro:actions';
    import { z } from 'astro:schema';
    export const server = {
    // déclarations d'action
    }
  3. Utilisez l’utilitaire defineAction() pour définir une action getGreeting. La propriété input sera utilisée pour valider les paramètres d’entrée avec un schéma Zod et la fonction handler() inclut la logique backend à exécuter sur le serveur.

    src/actions/index.ts
    import { defineAction } from 'astro:actions';
    import { z } from 'astro:schema';
    export const server = {
    getGreeting: defineAction({
    input: z.object({
    name: z.string(),
    }),
    handler: async (input) => {
    return `Bonjour, ${input.name} !`
    }
    })
    }
  4. Créez un composant Astro avec un bouton qui récupérera un message d’accueil à l’aide de votre action getGreeting lorsqu’il est cliqué.

    src/pages/index.astro
    ---
    ---
    <button>Obtenir un message d'accueil</button>
    <script>
    const button = document.querySelector('button');
    button?.addEventListener('click', async () => {
    // Afficher une fenêtre contextuelle d'alerte avec le message d'accueil de l'action
    });
    </script>
  5. Pour utiliser votre action, importez actions depuis astro:actions puis appelez actions.getGreeting() dans le gestionnaire de clics. L’option name sera envoyée à la fonction handler() de votre action sur le serveur et, s’il n’y a pas d’erreur, le résultat sera disponible sous la forme de la propriété data.

    src/pages/index.astro
    ---
    ---
    <button>Obtenir un message d'accueil</button>
    <script>
    import { actions } from 'astro:actions';
    const button = document.querySelector('button');
    button?.addEventListener('click', async () => {
    // Afficher une fenêtre contextuelle d'alerte avec le message d'accueil de l'action
    const { data, error } = await actions.getGreeting({ name: "Houston" });
    if (!error) alert(data);
    })
    </script>
Consultez la documentation complète de l’API Actions pour plus de détails sur defineAction() et ses propriétés.

Toutes les actions de votre projet doivent être exportées depuis l’objet server dans le fichier src/actions/index.ts. Vous pouvez définir des actions en ligne ou déplacer les définitions d’actions vers des fichiers séparés et les importer. Vous pouvez même regrouper des fonctions liées dans des objets imbriqués.

Par exemple, pour regrouper toutes vos actions utilisateur, vous pouvez créer un fichier src/actions/user.ts et imbriquer les définitions de getUser et createUser dans un seul objet user.

src/actions/user.ts
import { defineAction } from 'astro:actions';
export const user = {
getUser: defineAction(/* ... */),
createUser: defineAction(/* ... */),
}

Ensuite, vous pouvez importer cet objet user dans votre fichier src/actions/index.ts et l’ajouter en tant que propriété de niveau supérieur à l’objet server aux côtés de toute autre action :

src/actions/index.ts
import { user } from './user';
export const server = {
myAction: defineAction({ /* ... */ }),
user,
}

Désormais, toutes vos actions utilisateur peuvent être appelées à partir de l’objet actions.user :

  • actions.user.getUser()
  • actions.user.createUser()

Les actions renvoient un objet contenant soit data qui contient la valeur de retour de votre fonction handler() avec sûreté du typage, soit error qui contient les erreurs du backend. Ces dernières peuvent provenir d’erreurs de validation sur la propriété input ou d’erreurs générées dans la fonction handler().

Les actions renvoient un format de données personnalisé qui peut gérer les Dates, les Maps, les Sets et les URL à l’aide de la bibliothèque Devalue. Par conséquent, vous ne pouvez pas facilement inspecter la réponse du réseau comme vous le pouvez avec du JSON classique. Pour le débogage, vous pouvez plutôt inspecter l’objet data renvoyé par les actions.

Il est préférable de vérifier si une erreur (error) est présente avant d’utiliser la propriété data. Cela vous permet à la fois de gérer les erreurs à l’avance et d’être certain que data est définie sans vérification additionnelle pour undefined.

const { data, error } = await actions.example();
if (error) {
// gérer les cas d'erreur
return;
}
// utiliser `data`

Accéder directement aux données sans vérification d’erreur

Titre de la section Accéder directement aux données sans vérification d’erreur

Pour ignorer la gestion des erreurs, par exemple lors du prototypage ou de l’utilisation d’une bibliothèque qui détectera les erreurs à votre place, utilisez la propriété .orThrow() sur votre appel d’action pour générer des erreurs au lieu de renvoyer une error. Cela renverra directement les data de l’action.

Cet exemple appelle une action likePost() qui renvoie le nombre mis à jour de mentions « j’aime » sous forme de nombre à partir de l’action handler :

const updatedLikes = await actions.likePost.orThrow({ postId: 'example' });
// ^ type: number

Gestion des erreurs backend dans votre action

Titre de la section Gestion des erreurs backend dans votre action

Vous pouvez utiliser la classe ActionError fournie pour générer une erreur à partir de la fonction handler() de votre action, comme, par exemple, « not found » lorsqu’une entrée de base de données est manquante ou « unauthorized » lorsqu’un utilisateur n’est pas connecté. Cela présente deux avantages principaux par rapport au renvoi de undefined :

  • Vous pouvez définir un code d’état tel que 404 - Not found ou 401 - Unauthorized. Cela améliore le débogage des erreurs à la fois en développement et en production en vous permettant de voir le code d’état de chaque demande.

  • Dans le code de votre application, toutes les erreurs sont transmises à l’objet error sur un résultat d’action. Cela évite d’avoir à vérifier si les données sont indéfinies et vous permet d’afficher des commentaires ciblés à l’utilisateur en fonction de ce qui s’est mal passé.

Pour générer une erreur, importez la classe ActionError() depuis le module astro:actions. Transmettez-lui un code d’état lisible par l’homme (par exemple "NOT_FOUND" ou "BAD_REQUEST"), et un message facultatif pour fournir des informations supplémentaires sur l’erreur.

Cet exemple génère une erreur d’une action likePost lorsqu’un utilisateur n’est pas connecté, après avoir vérifié un hypothétique cookie de « session utilisateur » pour l’authentification :

src/actions/index.ts
import { defineAction, ActionError } from "astro:actions";
import { z } from "astro:schema";
export const server = {
likePost: defineAction({
input: z.object({ postId: z.string() }),
handler: async (input, ctx) => {
if (!ctx.cookies.has('user-session')) {
throw new ActionError({
code: "UNAUTHORIZED",
message: "L'utilisateur doit être connecté.",
});
}
// Sinon, aimer l'article
},
}),
};

Pour gérer cette erreur, vous pouvez appeler l’action depuis votre application et vérifier si une propriété error est présente. Cette propriété sera de type ActionError et contiendra votre code et message.

Dans l’exemple suivant, un composant LikeButton.tsx appelle l’action likePost() lorsqu’il est cliqué. Si une erreur d’authentification se produit, l’attribut error.code est utilisé pour déterminer s’il faut afficher un lien de connexion :

src/components/LikeButton.tsx
import { actions } from 'astro:actions';
import { useState } from 'preact/hooks';
export function LikeButton({ postId }: { postId: string }) {
const [showLogin, setShowLogin] = useState(false);
return (
<>
{
showLogin && <a href="/signin">Connectez-vous pour aimer une publication.</a>
}
<button onClick={async () => {
const { data, error } = await actions.likePost({ postId });
if (error?.code === 'UNAUTHORIZED') setShowLogin(true);
// Retour anticipé en cas d'erreurs inattendues
else if (error) return;
// mettre à jour les mentions j'aime
}}>
J'aime
</button>
</>
)
}

Lorsque vous appelez des actions à partir du client, vous pouvez intégrer une bibliothèque côté client comme react-router, ou vous pouvez utiliser la fonction navigate() d’Astro pour rediriger vers une nouvelle page lorsqu’une action réussit.

Cet exemple permet de retourner sur la page d’accueil après qu’une action de déconnexion (logout) ait abouti avec succès :

src/pages/LogoutButton.tsx
import { actions } from 'astro:actions';
import { navigate } from 'astro:transitions/client';
export function LogoutButton() {
return (
<button onClick={async () => {
const { error } = await actions.logout();
if (!error) navigate('/');
}}>
Déconnexion
</button>
);
}

Accepter les données d’un formulaire à partir d’une action

Titre de la section Accepter les données d’un formulaire à partir d’une action

Les actions acceptent les données JSON par défaut. Pour accepter les données d’un formulaire HTML, définissez accept: 'form' dans votre appel defineAction() :

src/actions/index.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
export const server = {
comment: defineAction({
accept: 'form',
input: z.object(/* ... */),
handler: async (input) => { /* ... */ },
})
}

Les actions analyseront les données de formulaire soumises à un objet, en utilisant la valeur de l’attribut name de chaque entrée comme propriétés d’objet. Par exemple, un formulaire contenant <input name="search"> sera analysé en un objet comme { search: 'user input' }. Le schéma input de votre action sera utilisé pour valider cet objet.

Pour recevoir l’objet FormData brut dans votre gestionnaire d’action au lieu d’un objet analysé, omettez la propriété input dans la définition de votre action.

L’exemple suivant montre un formulaire d’inscription à une newsletter validé qui accepte l’e-mail d’un utilisateur et nécessite une case à cocher pour accepter les « conditions d’utilisation ».

  1. Créez un composant de formulaire HTML avec des attributs name uniques sur chaque entrée :

    src/components/Newsletter.astro
    <form>
    <label for="email">E-mail</label>
    <input id="email" required type="email" name="email" />
    <label>
    <input required type="checkbox" name="terms">
    J'accepte les conditions d'utilisation
    </label>
    <button>S'inscrire</button>
    </form>
  2. Définir une action newsletter pour gérer le formulaire soumis. Validez le champ email en utilisant le validateur z.string().email() et la case à cocher terms en utilisant z.boolean() :

    src/actions/index.ts
    import { defineAction } from 'astro:actions';
    import { z } from 'astro:schema';
    export const server = {
    newsletter: defineAction({
    accept: 'form',
    input: z.object({
    email: z.string().email(),
    terms: z.boolean(),
    }),
    handler: async ({ email, terms }) => { /* ... */ },
    })
    }
    Consultez la référence de l’API input pour tous les validateurs de formulaire disponibles.
  3. Ajoutez un <script> au formulaire HTML pour soumettre la saisie de l’utilisateur. Cet exemple remplace le comportement de soumission par défaut du formulaire pour appeler actions.newsletter() et redirige vers /confirmation à l’aide de la fonction navigate() :

    src/components/Newsletter.astro
    <form>
    7 collapsed lines
    <label for="email">E-mail</label>
    <input id="email" required type="email" name="email" />
    <label>
    <input required type="checkbox" name="terms">
    J'accepte les conditions d'utilisation
    </label>
    <button>S'inscrire</button>
    </form>
    <script>
    import { actions } from 'astro:actions';
    import { navigate } from 'astro:transitions/client';
    const form = document.querySelector('form');
    form?.addEventListener('submit', async (event) => {
    event.preventDefault();
    const formData = new FormData(form);
    const { error } = await actions.newsletter(formData);
    if (!error) navigate('/confirmation');
    })
    </script>
    Consultez « Appeler des actions depuis une action de formulaire HTML » pour découvrir une autre façon de soumettre des données de formulaire.

Affichage des erreurs de saisie du formulaire

Titre de la section Affichage des erreurs de saisie du formulaire

Vous pouvez valider les entrées du formulaire avant la soumission à l’aide des attributs natifs de validation de formulaire HTML tels que required, type="email" et pattern. Pour une validation plus complexe d’input depuis le backend, vous pouvez utiliser la fonction utilitaire isInputError().

Pour récupérer les erreurs de saisie, utilisez l’utilitaire isInputError() pour vérifier si une erreur a été provoquée par une entrée non valide. Les erreurs de saisie contiennent un objet fields avec des messages pour chaque nom d’entrée qui n’a pas pu être validé. Vous pouvez utiliser ces messages pour demander à votre utilisateur de corriger sa soumission.

L’exemple suivant vérifie l’erreur avec isInputError(), puis vérifie si l’erreur se trouve dans le champ e-mail, avant de créer finalement un message à partir des erreurs. Vous pouvez utiliser la manipulation DOM JavaScript ou votre infrastructure d’interface utilisateur préférée pour afficher ce message aux utilisateurs.

import { actions, isInputError } from 'astro:actions';
const form = document.querySelector('form');
const formData = new FormData(form);
const { error } = await actions.newsletter(formData);
if (isInputError(error)) {
// Gérer les erreurs de saisie.
if (error.fields.email) {
const message = error.fields.email.join(', ');
}
}

Appeler des actions depuis une action de formulaire HTML

Titre de la section Appeler des actions depuis une action de formulaire HTML

Vous pouvez activer les soumissions de formulaires zéro-JS avec des attributs standard sur n’importe quel élément <form>. Les soumissions de formulaires sans JavaScript côté client peuvent être utiles à la fois comme solution de secours en cas d’échec du chargement de JavaScript ou si vous préférez gérer les formulaires entièrement à partir du serveur.

L’appel de Astro.getActionResult() sur le serveur renvoie le résultat de votre soumission de formulaire (data ou error), et peut être utilisé pour rediriger dynamiquement, gérer les erreurs de formulaire, mettre à jour l’interface utilisateur, etc.

Pour appeler une action à partir d’un formulaire HTML, ajoutez method="POST" à votre <form>, puis définissez l’attribut action du formulaire à l’aide de votre action, par exemple action={actions.logout}. Cela définira l’attribut action pour utiliser une chaîne de requête gérée automatiquement par le serveur.

Par exemple, ce composant Astro appelle l’action logout lorsque le bouton est cliqué et recharge la page actuelle :

src/components/LogoutButton.astro
---
import { actions } from 'astro:actions';
---
<form method="POST" action={actions.logout}>
<button>Se déconnecter</button>
</form>

Redirection en cas de réussite de l’action

Titre de la section Redirection en cas de réussite de l’action

Si vous devez rediriger vers une nouvelle route en cas de succès, vous pouvez utiliser le résultat d’une action sur le serveur. Un exemple courant est la création d’un enregistrement de produit et la redirection vers la page du nouveau produit, par exemple /products/[id].

Par exemple, supposons que vous ayez une action createProduct qui renvoie l’identifiant du produit généré :

src/actions/index.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
export const server = {
createProduct: defineAction({
accept: 'form',
input: z.object({ /* ... */ }),
handler: async (input) => {
const product = await persistToDatabase(input);
return { id: product.id };
},
})
}

Vous pouvez récupérer le résultat de l’action de votre composant Astro en appelant Astro.getActionResult(). Cela renvoie un objet contenant les propriétés data ou error lorsqu’une action est appelée, ou undefined si l’action n’a pas été appelée pendant cette requête.

Utilisez la propriété data pour construire une URL à utiliser avec Astro.redirect() :

src/pages/products/create.astro
---
import { actions } from 'astro:actions';
const result = Astro.getActionResult(actions.createProduct);
if (result && !result.error) {
return Astro.redirect(`/products/${result.data.id}`);
}
---
<form method="POST" action={actions.createProduct}>
<!--...-->
</form>

Gérer les erreurs d’action du formulaire

Titre de la section Gérer les erreurs d’action du formulaire

L’appel de Astro.getActionResult() dans le composant Astro contenant votre formulaire vous donne accès aux objets data et error pour la gestion personnalisée des erreurs.

L’exemple suivant affiche un message d’échec général lorsqu’une action newsletter échoue :

src/pages/index.astro
---
import { actions } from 'astro:actions';
const result = Astro.getActionResult(actions.newsletter);
---
{result?.error && (
<p class="error">Impossible de s'inscrire. Veuillez réessayer ultérieurement.</p>
)}
<form method="POST" action={actions.newsletter}>
<label>
E-mail
<input required type="email" name="email" />
</label>
<button>S'inscrire</button>
</form>

Pour plus de personnalisation, vous pouvez utiliser l’utilitaire isInputError() pour vérifier si une erreur est provoquée par une entrée non valide.

L’exemple suivant affiche une bannière d’erreur sous le champ de saisie email lorsqu’un e-mail invalide est soumis :

src/pages/index.astro
---
import { actions, isInputError } from 'astro:actions';
const result = Astro.getActionResult(actions.newsletter);
const inputErrors = isInputError(result?.error) ? result.error.fields : {};
---
<form method="POST" action={'/confirmation' + actions.newsletter}>
<label>
E-mail
<input required type="email" name="email" aria-describedby="error" />
</label>
{inputErrors.email && <p id="error">{inputErrors.email.join(',')}</p>}
<button>S'inscrire</button>
</form>

Conserver les valeurs d’entrée en cas d’erreur

Titre de la section Conserver les valeurs d’entrée en cas d’erreur

Les entrées seront effacées à chaque fois qu’un formulaire sera soumis. Pour conserver les valeurs d’entrée, vous pouvez activer les transitions de vue sur la page et appliquer la directive transition:persist à chaque entrée :

<input transition:persist required type="email" name="email" />

Mettre à jour l’interface utilisateur avec un résultat d’action de formulaire

Titre de la section Mettre à jour l’interface utilisateur avec un résultat d’action de formulaire

Pour utiliser la valeur de retour d’une action pour afficher une notification à l’utilisateur en cas de réussite, transmettez l’action à Astro.getActionResult(). Utilisez la propriété data renvoyée pour restituer l’interface utilisateur que vous souhaitez afficher.

Cet exemple utilise la propriété productName renvoyée par une action addToCart pour afficher un message de réussite.

src/pages/products/[slug].astro
---
import { actions } from 'astro:actions';
const result = Astro.getActionResult(actions.addToCart);
---
{result && !result.error && (
<p class="success">{result.data.productName} a été ajouté au panier</p>
)}
<!--...-->

Avancé : Persistance des résultats d’action avec une session

Titre de la section Avancé : Persistance des résultats d’action avec une session

Ajouté à la version : astro@5.0.0 Nouveau

Les résultats de l’action sont affichés sous forme de soumission POST. Cela signifie que le résultat sera réinitialisé sur undefined lorsqu’un utilisateur fermera et revisitera la page. L’utilisateur verra également une boîte de dialogue « Confirmer la nouvelle soumission du formulaire ?» s’il tente d’actualiser la page.

Pour personnaliser ce comportement, vous pouvez ajouter un middleware pour gérer manuellement le résultat de l’action. Vous pouvez choisir de conserver le résultat de l’action à l’aide d’un cookie ou d’un stockage de session.

Commencez par créer un fichier middleware et par importer l’utilitaire getActionContext() depuis astro:actions. Cette fonction renvoie un objet action avec des informations sur la demande d’action entrante, y compris le gestionnaire d’action et si l’action a été appelée à partir d’un formulaire HTML. getActionContext() renvoie également les fonctions setActionResult() et serializeActionResult() pour définir par programmation la valeur renvoyée par Astro.getActionResult() :

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => {
const { action, setActionResult, serializeActionResult } = getActionContext(context);
if (action?.calledFrom === 'form') {
const result = await action.handler();
// ... gérer le résultat de l'action
setActionResult(action.name, serializeActionResult(result));
}
return next();
});

Une pratique courante pour conserver les résultats des formulaires HTML est le modèle POST / Redirect / GET. Cette redirection supprime la boîte de dialogue « Confirmer la nouvelle soumission du formulaire ?» lorsque la page est actualisée et permet aux résultats de l’action d’être conservés tout au long de la session de l’utilisateur.

Cet exemple applique le modèle POST / Redirect / GET à toutes les soumissions de formulaire utilisant le stockage de session avec l’adaptateur de serveur Netlify installé. Les résultats de l’action sont écrits dans un magasin de sessions à l’aide de Netlify Blob et récupérés après une redirection à l’aide d’un ID de session :

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
import { randomUUID } from "node:crypto";
import { getStore } from "@netlify/blobs";
export const onRequest = defineMiddleware(async (context, next) => {
// Ignorer les demandes de pages pré-rendues
if (context.isPrerendered) return next();
const { action, setActionResult, serializeActionResult } =
getActionContext(context);
// Créer un magasin Blob pour conserver les résultats des actions avec Netlify Blob
const actionStore = getStore("action-session");
// Si un résultat d'action a été transmis sous forme de cookie, définir le
// résultat pour qu'il soit accessible à partir de `Astro.getActionResult()`
const sessionId = context.cookies.get("action-session-id")?.value;
const session = sessionId
? await actionStore.get(sessionId, {
type: "json",
})
: undefined;
if (session) {
setActionResult(session.actionName, session.actionResult);
// Facultatif : supprimer la session une fois la page rendue.
// N'hésitez pas à mettre en œuvre votre propre stratégie de persistance
await actionStore.delete(sessionId);
ctx.cookies.delete("action-session-id");
return next();
}
// Si une action a été appelée à partir d'une action de formulaire HTML,
// appeler le gestionnaire d'action et rediriger vers la page de destination
if (action?.calledFrom === "form") {
const actionResult = await action.handler();
// Conserver le résultat de l'action à l'aide du stockage de session
const sessionId = randomUUID();
await actionStore.setJSON(sessionId, {
actionName: action.name,
actionResult: serializeActionResult(actionResult),
});
// Transmettre l'ID de session sous forme de cookie
// à récupérer après la redirection vers la page
context.cookies.set("action-session-id", sessionId);
// Rediriger vers la page précédente en cas d'erreur
if (actionResult.error) {
const referer = context.request.headers.get("Referer");
if (!referer) {
throw new Error(
"Internal: Referer unexpectedly missing from Action POST request.",
);
}
return context.redirect(referer);
}
// Rediriger vers la page de destination en cas de succès
return context.redirect(context.originPathname);
}
return next();
});

Sécurité lors de l’utilisation des actions

Titre de la section Sécurité lors de l’utilisation des actions

Les actions sont accessibles en tant que points de terminaison publics en fonction du nom de l’action. Par exemple, l’action blog.like() sera accessible depuis /_actions/blog.like. Cela est utile pour tester les résultats des actions et déboguer les erreurs de production. Cependant, cela signifie que vous devez utiliser les mêmes contrôles d’autorisation que ceux que vous envisageriez pour les points de terminaison d’API et les pages rendues à la demande.

Autoriser les utilisateurs à partir d’un gestionnaire d’actions

Titre de la section Autoriser les utilisateurs à partir d’un gestionnaire d’actions

Pour autoriser les demandes d’action, ajoutez une vérification d’authentification à votre gestionnaire d’actions. Vous souhaiterez peut-être utiliser une bibliothèque d’authentification pour gérer la gestion des sessions et les informations utilisateur.

Les actions exposent l’objet APIContext complet pour accéder aux propriétés transmises par le middleware à l’aide de context.locals. Lorsqu’un utilisateur n’est pas autorisé, vous pouvez générer une ActionError avec le code UNAUTHORIZED :

src/actions/index.ts
import { defineAction, ActionError } from 'astro:actions';
export const server = {
getUserSettings: defineAction({
handler: async (_input, context) => {
if (!context.locals.user) {
throw new ActionError({ code: 'UNAUTHORIZED' });
}
return { /* les données en cas de réussite */ };
}
})
}

Limiter les actions depuis le middleware

Titre de la section Limiter les actions depuis le middleware

Ajouté à la version : astro@5.0.0 Nouveau

Astro recommande d’autoriser les sessions utilisateur à partir de votre gestionnaire d’actions pour respecter les niveaux d’autorisation et la limitation de débit par action. Cependant, vous pouvez également limiter les demandes à toutes les actions (ou à un sous-ensemble d’actions) à partir du middleware.

Utilisez la fonction getActionContext() de votre middleware pour récupérer des informations sur les demandes d’action entrantes. Cela inclut le nom de l’action et si cette action a été appelée à l’aide d’une fonction d’appel de procédure à distance (RPC) côté client (par exemple, actions.blog.like()) ou d’un formulaire HTML.

L’exemple suivant rejette toutes les demandes d’action qui ne disposent pas d’un jeton de session valide. Si la vérification échoue, une réponse « Interdit » est renvoyée. Remarque : cette méthode garantit que les actions ne sont accessibles que lorsqu’une session est présente, mais ne remplace pas une autorisation sécurisée.

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
import { getActionContext } from 'astro:actions';
export const onRequest = defineMiddleware(async (context, next) => {
const { action } = getActionContext(context);
// Vérifier si l'action a été appelée à partir d'une fonction côté client
if (action?.calledFrom === 'rpc') {
// Si tel est le cas, rechercher un jeton de session utilisateur
if (context.cookies.has('user-session')) {
return new Response('Forbidden', { status: 403 });
}
}
context.cookies.set('user-session', /* jeton de session */);
return next();
});

Appeler des actions à partir des composants Astro et des points de terminaison du serveur

Titre de la section Appeler des actions à partir des composants Astro et des points de terminaison du serveur

Vous pouvez appeler des actions directement à partir des scripts de composants Astro en utilisant l’enveloppe Astro.callAction() (ou context.callAction() lors de l’utilisation d’un point de terminaison de serveur). Il est courant de réutiliser la logique de vos actions dans un autre code serveur.

Transmettez l’action comme premier argument et tous les paramètres d’entrée comme deuxième argument. Cela renvoie les mêmes objets data et error que vous recevez lors de l’appel d’actions sur le client :

src/pages/products.astro
---
import { actions } from 'astro:actions';
const searchQuery = Astro.url.searchParams.get('search');
if (searchQuery) {
const { data, error } = Astro.callAction(actions.findProduct, { query: searchQuery });
// gérer le résultat
}
---
Contribuer

Comment pouvons-nous vous aider ?

Créer une issue GitHub

Le moyen le plus rapide d'alerter notre équipe d'un problème.

Communauté