Coduri de eroare API și cele mai bune practici
1) De ce să standardizați erorile
Predictibilitate pentru clienți: un singur format și un singur comportament de retras.
Accelerare depanare: 'trace _ id'/' request _ id', stabil' error _ code '.
Securitate: Urmele/configurațiile SQL/stack nu se vor scurge.
Observabilitate: raportarea taxonomiei de eroare (validare, cote, timeout-uri etc.).
2) Principii de bază
1. Un singur format de răspuns pentru toate 4xx/5xx (și pentru 2xx cu erori parțiale - o schemă separată).
2. Clear HTTP semantica: starea corectă este cea mai importantă.
3. Două niveluri de cod: transport ('status') și domain stable 'error _ code'.
4. Recuperabil vs Neretriabil: specificați explicit și dați un indiciu despre back-off.
5. Securitate implicită: detalii - numai clientului cu drepturi; fără urme interne.
6. Localizare: codul mașinii rămâne stabil, text - traducem.
3) Format de eroare unic (bazat pe RFC 7807)
Recomandat JSON (extins „aplicare/problemă + json”):json
{
"type": "https://api. example. com/errors/validation_failed",
"title": "Validation failed",
"status": 422,
"error_code": "VAL_001",
"detail": "Field 'email' must be a valid address",
"instance": "req_01HZY...93",
"trace_id": "a1b2c3d4e5f6",
"retriable": false,
"errors": [
{"field": "email", "code": "email_invalid", "message": "Invalid email"}
],
"hint": "Fix payload and retry",
"meta": {"docs": "https://docs. example. com/errors#VAL_001"}
}
Necesar: 'type', 'title', 'status', 'error _ code', 'trace _ id'.
Opţional: „erori []” (pe câmpuri), „recuperabil”, „indiciu”, „meta”.
- 'Continut-Type: aplicatie/problema + json'
- "X-Request-ID'/" Traceparent" (W3C)
- (pentru 429/503) „Retry-After” (secunde sau dată)
4) Semantica statusurilor HTTP (fuzionarea „clasice” și practica)
2xx (succes nuanțat)
200 OK este un succes comun.
201 Creat - Locație.
202 Acceptat - asincron în coadă (dă 'status _ url').
207 Multi-Status - succes parțial (evitați dacă este posibil).
4xx (eroare client)
400 Cerere proastă - sintaxă/format, dar nu validarea câmpului (de preferință 422).
401 Neautorizat - nu/token nevalid. Să 'WWW-Authenticat'.
403 Interzis - tokenul este valabil, dar nu există suficiente drepturi (RBAC/ABAC/limite).
404 Nu a fost găsit - nici o resursă/punct final.
409 Conflict - blocare optimă, idempotență.
410 Plecat - punct final eliminat definitiv.
412 Condiția prealabilă a eșuat - ETag/If-Match a eșuat.
415 Tip media nesusţinut - Nevalid 'Tip de conţinut'.
422 Entitate de neprelucrat - validarea regulilor de afaceri.
429 Prea multe cereri - a depășit cotele/viteza (a se vedea § 7).
5xx (eroare de server)
Eroare internă a serverului 500 - eroare bruscă; să nu dezvăluie detalii.
502 Bad Gateway - Eroare în amonte.
503 Service Indisponibil - degradare/supraîncărcare, dă 'Retry-After'.
504 Gateway Timeout - backend timeout.
5) Taxonomia domeniului 'error _ code'
Vă recomandăm următoarele intervale:- „AUTH _” - autentificare/autorizare.
- 'VAL _' - validarea datelor de intrare.
- 'RATELIMIT _' - cote și viteză.
- 'IDEMP _' - idempotence/duplicates.
- 'CONFLICT _' - versiuni/stare.
- 'REP _' - dependencies (PSP/DNS/SMTP).
- „PAY _” - erori de afaceri ale domeniului de plată.
- 'SEC _' - securitate (semnături, HMAC, mTLS).
- „INT _” - brusc intern.
- Stabilitate în timp (back-compat).
- Descrieri și exemple în directorul de eroare (docs + machine-readable JSON).
6) Retriable vs Neretriable
Domenii:- 'retriable: true' falses '
- Dacă „adevărat” - în mod necesar „Retry-After” (în câteva secunde) sau contract „exponențial back-off (începând de la 1-2 s, max 30-60 s)”.
Recuperabil de obicei: „502/503/504”, unele „500”, „429” (după fereastră).
Nerecuperabil: „400/401/403/404/ 409/410/415/422”.
7) Limită de rată și erori de cotă (429)
Corp:json
{
"type": "https://api. example. com/errors/rate_limited",
"title": "Rate limit exceeded",
"status": 429,
"error_code": "RATELIMIT_RPS",
"detail": "Too many requests",
"retriable": true
}
Titluri:
- 'Retry-After: 12'
- „X-RateLimit-Limit”, „X-RateLimit-Reset”, „X-RateLimit-Reset”
- Для квот: „X-Cota-limită”, „X-Cota-rămasă”, „X-Cota-Reset”
8) Idempotența și conflictele
În cererile de scriere - „Idempotency-Key” (unic în 24-72 de ore).
Încercați din nou conflictul → 409 Conflict cu 'error _ code: "IDEMP_REPLAY"'.
Conflict de versiune de resurse pentru ETag → 412 Condiție prealabilă eșuată.
În răspuns, atașați a 'resource _ id'/' status _ url' pentru o re-cerere sigură.
9) Validare și 422
Returnați o listă de erori în funcție de câmp:json
{
"status": 422,
"error_code": "VAL_001",
"errors": [
{"field":"email","code":"email_invalid","message":"Invalid email"},
{"field":"age","code":"min","message":"Must be >= 18"}
]
}
Reguli:
- Nu duplicați același lucru în 400 - 422 preferat pentru validarea afacerii.
- Mesajele pot fi citite de oameni; „cod” poate fi citit automat.
10) Securitatea erorilor
Niciodată: stiva urme, SQL, căi de fișiere, nume de gazdă private.
Editați PII; fii cu ochii pe GDPR/DSAR.
Pentru semnătură/HMAC, distingeți între 'SEC _ SIGNATURE _ MISMATCH' (403) și 'SEC _ TIMESTAMP _ SKEW' (401/403) cu promptul „check ± time 5 min”.
11) Corelație și observabilitate
Adăugați întotdeauna 'trace _ id'/' X-Request-ID' și parcurgeți jurnalele/piesele.
Erori agregate by 'error _ code' and 'status' → tablouri de bord „erori de top”, „noi vs cunoscute”.
Alerte: 5xx/422/429 spike, p95 latență, cota de erori.
12) gRPC/GraphQL/Webhooks - mapări
gRPC ↔ HTTP
GraphQL
Transport 200, dar 'erori []' în interior - add' extensii. cod 'и' trace _ id'.
Pentru „fatal” (autentificare/cote) - o 401/403/429 HTTP reală este mai bună.
Webhooks
Luați în considerare numai destinatarii 2xx de succes.
Retrai cu back-off exponențial, 'X-Webhook-ID',' X-Signature '.
410 de la destinatar - oprirea retraiului (punctul final eliminat).
13) Versionarea erorilor
„type ”/„ error _ code” - stabil; nou - doar adăugați.
Când schimbați schema corpului, ridicați versiunea minoră a API sau "problemă + json; v = 2 '.
Documentație: tabel de coduri + exemple; erori de changelog.
14) Documentație (fragmente OpenAPI)
Răspunsuri globale
yaml components:
responses:
Problem:
description: Problem Details content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
schemas:
Problem:
type: object required: [type, title, status, error_code, trace_id]
properties:
type: { type: string, format: uri }
title: { type: string }
status: { type: integer }
error_code: { type: string }
detail: { type: string }
instance: { type: string }
trace_id: { type: string }
retriable: { type: boolean }
errors:
type: array items:
type: object properties:
field: { type: string }
code: { type: string }
message: { type: string }
Exemplu de punct final
yaml paths:
/v1/users:
post:
responses:
'201': { description: Created }
'401': { $ref: '#/components/responses/Problem' }
'422': { $ref: '#/components/responses/Problem' }
'429': { $ref: '#/components/responses/Problem' }
'500': { $ref: '#/components/responses/Problem' }
15) Testarea și calitatea
Contract de încercare: meci 'cerere/problemă + json', câmpuri obligatorii.
Teste negative: toate ramurile 401/403/404/ 409/422/429/500.
Haos/latență: verificarea retribuțiilor pentru 5xx/ 503/504/429 ('Retry-After').
Teste de securitate: fără mesaje interne, mască PII corectă.
Înapoi-compat: clienții vechi înțeleg câmpuri noi (adăugați, nu rupeți).
16) Lista de verificare a implementării
- Single 'problemă + json' + stabil 'error _ code'.
- Corectați semantica HTTP/gRPC/GraphQL.
- Retriable/neretriable + „Retry-After ”/back-off recomandări.
- Anteturile cu limită de rată și comportamentul 429.
- Idempotency ('Idempotency-Key', 409/412).
- Securitate: fără urme/secrete, ediție PII.
- 'trace _ id'/' X-Request-ID' în toate erorile.
- Eroare documentație catalog și exemple.
- Monitorizarea prin taxonomie eroare.
- Autotestele scenariilor negative.
17) Mini-Întrebări frecvente
Cum este 400 diferit de 422?
400 - cerere ruptă (tip sintaxă/conținut). 422 - valabil în sintaxă, dar regulile de afaceri nu au trecut.
Când este 401 și când este 403?
401 - nu/token incorect; 403 - există un token, nu există suficiente drepturi.
E nevoie de Retry-After 'always?
Pentru 429/503, da; pentru restul, recuperabil - este recomandabil să se dea o recomandare explicită.
Total
Bug-uri bine concepute sunt contractul: starea corectă HTTP, single 'problemă + json', stabil 'error _ code', indicii explicite retray, și securitate puternică. Standardizați formatul, documentați taxonomia, adăugați telemetrie și teste - iar API-ul devine previzibil, sigur și prietenos cu integratorul.