Erreurs 500, 502, 503 et 504 provenant d’API : ce que signifient les erreurs 500, 502, 503 et 504 et comment les gérer

Un code d’état de 500 à 599 signifie que le serveur n’a pas pu répondre à une demande qui semblait valide. Votre demande n’est pas le problème, donc l’envoyer à nouveau peut fonctionner. Si vous devez l’envoyer à nouveau dépend du code d’état et de ce que fait la demande. Pour connaître les définitions, consultez RFC 9110, section 15.6.

Signification de chaque code d’état

Code de statut Ce que cela signifie Réessayez ?
500 Internal Server Error Le serveur a atteint une condition qu’il n’attendait pas Cela dépend de l’API. Certaines API, comme l’API Claude, vous indiquent de réessayer après une erreur 500 en appliquant un délai exponentiel entre les tentatives. Consultez les documents de l’API.
502 Bad Gateway Une passerelle ou un proxy a obtenu une réponse non valide du serveur derrière celui-ci Oui, si la demande est sûre à répéter
503 Service Unavailable Le serveur est temporairement surchargé ou arrêté pour maintenance, et il devrait redevenir accessible après un certain temps. Le serveur peut envoyer un en-tête Retry-After. Oui, après Retry-After l’heure si le serveur en a envoyé un
504 Gateway Timeout Une passerelle ou un proxy n’a pas reçu de réponse à temps du serveur en amont Oui, si la demande peut être répétée sans risque. La passerelle a cessé d’attendre. Vous ne savez donc pas si le serveur a effectué le travail.

Quelles requêtes sont sécurisées pour réessayer

La RFC 9110 considère qu’une méthode est idempotente lorsque l’envoi de la même requête plusieurs fois a le même effet que son envoi une seule fois. GET, HEAD, TRACE, OPTIONS, PUT et DELETE sont idempotents. POST et PATCH ne le sont pas. Selon la RFC, un client ne doit pas réessayer automatiquement une demande avec une méthode non idempotente, sauf s’il sait que la requête est idempotente de toute façon, ou qu’il peut déterminer que le serveur n’a jamais appliqué la requête d’origine. Pour plus d’informations, consultez les méthodes idempotentes.

Une nouvelle tentative POST après un 502 ou 504 peut créer une deuxième commande ou envoyer un deuxième e-mail. Certaines bibliothèques de réessai réessaient chaque méthode par défaut. Par exemple, le gestionnaire de résilience standard .NET réessayePOST, sauf si vous appelez options.Retry.DisableForUnsafeHttpMethods(). Pour plus d’informations, consultez Créer des applications HTTP résilientes.

Retry-After dans une réponse 503

Un 503 peut inclure un en-tête Retry-After. Sa valeur est soit un nombre de secondes, par 120exemple, soit une date HTTP, comme Fri, 31 Dec 1999 23:59:59 GMT. Votre code doit gérer les deux. Pour plus d’informations, consultez Retry-After.

Arrêter l’appel d’une API qui continue d’échouer

Les réessais aident en cas d’échecs temporaires. Lorsqu’une API est en panne pendant des minutes, réessayer chaque requête ajoute une charge à un serveur déjà en difficulté, et vos utilisateurs attendent que chaque nouvelle tentative échoue. Un disjoncteur suit les défaillances et, lorsqu’il y a trop d’échecs, il cesse d’appeler l’API pendant un certain temps et échoue immédiatement. Après ce temps, il laisse passer quelques requêtes pour vérifier si l’API s’est rétablie. Pour plus d’informations, consultez le modèle Circuit Breaker. Le gestionnaire de résilience standard .NET inclut un disjoncteur qui s’ouvre pendant 5 secondes quand au moins 10% de requêtes échouent dans une fenêtre de 30 secondes avec au moins 100 requêtes.

Comment gérer les erreurs 5xx

  1. Réessayez les requêtes idempotentes uniquement en cas de code 502, 503 ou 504. Pour POST et PATCH, réessayez uniquement si l’API documente un moyen de garantir qu’ils peuvent être relancés sans risque.
  2. Attendez avant de réessayer. Utilisez Retry-After quand le serveur l’envoie. Sinon, utilisez un backoff exponentiel avec une gigue aléatoire et arrêtez après quelques tentatives.
  3. Lisez la documentation de l’API pour l’erreur 500. Réessayez uniquement si l’API indique que cela est sans danger.
  4. Arrêtez d’appeler une API qui échoue constamment. Utilisez un circuit breaker pour que votre application échoue rapidement pendant que l’API se rétablit.
  5. Indiquez à l’utilisateur ce qui s’est passé. Affichez « le service rencontre des problèmes, réessayez ultérieurement » au lieu d’une erreur générique ou d’une trace de pile.
const RETRYABLE_STATUS = new Set([502, 503, 504]);
const IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "OPTIONS", "TRACE", "PUT", "DELETE"]);

function retryAfterMs(response) {
  const value = response.headers.get("retry-after");
  if (!value) return null;
  const seconds = Number(value);
  if (Number.isFinite(seconds)) return seconds * 1000;
  const date = Date.parse(value);
  return Number.isNaN(date) ? null : Math.max(0, date - Date.now());
}

export async function fetchWithRetry(url, options = {}, maxRetries = 3) {
  const method = (options.method ?? "GET").toUpperCase();
  const canRetry = IDEMPOTENT_METHODS.has(method);

  for (let attempt = 0; ; attempt++) {
    const response = await fetch(url, options);
    if (!RETRYABLE_STATUS.has(response.status) || !canRetry || attempt === maxRetries) {
      return response;
    }
    await response.body?.cancel();
    const backoff = 2 ** attempt * 1000 + Math.random() * 1000;
    const wait = retryAfterMs(response) ?? backoff;
    await new Promise((resolve) => setTimeout(resolve, wait));
  }
}

Comment tester que votre application gère les erreurs 5xx

Vous voyez rarement un 5xx pendant que vous développez, et vous ne pouvez pas provoquer l’échec d’une API à la demande. La façon dont vous testez détermine si vous trouvez les bogues avant que vos utilisateurs ne le fassent.

Approach Ce que vous trouvez Ce qui vous manque
Attendre la mise en production Pannes réelles Tout, jusqu’à ce qu’un utilisateur clique dessus
Simuler l’API dans vos tests ou laisser votre agent de codage écrire la simulation Si votre branche d’erreur s’exécute Votre client HTTP réel et votre bibliothèque de nouvelles tentatives, et combien de fois il retente réellement. Votre application a également besoin d’un commutateur uniquement pour les tests afin d’atteindre le mock.
Appelez l’API réelle et attendez qu’elle échoue Comportement réel Vous ne pouvez pas faire échouer l’API volontairement
Interceptez le trafic réel de votre application et retournez des erreurs 5xx à un débit que vous choisissez Votre véritable client HTTP, bibliothèque de nouvelle tentative et coupe-circuit Rien dans votre application ne change, de sorte que cela ne teste pas votre code de manière isolée. Conservez vos tests unitaires pour cela.

Essayez-le dans votre application

Le proxy de développement intercepte les requêtes de votre application et fait échouer une partie d’entre elles avec les erreurs que vous définissez, à l’aide de GenericRandomErrorPlugin. Votre application continue d’appeler l’URL réelle. Ajoutez le plug-in à votre fichier de configuration et faites pointer son errorsFile vers un fichier contenant les erreurs 5xx. Cet exemple utilise https://api.contoso.com. Remplacez-le par l’URL de l’API que votre application appelle.

Fichier : server-errors.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.errorsfile.schema.json",
  "errors": [
    {
      "request": {
        "url": "https://api.contoso.com/*"
      },
      "responses": [
        { "statusCode": 500 },
        { "statusCode": 502 },
        {
          "statusCode": 503,
          "headers": [
            { "name": "Retry-After", "value": "10" }
          ]
        },
        { "statusCode": 504 }
      ]
    }
  ]
}

Par défaut, le plug-in échoue pour 50 % des requêtes. Vérifiez dans la sortie de Dev Proxy que votre application retente les requêtes GET et n’envoie chaque POST qu’une seule fois. Le proxy de développement ne vérifie pas si votre application attend Retry-After en cas de réponse 503, donc comparez vous-même les temps de requête. Démarrez ensuite Dev Proxy avec --failure-rate 100 pour voir ce que fait votre application lorsque l’API continue d’échouer. Pour plus d’informations, consultez Le taux d’échec des demandes de modification. Pour installer Dev Proxy, consultez Configurer Dev Proxy.

Étapes suivantes

Voir aussi