Quando si chiama un'API, 401 Unauthorized, 403 Forbidden e 429 Too Many Requests sono le tre categorie di errori più comuni.

Appartengono tutti agli errori client 4xx, ma i metodi per risolverli sono completamente diversi:

  • 401: autenticazione non riuscita——il server non riesce a confermare “chi sei”
  • 403: accesso rifiutato——il server comprende la richiesta, ma non ne consente l'esecuzione
  • 429: troppe richieste——la velocità di chiamata o l'utilizzo supera i limiti

Se si ritenta direttamente senza distinguere il tipo di errore, non solo non si risolverà il problema, ma si potrebbe anche creare una tempesta di tentativi, fino a causare ulteriori limitazioni dell'interfaccia.

Questo articolo illustrerà come gestire questi tre tipi di errori tramite checklist di risoluzione dei problemi, comandi curl e codice Node.js.

Comprendere 401, 403 e 429 in una tabella

Codice di stato Significato principale Cause comuni Si dovrebbe ritentare immediatamente
401 Unauthorized Mancano credenziali di autenticazione valide API Key errata, Token scaduto, formato dell'header di autenticazione errato Non si dovrebbe ritentare invariato
403 Forbidden Il server rifiuta di elaborare la richiesta Permessi insufficienti, limitazioni IP o geografiche, policy delle risorse, blocco WAF Di solito no
429 Too Many Requests Le richieste superano i limiti di velocità o quota Concorrenza troppo elevata, QPS oltre il limite, quota esaurita Ritentare dopo aver atteso

Va notato che, sebbene il nome inglese di 401 sia Unauthorized, durante la risoluzione pratica dei problemi è più appropriato intenderlo come “autenticazione non superata”; il 403 è invece solitamente correlato all'autorizzazione o alle policy di accesso.

I. 401 Unauthorized: controllare prima le credenziali di autenticazione

HTTP 401: credenziali API mancanti, non valide o scadute

HTTP 401 Unauthorized indica che alla richiesta mancano credenziali di autenticazione valide necessarie per la risorsa di destinazione. Una risposta 401 standard comunica solitamente al client, tramite l'header di risposta WWW-Authenticate, lo schema di autenticazione che il server si aspetta di utilizzare.

Cause comuni

  1. L'header della richiesta Authorization non è stato inviato
  2. API Key o Access Token compilati in modo errato
  3. Il Token è scaduto o è stato revocato
  4. Schema di autenticazione errato, ad esempio manca Bearer
  5. Le variabili d'ambiente non sono state caricate correttamente
  6. È stata utilizzata una chiave dell'ambiente sbagliato
  7. Quando la richiesta viene inoltrata da un proxy o gateway, l'header di autenticazione viene perso
  8. La differenza di orario tra client e server è troppo elevata, causando l'invalidazione della firma

Errori comuni

L'interfaccia richiede un Bearer Token:

Authorization: Bearer YOUR_ACCESS_TOKEN

Ma il client lo invia così:

Authorization: YOUR_ACCESS_TOKEN

Oppure lo scrive erroneamente così:

Authentication: Bearer YOUR_ACCESS_TOKEN

Entrambe queste situazioni possono restituire 401.

Risoluzione dei problemi con curl

Non limitarti a visualizzare inizialmente il corpo della risposta. Aggiungi -i e controlla contemporaneamente il codice di stato e gli header di risposta:

curl -i "https://api.example.com/v1/profile" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Accept: application/json"

Controlla in particolare:

  • Se Authorization è stato effettivamente inviato
  • Se lo schema di autenticazione è corretto
  • Se sono presenti spazi o ritorni a capo prima o dopo il Token
  • Cosa restituisce WWW-Authenticate
  • Se nel corpo della risposta sono presenti informazioni di errore come invalid_token, expired_token e simili

Se è necessario visualizzare un processo di richiesta più dettagliato, puoi utilizzare:

curl -v "https://api.example.com/v1/profile" \
  -H "Authorization: Bearer $API_TOKEN"

Nota: i log di debug possono contenere Token. Non inviare direttamente i log completi in Issue pubbliche, chat di gruppo o ticket di assistenza.

Si dovrebbe ritentare dopo un 401?

Non ritentare ripetutamente utilizzando le stesse credenziali non valide.

Flusso consigliato:

  1. Controllare se la richiesta include informazioni di autenticazione
  2. Controllare se il Token è scaduto, revocato o copiato erroneamente
  3. Se Refresh Token è supportato, aggiornare una volta il token di accesso
  4. Ritentare una volta utilizzando il nuovo Token
  5. Se continua a restituire 401, interrompere i tentativi e registrare l'errore

Se si utilizza un'API Key fissa, è necessario controllare lo stato della chiave o sostituirla con una chiave valida, anziché ritentare in un ciclo.

II. 403 Forbidden: l'autenticazione potrebbe essere riuscita, ma la richiesta viene comunque rifiutata

HTTP 403: richiesta rifiutata a causa di permessi o policy di accesso

403 Forbidden indica che il server ha già compreso la richiesta, ma ne rifiuta l'elaborazione. Per un tipico errore di autorizzazione, anche una nuova autenticazione non risolverà automaticamente il problema; se non si modifica la richiesta o la configurazione dei permessi, le richieste ripetute continueranno solitamente a fallire.

Cause comuni

  • L'account o la chiave corrente non dispone dei permessi necessari
  • Lo Scope del Token è insufficiente
  • È stata effettuata una richiesta di accesso a una risorsa che non appartiene al progetto o tenant corrente
  • L'IP di origine non è incluso nella whitelist
  • La regione geografica di origine della richiesta è soggetta a limitazioni
  • Blocco da parte di WAF, firewall o sistemi anti-abuso
  • Account, progetto o risorsa disattivati
  • L'interfaccia è disponibile solo per piani o ruoli specifici
  • La firma è valida, ma l'ambito della risorsa nella firma non corrisponde
  • In scenari browser, limitazioni dovute a policy CSRF, Origin o Referer

Differenza tra 401 e 403

È possibile giudicarla rapidamente con due frasi:

  • 401: il server non riesce a confermare chi sei
  • 403: il server conosce o comprende la tua identità e richiesta, ma non ti consente di farlo

Ad esempio, un membro ordinario utilizza un Token valido per chiamare l'interfaccia “elimina organizzazione”:

curl -i -X DELETE \
  "https://api.example.com/v1/organizations/org_123" \
  -H "Authorization: Bearer $API_TOKEN"

Se il Token è valido, ma l'account non è un amministratore dell'organizzazione, il server potrebbe restituire:

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
  "error": "insufficient_permissions",
  "message": "Administrator role is required."
}

Ordine di risoluzione dei problemi per il 403

1. Leggere il corpo della risposta

Cercare prioritariamente il codice di errore, i ruoli o permessi mancanti, lo Scope richiesto, l'ID della risorsa rifiutata, nonché suggerimenti relativi a IP, regione geografica o policy di sicurezza.

2. Controllare lo Scope del Token

Ad esempio, per leggere dati potrebbe essere necessario solo data:read, ma per creare dati potrebbe essere necessario data:write. Un Token valido non significa disporre di tutti i permessi.

3. Controllare l'appartenenza della risorsa

Verificare che l'ID del progetto, l'ID dell'organizzazione, l'ID del tenant, l'ID utente, la regione o l'ambiente appartengano allo stesso account o ambito di autorizzazione delle credenziali correnti.

4. Controllare le policy di rete e sicurezza

Se il codice viene eseguito correttamente in locale ma restituisce 403 dopo il deployment, è necessario controllare principalmente l'IP di uscita del server, la whitelist IP, la configurazione del proxy, il CDN, il WAF, la regione di origine della richiesta e le intestazioni della richiesta correlate.

Non trarre conclusioni basandosi solo sul codice di stato

Le implementazioni API nel mondo reale non sono necessariamente del tutto coerenti. Alcune piattaforme possono restituire 403 quando viene attivato il rate limiting, invece di 429. Ad esempio, la GitHub REST API può restituire 403 o 429 quando viene superato il limite di velocità, e indicare lo stato della limitazione tramite intestazioni di risposta come x-ratelimit-remaining, x-ratelimit-reset o retry-after.

Pertanto, quando si incontra un 403, è necessario controllare anche in modo completo:

  • Il codice di errore di business nel corpo della risposta
  • Retry-After
  • X-RateLimit-Remaining
  • X-RateLimit-Reset
  • La documentazione ufficiale della piattaforma

Un 403 deve essere ritentato?

Per i 403 causati da autorizzazioni insufficienti, limitazioni IP o policy sulle risorse, ritentare senza modifiche non ha senso.

La procedura corretta consiste nel modificare le autorizzazioni o il Token Scope, utilizzare l'account o il progetto corretto, regolare la whitelist e le policy di sicurezza, correggere l'ID della risorsa e confermare se il servizio o il piano supporta questa API. Solo quando la piattaforma dichiara chiaramente che questo 403 rappresenta effettivamente una limitazione temporanea, si dovrebbe attendere e riprovare secondo le regole del rate limiting.

Tre, 429 Too Many Requests: prima rallentare, poi riprovare

HTTP 429: la richiesta API è soggetta a rate limiting, occorre attendere e riprovare con backoff

429 Too Many Requests indica che il client ha inviato troppe richieste in un certo periodo di tempo, ovvero è stato attivato il limite di velocità. Il server può indicare al client tramite Retry-After quanto tempo deve attendere prima di riprovare.

Cause comuni

  • Troppe richieste in un breve periodo di tempo
  • Numero di attività concorrenti troppo elevato
  • Più servizi condividono la stessa API Key
  • Il codice di retry non dispone di un meccanismo di attesa
  • Le attività pianificate vengono eseguite simultaneamente
  • Le richieste non sono memorizzate nella cache e recuperano ripetutamente gli stessi dati
  • La quota di un singolo account, IP o progetto è esaurita
  • Limiti di utilizzo o saldo del piano

Controllare prima le intestazioni della risposta

curl -i "https://api.example.com/v1/resources" \
  -H "Authorization: Bearer $API_TOKEN"

Prestare particolare attenzione a:

Retry-After: 30
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1710000000

I nomi delle intestazioni di risposta possono variare tra le piattaforme; fare riferimento alla documentazione della piattaforma.

Gestire correttamente Retry-After

I due formati comuni di Retry-After sono il numero di secondi o una data HTTP:

Retry-After: 30
Retry-After: Wed, 21 Oct 2026 07:28:00 GMT

Il client dovrebbe preferibilmente supportare entrambi i formati.

Perché non si può riprovare immediatamente?

Se si riprova immediatamente dopo che una richiesta è stata limitata, anche la nuova richiesta verrà ancora limitata; più client potrebbero inoltre riprovare contemporaneamente, creando un “thundering herd”. Un approccio più sicuro consiste nel:

  1. Rispettare prioritariamente Retry-After
  2. Quando non è presente un tempo di attesa esplicito, utilizzare il backoff esponenziale
  3. Aggiungere jitter casuale al tempo di attesa
  4. Impostare un numero massimo di tentativi
  5. Restituire un errore chiaro dopo aver raggiunto il limite

Node.js: gestione sicura di 429

L'esempio seguente utilizza il fetch integrato di Node.js, analizzando prioritariamente Retry-After; se il server non fornisce questa intestazione di risposta, utilizza il backoff esponenziale con jitter casuale.

const sleep = (ms) =>
  new Promise((resolve) => setTimeout(resolve, ms));

function parseRetryAfter(value) {
  if (!value) return null;

  const seconds = Number(value);
  if (Number.isFinite(seconds) && seconds >= 0) {
    return seconds * 1000;
  }

  const timestamp = Date.parse(value);
  if (!Number.isNaN(timestamp)) {
    return Math.max(0, timestamp - Date.now());
  }

  return null;
}

async function fetchWithRetry(url, options = {}, config = {}) {
  const {
    maxRetries = 3,
    baseDelayMs = 1000,
    maxDelayMs = 30_000,
  } = config;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) {
      return response;
    }

    if (attempt === maxRetries) {
      throw new Error(
        `请求持续受到限流,已达到最大重试次数:${maxRetries}`
      );
    }

    const retryAfterMs = parseRetryAfter(
      response.headers.get("retry-after")
    );

    const backoffCap = Math.min(
      maxDelayMs,
      baseDelayMs * 2 ** attempt
    );

    const jitterMs = Math.floor(Math.random() * backoffCap);
    const delayMs = retryAfterMs ?? jitterMs;

    console.warn(
      `收到 429,第 ${attempt + 1} 次等待 ${delayMs}ms 后重试`
    );

    await sleep(delayMs);
  }

  throw new Error("请求失败");
}

Esempio di chiamata:

const response = await fetchWithRetry(
  "https://api.example.com/v1/resources",
  {
    headers: {
      Authorization: `Bearer ${process.env.API_TOKEN}`,
      Accept: "application/json",
    },
  },
  {
    maxRetries: 3,
    baseDelayMs: 1000,
    maxDelayMs: 30_000,
  }
);

if (!response.ok) {
  const errorBody = await response.text();
  throw new Error(`API 请求失败:${response.status} ${errorBody}`);
}

const data = await response.json();
console.log(data);

Quando si ritentano richieste POST, bisogna considerare anche l'idempotenza

Non tutte le richieste sono adatte al retry automatico. Le richieste di lettura come GET e HEAD sono generalmente più facili da ritentare in modo sicuro. Per richieste POST come la creazione di ordini, l'addebito o l'invio di messaggi, il client potrebbe aver già inviato correttamente la richiesta ma non aver ricevuto la risposta a causa di un'interruzione di rete. In questo caso, riprovare direttamente potrebbe causare operazioni duplicate.

Se la piattaforma lo supporta, è necessario impostare una chiave di idempotenza per le operazioni di scrittura:

curl -i -X POST "https://api.example.com/v1/orders" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-20260331-0001" \
  -d '{
    "product_id": "prod_123",
    "quantity": 1
  }'

Il nome dell'intestazione della chiave di idempotenza e il periodo di validità sono determinati dalla piattaforma specifica; fare riferimento alla documentazione API corrispondente.

Checklist per il troubleshooting in ambiente di produzione

Quando si riceve 401

  • La richiesta include un'intestazione di autenticazione?
  • Lo schema di autenticazione, come Bearer, è corretto?
  • Il Token è scaduto, revocato o copiato in modo errato?
  • Viene utilizzata la chiave dell'ambiente corretto?
  • Il proxy o il gateway ha rimosso l'intestazione di autenticazione?
  • L'ora del client è precisa?
  • È possibile aggiornare una volta il Token in modo sicuro?

Quando si riceve 403

  • Il Token dispone dello Scope richiesto
  • L'account corrente dispone del ruolo richiesto
  • La risorsa appartiene al progetto o al tenant corrente
  • L'IP in uscita è presente nella whitelist
  • È soggetto a limitazioni regionali, WAF o a policy di sicurezza
  • Il corpo della risposta indica chiaramente autorizzazioni o limitazione della frequenza
  • Sono presenti informazioni sulla limitazione della frequenza nelle intestazioni della risposta

Ricevuto 429

  • È stato letto Retry-After
  • Sono state controllate le intestazioni della risposta relative alla limitazione della frequenza
  • Vengono utilizzati backoff esponenziale e jitter casuale
  • È stato impostato un numero massimo di tentativi
  • La concorrenza è limitata
  • I risultati delle query ripetute vengono memorizzati nella cache
  • È possibile unire o inviare richieste in batch
  • È stata raggiunta la quota del piano o il limite di utilizzo dell'account

Quali informazioni diagnostiche si consiglia di registrare?

Si consiglia di registrare nei log l'ora della richiesta, il nome host e il percorso dell'API, il metodo HTTP, il codice di stato, il codice di errore aziendale, request-id o trace-id, Retry-After, la quota residua della limitazione della frequenza e l'orario di ripristino, il numero di tentativi e il tempo di attesa effettivo.

Ma non registrare l'API Key completa, l'Access Token completo, il Refresh Token, la password dell'utente o informazioni personali sensibili nel corpo della richiesta.

Regola mnemonica finale

401: correggi prima le credenziali, non riprovare con il vecchio Token.
403: correggi prima i permessi o la policy, non ripetere la richiesta così com'è.
429: rispetta il tempo di attesa, applica backoff, riduci la velocità e limita la concorrenza.

Il codice di stato è solo il punto di ingresso per la risoluzione dei problemi, non è l'intera risposta. Un approccio affidabile consiste nel combinare il codice di stato HTTP, il codice di errore aziendale nel corpo della risposta, le intestazioni della risposta pertinenti, la documentazione della piattaforma, l'ID della richiesta e i log del server, trasformando gli “errori dell'interfaccia” in un meccanismo ingegneristico osservabile, recuperabile e manutenibile.

Riferimenti