Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo descrive le procedure consigliate per l'implementazione, la distribuzione e l'uso di un'API Web RESTful. È incentrato sulla gestione delle richieste, sulle prestazioni, sull'affidabilità, sulla pubblicazione e sul monitoraggio. Per indicazioni sulla modellazione delle risorse e sulla progettazione di API, vedere Progettazione api Web.
Le linee guida per l'architettura si applicano a linguaggi e framework di implementazione. Gli esempi C# illustrano i controller di ASP.NET Core.
Elaborazione delle richieste
Quando si implementa il codice per gestire le richieste, tenere presente quanto segue.
Mantenere la semantica del metodo HTTP e implementare idempotency
Usare GET per restituire i dati delle risorse e HEAD per restituire intestazioni di risposta senza corpo. Non usare uno dei due metodi per creare, aggiornare o eliminare risorse.
GET, HEAD, PUT e DELETE devono essere idempotenti, quindi ripetere una richiesta identica ha lo stesso effetto previsto che eseguirla una sola volta. Ad esempio, DELETE modifica lo stato della risorsa, ma ripetendolo non elimina risorse aggiuntive. La prima richiesta DELETE potrebbe restituire 204 (Nessun contenuto), mentre una richiesta successiva restituisce 404 (Non trovato).
POST e PATCH non sono intrinsecamente idempotenti. Un'operazione PATCH che imposta una proprietà su un valore può essere idempotente, ma non una che incrementa un contatore. Documentare quali operazioni che modificano lo stato i client possono riprovare in sicurezza. Se si supportano i tentativi per le operazioni che non sono naturalmente idempotenti, implementare e documentare il modo in cui il servizio impedisce effetti duplicati. Per la semantica del metodo, vedere Metodi di richiesta HTTP.
Nota
Per linee guida sull'implementazione, consulta il pattern del consumer idempotente. In pratica, identificare innanzitutto se un'operazione è naturalmente idempotente. In caso contrario, applicare l'idempotenza artificiale monitorando gli ID dei messaggi elaborati e gestendo i duplicati in modo proattivo o reattivo.
Valida i dati della richiesta e controlla l'accesso ai campi
Definire modelli di richiesta e risposta che espongono solo i campi nel contratto API. Eseguire il mapping di questi modelli ai dati archiviati anziché associare i corpi delle richieste direttamente alle entità di database o restituire ogni proprietà archiviata. Impedire ai chiamanti di modificare le proprietà protette tramite l'invio di campi aggiuntivi e omettere le proprietà che non sono autorizzati a leggere. Gli oggetti di trasferimento dei dati (DTO) sono un modo per applicare questo confine. Per altre informazioni, vedere Impedire l'over-post in ASP.NET Core.
Verifica campi obbligatori, tipi, intervalli e regole di business prima di salvare le modifiche. Se si supporta la selezione dei campi, convalidare i campi richiesti rispetto a un elenco consentito e le autorizzazioni del chiamante prima di proiettare la risposta. Applicare limiti documentati anche al filtro e all'ordinamento. Per le scelte di contratto corrispondenti, vedere Implementare la paginazione e il filtro.
Limitare gli effetti collaterali delle azioni POST che creano risorse
Quando una richiesta POST crea una risorsa, limitarne gli effetti a tale risorsa e alle risorse direttamente correlate. Ad esempio, la creazione di un ordine potrebbe anche aggiornare l'inventario e generare informazioni di fatturazione. Non deve modificare informazioni non correlate.
Evitare di implementare operazioni POST, PUT e DELETE verbose
Evitare di progettare l'API in base alle operazioni di chat. Ogni richiesta include protocollo, rete e sovraccarico di calcolo. Ad esempio, l'esecuzione di 100 richieste più piccole anziché una richiesta batch più grande comporta un sovraccarico aggiuntivo nel client, nella rete e nel server di risorse. Per i carichi di lavoro che richiedono operazioni in blocco, prendere in considerazione le richieste batch delimitate anziché molte richieste singole.
- Una richiesta GET a una raccolta può recuperare più risorse contemporaneamente.
- Una richiesta POST può contenere i dettagli per più nuove risorse e aggiungerle tutte alla stessa raccolta.
- Una richiesta PUT può sostituire l'intero set di risorse in una raccolta.
- Una richiesta DELETE può rimuovere un'intera raccolta.
Definire dimensioni massime del batch, dimensioni del payload, tempi di esecuzione e concorrenza. Specificare se un batch è atomico o può avere esito parzialmente positivo e restituire un risultato per ogni operazione. Autorizzare e convalidare ogni operazione nel batch.
Se si usa OData, è possibile usare ASP.NET Core OData per implementare le richieste batch. Per altre informazioni, vedere panoramica di OData per ASP.NET Core.
Seguire la specifica HTTP durante l'invio di una risposta
Restituisce il codice di stato HTTP appropriato, le intestazioni e il formato del corpo in modo che i client possano interpretare e gestire la risposta.
Ad esempio, un'operazione POST che crea una risorsa in modo sincrono deve restituire 201 (Creato) e identificare la risorsa nell'intestazione della Location risposta. Un'operazione che accetta il lavoro per un'elaborazione successiva può restituire 202 (accettato), ma tale risposta non indica che il lavoro è riuscito. Non includere un corpo della risposta con 204 (nessun contenuto) o 304 (non modificato). Per altre informazioni, vedere metodi di richiesta HTTP.
Negoziazione dei contenuti di supporto
Un corpo della risposta può contenere dati in formati diversi, ad esempio JSON o XML. I client possono usare l'Accept intestazione della richiesta per specificare i tipi di media supportati. Ad esempio, un client che richiede un'immagine potrebbe specificare image/jpeg, image/gif, image/png. Restituisce una rappresentazione supportata e identifica il tipo di contenuto nell'intestazione della risposta Content-Type.
Se il client non specifica un'intestazione Accept , usare un formato predefinito documentato. I controller di ASP.NET Core usano i formattatori JSON per impostazione predefinita. Definire cosa accade quando l'API non può produrre una rappresentazione richiesta. Ad esempio, configurare l'API per restituire 406 (Non accettabile) anziché restituire silenziosamente un formato non supportato. Per altre informazioni, vedere Formattare i dati di risposta in API Web ASP.NET Core.
Per le richieste con un corpo, controllare il Content-Type della richiesta e accettare solo i formati supportati dall'operazione. Restituisce 415 (Unsupported Media Type) per un formato non supportato. Questo controllo è separato dalla negoziazione della risposta tramite Accept. In ASP.NET Core, configurare i formattatori di input e usare [Consumes] quando è necessario limitare i formati di richiesta di un'operazione. Per altre informazioni, vedere Creare API Web con ASP.NET Core.
Implementa la strategia di versionamento delle API selezionata
Applicare la strategia di controllo delle versioni scelta durante la progettazione in modo coerente nel gateway e nell'applicazione. Instradare le richieste al gestore e allo schema di risposta per la versione selezionata. Definire il comportamento per gli identificatori di versione omessi, in formato non valido e non supportati anziché modificare senza segnalarlo quale contratto riceve un chiamante esistente.
Mantenere i contratti di richiesta e di risposta delle versioni supportate. Quando si introduce una modifica incompatibile, fornire una nuova versione e mantenere disponibili le versioni precedenti supportate. Gestire le richieste dei client meno recenti che omettono i campi facoltativi appena aggiunti. Per altre informazioni, vedere Gestione delle versioni e compatibilità delle API.
Mantenere i collegamenti di risorse generati e le rappresentazioni memorizzate nella cache coerenti con la versione selezionata. Per il controllo delle versioni basato su intestazione, assicurarsi che le cache distinguano le richieste per versioni diverse anziché basarsi solo sull'URI.
Risolvere e autorizzare il contesto del tenant
Per un'API multi-tenant, determinare il tenant per ogni richiesta e verificare che il chiamante autenticato possa accedere a tale tenant. Trattare gli identificatori del tenant nei percorsi, nei nomi host e nelle intestazioni soltanto come input di routing. Per altre informazioni, vedere Eseguire il mapping delle richieste ai tenant in una soluzione multi-tenant.
Usare il contesto tenant autorizzato in modo coerente quando si eseguono query o si aggiornano i dati e quando si distribuisce il lavoro ai processori in background. Se l'applicazione o il gateway memorizza nella cache i dati specifici del tenant, includere l'identificatore del tenant nella chiave della cache. Per indicazioni specifiche del gateway, vedere Funzionalità di Gestione API che supportano la multi-tenancy.
Specificare i collegamenti per supportare la navigazione di tipo HATEOAS e l'individuazione di risorse
Hypertext as the Engine of Application State (HATEOAS) usa collegamenti per consentire ai client di individuare e esplorare le risorse. Ad esempio, una risposta che contiene i dettagli del cliente può includere collegamenti agli ordini del cliente. Descrivere le operazioni supportate da ogni risorsa collegata, ad esempio GET, POST, PUT e DELETE e specificare gli URI corrispondenti. Per altre informazioni, vedi Progettazione API.
Nell'esempio seguente viene usata una rappresentazione di collegamento definita dall'applicazione. Documentare le convenzioni anziché presupporre che i client possano interpretare campi di collegamento personalizzati. Una richiesta GET per un cliente restituisce collegamenti agli ordini del cliente:
GET https://api.contoso.com/customers/2 HTTP/1.1
Accept: application/json
HTTP/1.1 200 OK
...
Content-Type: application/json; charset=utf-8
...
Content-Length: ...
{"customerId": 2,"customerName": "Bert","links": [
{"rel": "self",
"href": "https://api.contoso.com/customers/2",
"action": "GET",
"types": ["text/xml","application/json"]},
{"rel": "self",
"href": "https://api.contoso.com/customers/2",
"action": "PUT",
"types": ["application/x-www-form-urlencoded"]},
{"rel": "self",
"href": "https://api.contoso.com/customers/2",
"action": "DELETE",
"types": []},
{"rel": "orders",
"href": "https://api.contoso.com/customers/2/orders",
"action": "GET",
"types": ["text/xml","application/json"]},
{"rel": "orders",
"href": "https://api.contoso.com/customers/2/orders",
"action": "POST",
"types": ["application/x-www-form-urlencoded"]}
]}
Il record seguente Customer rappresenta i dati del cliente. La sua proprietà Links contiene i collegamenti HATEOAS.
public sealed record Customer(
int CustomerId,
string CustomerName,
IReadOnlyList<Link> Links);
public sealed record Link(
string Rel,
string Href,
string Action,
IReadOnlyList<string> Types);
L'operazione GET recupera i dati del cliente dall'archiviazione, costruisce un Customer record con i relativi collegamenti e restituisce una risposta JSON. Ogni collegamento comprende i seguenti campi:
- Relazione (
Rel) tra la risorsa restituita e la risorsa collegata. In questo esempio,selffa riferimento al cliente eordersfa riferimento alla raccolta ordini del cliente. - Collegamento ipertestuale (
Href) per l'oggetto descritto dal collegamento, sotto forma di URI. - Tipo di richiesta HTTP (
Action) che può essere inviato all'URI. - Il formato dei dati (
Types) che deve essere fornito nella richiesta HTTP o che può essere restituito nella risposta, a seconda del tipo di richiesta.
I collegamenti HATEOAS illustrati nell'esempio di risposta HTTP indicano che un'applicazione client è in grado di eseguire le operazioni seguenti:
- Richiesta HTTP GET a
https://api.contoso.com/customers/2per recuperare i dettagli del cliente come XML o JSON. - Richiesta HTTP PUT a
https://api.contoso.com/customers/2per modificare i dettagli del cliente. Il corpo della richiesta usa questo formato:application/x-www-form-urlencoded. - Richiesta HTTP DELETE per
https://api.contoso.com/customers/2per eliminare il record del cliente. Questa operazione non richiede alcun corpo della richiesta e non restituisce alcun corpo della risposta. - Richiesta HTTP GET a
https://api.contoso.com/customers/2/ordersper recuperare gli ordini del cliente come XML o JSON. - Richiesta HTTP POST a
https://api.contoso.com/customers/2/ordersper creare un ordine per il cliente. Il corpo della richiesta usa questo formato:application/x-www-form-urlencoded.
Gestione delle eccezioni
Se un'operazione genera un'eccezione non gestita, prendere in considerazione le indicazioni seguenti.
Gestire le eccezioni e restituire una risposta significativa ai clienti.
Gestire le eccezioni in modo coerente e restituire una risposta di errore significativa che sia sicura da condividere con i client. Non restituire eccezioni, tracce dello stack o dettagli di implementazione interni nelle risposte di produzione. Restituisce un codice di stato HTTP che riflette l'errore anziché restituire il codice di stato 500 per ogni situazione. Ad esempio, se una richiesta utente causa un aggiornamento del database che viola un vincolo (ad esempio il tentativo di eliminare un cliente con ordini in sospeso), restituire 409 (Conflitto) e una spiegazione sicura. Restituisce 400 (richiesta non valida) per errori di input o di convalida delle richieste in formato non valido, non per errori imprevisti del server. Per le definizioni di stato HTTP, vedere Codici di stato. Per indicazioni sull'implementazione, vedere Gestire gli errori in ASP.NET Core.
Il controller seguente esegue il mapping dei risultati del dominio previsti alle risposte HTTP. L'operazione del repository controlla l'autorizzazione e gli ordini in sospeso come parte dell'operazione di eliminazione. Gli errori imprevisti vengono propagati alla gestione centralizzata delle eccezioni anziché essere intercettati silenziosamente in ogni azione.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Authorize]
[Route("customers")]
public sealed class CustomersController(ICustomerRepository repository) : ControllerBase
{
[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteCustomer(int id, CancellationToken cancellationToken)
{
var outcome = await repository.DeleteAuthorizedAsync(id, User, cancellationToken);
return outcome switch
{
DeleteOutcome.Deleted => NoContent(),
DeleteOutcome.NotFound => NotFound(),
DeleteOutcome.HasOutstandingOrders => Conflict(new ProblemDetails
{
Status = StatusCodes.Status409Conflict,
Title = "The customer has outstanding orders."
}),
_ => throw new InvalidOperationException("Unknown deletion outcome.")
};
}
}
public enum DeleteOutcome
{
Deleted,
NotFound,
HasOutstandingOrders
}
Important
Non includere informazioni che potrebbero essere utili per un utente malintenzionato che tenta di ottenere l'accesso non autorizzato all'API.
Il livello di hosting può rifiutare le richieste prima che raggiungano l'API. Ad esempio, le autenticazioni non riuscite possono comportare risposte 401 (non autorizzate). Dopo l'autenticazione, verificare che il chiamante sia autorizzato ad accedere alla risorsa richiesta. Restituisce 403 (Forbidden) quando l'autorizzazione non riesce.
Gestire le eccezioni in modo coerente e registrare le informazioni sugli errori
Per gestire le eccezioni in modo coerente, è consigliabile implementare una strategia globale di gestione degli errori nell'intera API Web. Registrare le informazioni di diagnostica sul server, ma escludere segreti, token di accesso e dati personali sensibili. Oscura i valori sensibili prima di scrivere voci di log e limita l'accesso al log agli utenti autorizzati. Per altre informazioni, vedere Strategie di architettura per il monitoraggio e il rilevamento delle minacce.
In ASP.NET Core, usare il middleware di gestione delle eccezioni e le risposte Problem Details per un contratto di errore coerente. Configurare le risposte di produzione per omettere i dettagli di diagnostica e includere un identificatore di correlazione che i team di supporto possono usare per individuare i log corrispondenti. Per altre informazioni, vedere Gestire gli errori in ASP.NET Core.
Distinzione tra errori sul lato client ed errori sul lato server
Usare i codici di stato HTTP 4xx per gli errori client e i codici di stato HTTP 5xx per gli errori del server. Mantenere questa distinzione nelle risposte di errore.
Ottimizzazione dell'accesso ai dati sul lato client
Le richieste frequenti e le risposte di grandi dimensioni possono rendere la rete un collo di bottiglia. Ridurre i trasferimenti non necessari quando si implementano il recupero e gli aggiornamenti delle risorse.
Supporto di memorizzazione nella cache sul lato client
Usare l'intestazione di risposta Cache-Control per specificare se i client e i server intermedi possono archiviare una risposta e per quanto tempo rimane aggiornata.
Nell'esempio seguente viene mostrata una richiesta HTTP GET e la relativa risposta che include un'intestazione Cache-Control:
GET https://api.contoso.com/orders/2 HTTP/1.1
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: application/json
Content-Length: 59
{"orderId":2,"productId":4,"quantity":2,"orderValue":10.00}
In questo esempio la risposta rimane valida per 600 secondi. La private direttiva consente l'archiviazione in una cache privata, ad esempio una cache del browser, ma impedisce l'archiviazione in una cache condivisa. Usare public solo per le risposte sicure da condividere con tutti i chiamanti. Usare no-store per le risposte sensibili che non devono essere archiviate.
In un controller ASP.NET Core impostare le intestazioni della cache prima di restituire la risposta:
Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
{
Private = true,
MaxAge = TimeSpan.FromMinutes(10)
};
Nota
La no-cache direttiva consente l'archiviazione, ma richiede la riconvalida prima del riutilizzo. Usare no-store per impedire l'archiviazione.
L'API controlla i criteri della cache e i validator nelle relative risposte. I client e i server intermedi usano tali informazioni per gestire le cache. Impostare queste intestazioni in modo coerente in modo che i chiamanti possano riutilizzare le risposte senza trasferimenti di dati non necessari.
Per determinare max-age, valutare la quantità di obsolescenza dei dati che il carico di lavoro può tollerare. Una risorsa può cambiare mentre una risposta memorizzata nella cache è ancora aggiornata. Alla scadenza della validità, una cache può riconvalidare la risposta anziché eliminarla e scaricare nuovamente l'intera rappresentazione. Non usare un lungo tempo di validità per i dati che richiedono visibilità immediata delle modifiche.
Fornire gli ETag per ottimizzare l'elaborazione delle interrogazioni
Un tag di entità (ETag) è un validatore opaco per una rappresentazione di risorsa selezionata. I client possono conservarla con una risposta memorizzata nella cache e inviarlo in If-None-Match per verificare se la rappresentazione è cambiata. Una richiesta GET o HEAD corrispondente restituisce 304 (non modificato) senza un corpo della risposta.
Generare un validator che rimane coerente tra le istanze dell'applicazione e cambia quando cambia la rappresentazione.
Il controller seguente calcola l’hash dei byte JSON esatti che restituisce e riutilizza le opzioni JSON configurate dell'applicazione.
FileContentResult applica la gestione della risposta condizionale di ASP.NET Core senza wrapper di risultati personalizzati. Il repository restituisce solo un ordine che il chiamante è autorizzato a leggere. Configurare l'autenticazione e l'autorizzazione nell'applicazione host.
using System.Security.Cryptography;
using System.Text.Json;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
[ApiController]
[Authorize]
[Route("orders")]
public sealed class OrdersController(IOrderRepository repository,IOptions<JsonOptions> jsonOptions) : ControllerBase
{
[HttpGet("{id:int}")]
[HttpHead("{id:int}")]
public async Task<IActionResult> GetOrder(int id, CancellationToken cancellationToken)
{
var order = await repository.FindAuthorizedAsync(id, User, cancellationToken);
if (order is null)
{
return NotFound();
}
var payload = JsonSerializer.SerializeToUtf8Bytes(order, jsonOptions.Value.JsonSerializerOptions);
var etag = new EntityTagHeaderValue($"\"{Convert.ToHexString(SHA256.HashData(payload))}\"");
Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
{
Private = true,
MaxAge = TimeSpan.FromMinutes(10)
};
return new FileContentResult(payload, "application/json")
{
EntityTag = etag
};
}
}
Questo esempio memorizza nel buffer la rappresentazione e legge l'ordine dei byte anche per una richiesta condizionale. Usarlo solo per risposte delimitate e non sensibili. Per le risorse di grandi dimensioni, è consigliabile usare un token di versione archiviato che cambia ogni volta che viene modificata la rappresentazione selezionata, in modo da poter convalidare una richiesta senza generare il payload completo. Se la negoziazione del contenuto, la compressione o le trasformazioni del gateway modificano la rappresentazione, assicurarsi che i validator e la variazione della cache rimangano corretti per tale rappresentazione.
Una risposta include l'ETag e il criterio di cache. Gli esempi seguenti mostrano i primi 16 caratteri esadecimali (64 bit) dell'hash SHA-256 del corpo JSON visualizzato, seguito da ... per brevità. Le intestazioni effettive contengono l'hash completo senza i puntini di sospensione.
HTTP/1.1 200 OK
...
Cache-Control: max-age=600, private
Content-Type: application/json
ETag: "3097D1FD51082205..."
Content-Length: 59
{"orderId":2,"productId":4,"quantity":2,"orderValue":10.00}
Suggerimento
Usare Cache-Control: no-store per le risposte che contengono dati sensibili. Per altre risposte specifiche dell'utente che possono essere memorizzate nella cache, usare private per impedire la memorizzazione nelle cache condivise. Per considerazioni sull'implementazione, vedere Middleware di memorizzazione nella cache delle risposte in ASP.NET Core.
Supporta le richieste GET condizionali in modo che i chiamanti possano riconvalidare le risposte memorizzate nella cache senza scaricare nuovamente una rappresentazione invariata. Implementare il comportamento di richiesta e risposta seguente:
Accettare richieste GET condizionali che forniscono un ETag nell'intestazione
If-None-Match, ad esempio:GET https://api.contoso.com/orders/2 HTTP/1.1 If-None-Match: "3097D1FD51082205..."Confrontare l'ETag corrente per la risorsa richiesta (risorsa 2 in questo esempio) con la condizione
If-None-Match.Se la condizione corrisponde, restituire 304 (Non modificato) senza un corpo della risposta.
Se la condizione non è soddisfatta, restituire 200 (OK) con la rappresentazione corrente.
Se la risorsa richiesta non esiste più, restituire 404 (Non trovato).
Nota
Un ETag non rende una risposta sicura per la cache. Applicare le direttive della cache in modo coerente, incluse le risposte condizionali e di errore, e usare no-store per i dati sensibili.
Usare il supporto del framework per le richieste condizionali laddove possibile. Se si implementano i confronti manualmente, gestire tutti i tag di entità forniti, le condizioni con caratteri jolly e le regole di confronto deboli e forti anziché confrontare solo il primo tag. Includere le intestazioni ETag e cache appropriate nelle risposte 304 (non modificate) ed eseguire l'autorizzazione prima di restituire i metadati delle risorse.
Suggerimento
Un validatore archiviato può consentire di verificare se una rappresentazione è cambiata senza recuperare la risorsa completa. Questo approccio può ridurre il trasferimento e l'elaborazione dei dati quando la risorsa è di grandi dimensioni o costosa da recuperare.
Usare ETags per supportare la concorrenza ottimistica
Per evitare aggiornamenti persi, valutare If-Match le precondizioni sulle richieste di modifica dello stato rispetto all'ETag corrente della risorsa. In questo modo si consente all'API di rifiutare una modifica in base a una rappresentazione già modificata da un'altra operazione. Implementare il comportamento seguente:
Accettare le richieste di aggiornamento che identificano la versione prevista nell'intestazione
If-Match. La seguente richiesta PUT aggiorna l'ordine 2. Usa l'ETag della risposta GET precedente, abbreviato nello stesso modo. Il tag identifica la rappresentazione esistente, non il nuovo corpo della richiesta:PUT https://api.contoso.com/orders/2 HTTP/1.1 If-Match: "3097D1FD51082205..." Content-Type: application/x-www-form-urlencoded Content-Length: 37 productId=3&quantity=5&orderValue=250Confronta l'ETag corrente per la risorsa richiesta (risorsa 2 in questo esempio) con la condizione
If-Match.Se la precondizione corrisponde, eseguire l'aggiornamento in modo atomico e restituire la risposta di esito positivo documentato, ad esempio 204 (Nessun contenuto). Un'intestazione
Locationnon è necessaria semplicemente perché è stata aggiornata una risorsa esistente. Restituisce un ETag solo in una risposta PUT riuscita quando soddisfa i requisiti del validator HTTP per la rappresentazione archiviata.Se la condizione non corrisponde, restituire 412 (Precondition Failed). In questo esempio non viene restituito alcun corpo della risposta.
Se la risorsa da aggiornare non esiste più, restituire 404 (Non trovato).
Documentare le risposte con esito positivo e in conflitto in modo che i chiamanti possano determinare se un aggiornamento è riuscito o se devono recuperare la rappresentazione corrente prima di inviare un'altra modifica.
Per le operazioni che devono impedire gli aggiornamenti persi, richiedere una If-Match precondizione e restituire 428 (Precondition Required) quando manca. Usare un confronto rigoroso per If-Match.
Verificare una versione nella memoria dell'applicazione e quindi salvare in modo incondizionato crea una race condition. Applicare il confronto delle versioni e la scrittura in modo atomico nell'archivio dati. Ad esempio, usare un token di concorrenza del database in modo che l'aggiornamento abbia esito positivo solo se la versione archiviata corrisponde ancora alla versione usata per valutare la richiesta.
In Entity Framework (EF) Core configurare un token di concorrenza e gestire DbUpdateConcurrencyException anziché sovrascrivere una modifica simultanea. Nel codice di accesso ai dati dell'API, non sostituire automaticamente la versione prevista né riprovare un aggiornamento del database in conflitto, a meno che la semantica dell'operazione non lo consenta. Per altre informazioni, vedere Gestione dei conflitti di concorrenza.
Gestione di richieste e risposte di grandi dimensioni
I corpi di richiesta e risposta di grandi dimensioni utilizzano memoria, larghezza di banda e capacità di connessione dell'API. Implementa limiti di streaming e risorse in modo che i trasferimenti di grandi dimensioni non esauriscano il servizio. Quando si gestiscono quantità significative di dati, tenere presente quanto segue:
Ottimizzare richieste e risposte contenenti oggetti di grandi dimensioni
Per oggetti di grandi dimensioni, ad esempio immagini o altri dati binari, supporta i caricamenti e i download in streaming.
Usare le API di streaming asincrone e consentire al server di selezionare la modalità di framing del trasferimento per la versione HTTP negoziata. Non aggiungere Transfer-Encoding: chunked manualmente a ogni parte di una risposta. Lo streaming non è limitato alla codifica in blocchi HTTP/1.1. Evitare di memorizzare nel buffer un'intera richiesta o risposta non limitata nella memoria dell'applicazione.
Impostare i limiti del corpo della richiesta, i limiti di caricamento, i timeout e i criteri di annullamento ai livelli dell'applicazione e dell'hosting. Rifiutare una richiesta sovradimensionata con 413 (contenuto troppo grande) prima di avviare la risposta.
La compressione HTTP può ridurre le dimensioni del trasferimento, a costo di elaborazione aggiuntiva nel server e nel client. Ad esempio, un client può inviare Accept-Encoding: gzip. Se il server restituisce contenuto compresso gzip, identificare la codifica usando Content-Encoding: gzip.
Configurare la compressione tramite la piattaforma di hosting o il middleware e misurare i compromessi di CPU e larghezza di banda sia sul lato client che sul lato server.
- Evitare di ricomprimere i formati già compressi.
- Prima di abilitare la compressione per le risposte HTTPS generate in modo dinamico, valutare i rischi di compressione, ad esempio BREACH, e applicare mitigazioni appropriate. Anche se si disabilita la compressione HTTPS nel middleware, il server di hosting potrebbe essere configurato per applicare la compressione.
- Assicurarsi che la variazione della cache e gli ETag rimangano corretti quando cambia la codifica del contenuto.
Per indicazioni sull'implementazione della compressione e considerazioni sulla sicurezza, vedere Compressione delle risposte in ASP.NET Core.
Supporta download parziali di risorse di grandi dimensioni
Se l'API supporta download parziali di risorse di grandi dimensioni, annunciare tale funzionalità con Accept-Ranges. Gestire le richieste HEAD restituendo i metadati della risorsa, inclusa la dimensione totale Content-Length, senza un corpo della risposta. Per le richieste GET che specificano un intervallo di byte supportato, restituire 206 (contenuto parziale), un Content-Length per la parte restituita e un oggetto Content-Range che identifica tale parte della risorsa. Questo contratto di risposta consente ai chiamanti di recuperare parti di una risorsa senza richiedere all'API di restituire l'intero oggetto.
Le richieste HTTP HEAD e le risposte parziali sono descritte in dettaglio in Progettazione API.
Gestire 100-Continue per caricamenti di grandi dimensioni
Per un caricamento HTTP/1.1 di grandi dimensioni, un client può inviare intestazioni di richiesta con Expect: 100-continue e attendere prima di trasmettere il corpo. Il server può inviare una risposta provvisoria 100 (Continua) o rifiutare la richiesta senza ricevere il corpo completo. Questo scambio fa parte di una richiesta, non una richiesta vuota preliminare seguita da una seconda richiesta completa.
Configurare e testare il modo in cui lo stack di hosting e il gateway gestiscono le richieste con e senza Expect: 100-continue. Verificare il comportamento dell'API quando accetta o rifiuta un caricamento e misurare gli effetti sull'uso delle risorse server e sulla latenza delle richieste.
Supporto della paginazione per le richieste che potrebbero restituire un numero elevato di oggetti
Il recupero di un'intera raccolta di grandi dimensioni può aumentare l'elaborazione del server, il traffico di rete e la latenza.
Validare gli input di paginazione sul server e applicare una dimensione massima della pagina. Il controller seguente illustra la convalida delle richieste. Il valore predefinito è 10 risultati e rifiuta limiti al di fuori di 1 a 100 o offset al di fuori di 0 a 10.000. Questi limiti sono illustrativi. Scegliere i limiti in base al carico di lavoro e ai test di carico. Quando si usa [ApiController], gli errori di convalida producono una risposta 400. Per altre informazioni, vedere Creare API Web con ASP.NET Core.
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Authorize]
[Route("orders")]
public sealed class OrderCollectionsController(IOrderRepository repository) : ControllerBase
{
[HttpGet]
public async Task<ActionResult<IReadOnlyList<Order>>> GetOrders(
[FromQuery, Range(1, 100)] int limit = 10,
[FromQuery, Range(0, 10000)] int offset = 0,
CancellationToken cancellationToken = default)
{
var orders = await repository.ListAuthorizedAsync(limit, offset, User, cancellationToken);
return Ok(orders);
}
}
Un client può richiedere 30 ordini a partire dall'offset 50 usando https://api.contoso.com/orders?limit=30&offset=50.
Oltre alla convalida della richiesta illustrata nell'esempio precedente, includere un collegamento di pagina successiva o un token di continuazione nel contratto di risposta. Ad esempio, restituire gli ordini con una nextLink proprietà impostata su https://api.contoso.com/orders?limit=30&offset=80 quando è disponibile un'altra pagina. Mantenere i filtri, l'ordinamento e la versione dell'API nel collegamento. Ometti nextLink o impostalo su null nell'ultima pagina. Per un esempio di contratto nextLink, vedere Microsoft Graph paging.
Applicare filtri e paginazione nel data store, non dopo il caricamento dell'intera raccolta. Usare un ordinamento deterministico. Per raccolte grandi o soggette a modifiche frequenti, valutare la paginazione basata su cursore per evitare offset costosi e limiti di pagina instabili.
Suggerimento
Applicare limiti documentati sulla complessità delle query, sulle espressioni di filtro e sulle dimensioni delle richieste. Testa i limiti di ogni gateway, proxy e server nel percorso della richiesta.
Gestione di velocità di risposta, scalabilità e disponibilità
Definire obiettivi di latenza, velocità effettiva e disponibilità per le operazioni critiche dell'API. Progettare ed eseguire test per il traffico previsto, i picchi e i guasti delle dipendenze. La gestione con scalabilità orizzontale e senza stato supporta tali obiettivi. Prendere in considerazione i requisiti di implementazione seguenti.
Offrire supporto asincrono per le richieste a esecuzione prolungata
Per il lavoro che supera la durata di una normale richiesta HTTP, convalidare e autorizzare la richiesta, registrare in modo permanente il lavoro e restituire 202 (accettato). Non basarsi su un'attività in-process non tracciata per terminare dopo una risposta: il riavvio dell'applicazione, uno scale-in e la distribuzione possono interromperla. Usare una coda durevole e un worker o un flusso di lavoro durevole quando il lavoro deve continuare l'esecuzione nonostante tali eventi. Per le linee guida complete sulla semantica HTTP e sull'implementazione, vedere Modello di Request-Reply asincrono.
Fornire ai chiamanti un modo per recuperare lo stato e il risultato dell'operazione. L'API può anche inviare notifiche ai chiamanti al termine dell'elaborazione.
È possibile fornire una risorsa di stato che i client possono interrogare periodicamente:
- Il client invia la richiesta. Verificare l'input e le autorizzazioni prima di accettare il lavoro.
- Rendere persistente un identificatore e lo stato di un'operazione nell'archiviazione durevole, ad esempio Archiviazione tabelle di Azure e accodare il lavoro per un processore separato, ad esempio usando bus di servizio di Azure. Coordina la persistenza e l'accodamento in modo che un errore tra queste due azioni non comporti la perdita di lavoro accettato.
- Restituisce 202 con un'intestazione
Locationche identifica l'endpoint di stato e un'intestazioneRetry-Afterche controlla la frequenza di polling. Accettare la richiesta solo dopo che il lavoro viene registrato in modo duraturo. - Un worker elabora l'operazione e ne aggiorna lo stato durevole. Rendere l'elaborazione idempotente perché un worker può ricevere più volte lo stesso lavoro. Applicare tentativi limitati a errori temporanei.
- Il client esegue il polling dell'endpoint di stato. Applicare l'autorizzazione a livello di risorsa sia per gli endpoint di stato che per gli endpoint dei risultati. Un identificatore impossibile da indovinare non è autorizzazione.
- Restituisce una rappresentazione dello stato documentata mentre il lavoro è in corso. Al termine, specificare il risultato o un reindirizzamento 303 (See Other) a una risorsa risultato. Segnalare i guasti tramite un contratto di errore coerente e sicuro.
- Definire la conservazione e la pulizia per i record e i risultati delle operazioni. Scadenza dell'operazione di documento, invii duplicati e qualsiasi comportamento di annullamento supportato.
Per i client connessi, è consigliabile usare ASP.NET Core SignalR per le notifiche di completamento. Mantenere disponibile la risorsa di stato durevole in modo che i client possano eseguire il ripristino dopo una disconnessione o una notifica persa. Per altre informazioni, vedere Panoramica di ASP.NET Core SignalR.
Assicurati che ogni richiesta sia senza stato
Non richiedere che una richiesta successiva raggiunga la stessa istanza dell'applicazione di una richiesta precedente. Mantenere lo stato del flusso di lavoro e della risorsa in archivi condivisi appropriati, non esclusivamente nella memoria di processo. Le richieste possono dipendere dallo stato della risorsa durevole senza creare affinità tra istanze del server. La gestione delle richieste senza stato supporta la scalabilità orizzontale.
Comprendi le tue dipendenze downstream
Impostare un timeout per ogni chiamata downstream. Mantenere il tempo totale per le chiamate, i tentativi e i ritardi entro la scadenza della richiesta API e propagare l'annullamento delle richieste alle operazioni downstream.
Ritentare solo in caso di errori temporanei e operazioni sicure da ripetere. Usare un numero limitato di tentativi con backoff e jitter. Limitare i tentativi complessivi di ripetizione per ogni dipendenza e i tentativi per ogni richiesta. Per altre informazioni, vedere Gestione degli errori temporanei.
Usare un circuit breaker quando errori ripetuti di dipendenza potrebbero esaurire la capacità dell'API.
Traccia i clienti e implementa limiti per ridurre le possibilità di attacchi DoS.
Applicare limiti di frequenza delle richieste, concorrenza, payload e tempo di esecuzione. Suddividi i limiti per chiamante autenticato o tenant, laddove possibile. Restituisce 429 (troppe richieste) quando un chiamante supera una frequenza configurata e 503 (servizio non disponibile) per la mancata disponibilità temporanea del servizio. Includi Retry-After laddove appropriato. Se l'API ritenta le chiamate alle dipendenze downstream, limitare tali tentativi in modo da non amplificare l'overload.
I limiti del gateway e dell'applicazione servono a scopi diversi. I limiti del gateway possono proteggere la capacità condivisa. I limiti dell'applicazione possono riflettere i costi operativi e la capacità downstream. Nessuno dei due sostituisce la protezione DDoS a livello di rete o un web application firewall. Per altre informazioni, vedere Pattern di throttling.
Gestire attentamente le connessioni HTTP permanenti
Per le connessioni in ingresso, configurare timeout keep-alive del server e del gateway, timeout delle richieste e limiti di connessione simultanei per il carico di lavoro e il percorso di rete. Non forzare regolarmente la chiusura delle connessioni dopo ogni risposta. Per informazioni sulle impostazioni del server ASP.NET Core, vedere Configurare le opzioni per il server Web Kestrel.
Se l'API stessa chiama servizi HTTP downstream, riutilizzare tali connessioni in uscita. In un'implementazione dell'API .NET usare istanze di lunga durata HttpClient con un'istanza appropriata PooledConnectionLifetimeo usare i client creati da IHttpClientFactory. Smaltire i messaggi di risposta in uscita e i flussi quando non sono più necessari. Queste impostazioni si applicano alle chiamate downstream dell'API, non alle connessioni client in ingresso. Per informazioni dettagliate e avvertenze sulla gestione dei cookie, vedere Linee guida per l'uso di HttpClient.
Pubblicazione e gestione di un'API Web
Distribuire l'API in un ambiente di hosting che soddisfi i requisiti operativi. Considerare le strategie seguenti:
- Usare HTTPS. Autenticare le richieste agli endpoint protetti e applicare l'autorizzazione per ogni risorsa e operazione.
- Ridimensionare l'ambiente di hosting per soddisfare gli impegni relativi ai tempi di risposta man mano che cambiano le richieste.
- Conteggia le richieste se il modello di fatturazione dell'API lo richiede.
- Regolare il traffico e applicare le quote client, se necessario.
- Registrare gli eventi di audit necessari per la conformità e la risposta agli incidenti, ma non registrare credenziali, token o corpi di richiesta e risposta sensibili.
- Monitorare l'integrità dell'host e definire azioni di ripristino, ad esempio il riavvio di un host non integro.
Prendere in considerazione l'uso di una facciata separata che gestisce i problemi di gestione condivisa e inoltra le richieste convalidate all'API. Una facciata può fornire le funzionalità seguenti:
- Agire come un punto di integrazione per più API Web.
- Trasformare i messaggi e convertire i protocolli di comunicazione per i client creati utilizzando diverse tecnologie.
- Memorizzare nella cache richieste e risposte per ridurre il carico sul server che ospita l'API Web.
Mantenere i contratti API e la configurazione del gateway sotto il controllo della versione, convalidare le modifiche nelle pipeline di distribuzione e definire le procedure di rollback. Allineare l'hosting, l'identità, la rete e la governance all'approccio landing zone dell'organizzazione. Per altre informazioni, vedere Che cos'è una zona di destinazione di Azure?.
Test di un'API Web
Usare unit test per convalidare la logica dell'API e test di integrazione per verificarne il comportamento HTTP.
Includi i controlli seguenti:
Testare tutti i percorsi per verificare che richiamino le operazioni corrette nel sistema. Tenere presente che il codice di stato HTTP 405 (metodo non consentito) viene restituito in modo imprevisto. Questo codice di stato può indicare una mancata corrispondenza tra una route e i metodi HTTP (GET, POST, PUT, DELETE) che possono essere gestiti da tale route.
Inviare richieste che usano metodi non supportati da ogni route e verificare la risposta 405 (metodo non consentito) e l'intestazione
Allowdocumentate.Verificare che tutte le route siano protette correttamente e siano soggette ai controlli di autenticazione e autorizzazione appropriati.
Nota
Alcuni aspetti della sicurezza, ad esempio l'autenticazione utente, sono probabilmente di responsabilità dell'ambiente host anziché dell'API Web, ma è comunque necessario includere i test di sicurezza come parte del processo di distribuzione.
Testare la gestione delle eccezioni eseguite da ogni operazione e verificare che una risposta HTTP appropriata e significativa sia passata all'applicazione client.
Verificare che i messaggi di richiesta e risposta siano ben formati. Ad esempio, per una richiesta POST che crea una risorsa, verificare la deserializzazione, l'analisi, la creazione della risorsa e l'intestazione della
Locationrisposta.Testare separatamente i tipi di media della richiesta supportati e non supportati dalla negoziazione del contenuto della risposta. Verificare le risposte 415 (tipo di supporto non supportato) per i formati di richiesta non supportati e gli errori di convalida documentati per i corpi in formato non valido.
Verifica ogni versione dell'API supportata, incluso il routing, la convalida delle richieste e lo schema di risposta. Testare gli identificatori di versione omessi, non validi e non supportati e verificare che le risposte memorizzate nella cache non attraversino i confini tra versioni.
Verificare tutti i collegamenti e gli URI nei messaggi di risposta. Ad esempio, un messaggio HTTP POST deve restituire l'URI della risorsa appena creata. Tutti i collegamenti HATEOAS devono essere validi.
Assicurarsi che ogni operazione restituisca i codici di stato corretti per diverse combinazioni di input. Ad esempio:
- Se una query ha esito positivo, deve restituire il codice di stato 200 (OK).
- Se una risorsa non viene trovata, l'operazione deve restituire il codice di stato HTTP 404 (Non trovato).
- Se il client invia una richiesta che consente di eliminare una risorsa, il codice di stato deve essere 204 (Nessun contenuto).
- Se il client invia una richiesta che crea una nuova risorsa, il codice di stato deve essere 201 (Creato).
Esaminare risposte 5xx impreviste dall'applicazione o dal livello di hosting.
Testare le diverse combinazioni di intestazioni di richiesta che un'applicazione client può specificare e verificare che l'API Web restituisca le informazioni attese nei messaggi di risposta.
Prova le stringhe di query. Se un'operazione può accettare parametri facoltativi (ad esempio richieste di paginazione), testare le diverse combinazioni e l'ordine dei parametri.
Verificare che le operazioni asincrone siano state completate correttamente. Per le risposte di streaming, verificare che l'API non memorizza nel buffer l'intero payload e che gestisca correttamente le disconnessioni e l'annullamento del client. Se l'API fornisce risorse di stato per le operazioni a esecuzione prolungata, verificare che riportino correttamente l'avanzamento dell'operazione e i risultati.
Testa i casi di errore e limite che influiscono sulla correttezza:
- Verificare input minimi, massimi, negativi, in formato non valido e di paginazione e batch eccessivi.
- Seguire i collegamenti di paginazione fino all'ultima pagina. Verificare che i collegamenti mantengano le opzioni di query e che venga restituito il segnale di completamento documentato.
- Verificare che altri campi di input non possano modificare le proprietà protette e che la selezione dei campi non possa esporre dati non autorizzati.
- Verifica gli ETag corrispondenti, non corrispondenti, deboli, multipli e con caratteri jolly e verifica che le risposte 304 non contengano alcun corpo.
- Esegui aggiornamenti simultanei e verifica che l'archivio dati rifiuti le scritture obsolete in modo atomico.
- Verificare che i chiamanti non possano leggere le risorse, i record di stato o le risposte memorizzate nella cache di un altro chiamante.
- Per le API multi-tenant, testare gli identificatori tenant contraffatti o non corrispondenti. Quando la memorizzazione nella cache è abilitata, testare le richieste per lo stesso URI della risorsa da tenant diversi.
- Simula timeout, annullamento client, errori di dipendenza, riavvii del ruolo di lavoro e recapito duplicato del lavoro in background.
- Verificare il timeout downstream e i budget dei tentativi, l'annullamento e il ripristino del circuit breaker.
- Verificare le risposte 429 (troppe richieste) e 503 (servizio non disponibile), il comportamento dei tentativi di riprova e il costo del rifiuto delle richieste quando il sistema è sovraccarico.
Eseguire test di carico su un'infrastruttura simile alla produzione e combinazioni realistiche di operazioni. Definire criteri di superamento e fallimento per velocità effettiva, percentili di latenza, percentuali di errore e saturazione delle risorse. Usare Test di carico di Azure e integrare i controlli di regressione nella pipeline di distribuzione.
Uso di API Management
È consigliabile usare Gestione API di Azure quando è necessario un gateway gestito con l'imposizione dei criteri. Aggiunge costi, un altro hop di rete e una dipendenza nel percorso della richiesta. Scegliere un livello di servizio e una topologia in base ai requisiti di capacità, rete, disponibilità e requisiti regionali; le funzionalità differiscono per livello. Il livello Developer non è destinato ai carichi di lavoro di produzione. Segui le indicazioni del servizio Well-Architected per API Management.
È possibile pubblicare e gestire un'API Web completando questa procedura:
Distribuire l'API Web in una piattaforma di hosting come Servizio app di Azure, App contenitore di Azure, Servizio Azure Kubernetes (AKS) o Macchine virtuali di Azure.
Configurare API Management per instradare le richieste dall'URL del gateway all'API back-end. Un'istanza di Gestione API può instradare le richieste a più API. Più istanze possono anche esporre la stessa API back-end quando le applicazioni necessitano di limiti di accesso diversi.
Nota
I collegamenti HATEOAS nelle risposte devono fare riferimento all'URL del gateway di Gestione API, non all'URL del server back-end.
Importare una definizione OpenAPI sottoposta a controllo versione e verificare che le operazioni importate, i parametri, i requisiti di sicurezza e gli schemi di risposta corrispondano all'implementazione. Controllare le versioni OpenAPI supportate e le limitazioni di importazione. Per altre informazioni, vedere Importare una specifica OpenAPI.
Configurare l'autenticazione e l'autorizzazione per le comunicazioni da client a gateway e da gateway a back-end. Convalida i token di accesso OAuth 2.0 e applica le autorizzazioni necessarie per le richieste client. Per i back-end che supportano l'autenticazione Microsoft Entra ID, preferire un'identità gestita di Gestione API con solo le autorizzazioni necessarie. L'autenticazione del certificato è un'altra opzione. Evitare l'autenticazione di base quando sono disponibili opzioni più sicure. Per altre informazioni, vedere Autenticazione e autorizzazione per le API in Gestione API di Azure.
Nota
Se ti servono chiavi di sottoscrizione di API Management, non usarle come sostituto dell'autenticazione e dell'autorizzazione a livello di risorsa.
Configurare i criteri per l'autenticazione, l'accesso tra le origini, le trasformazioni dei messaggi, il filtro IP, i limiti di frequenza e le quote in base alle esigenze. Configurare la memorizzazione nella cache delle risposte solo per i dati sicuri da memorizzare nella cache. Applicare i criteri nell'ambito appropriato e verificarne il comportamento effettivo per ogni operazione.
Per altre informazioni, vedere Documentazione di Gestione API.
Important
Un gateway non rende privato il back end né sostituisce l'autorizzazione a livello di risorsa. Progettare controlli di accesso back-end, gestione degli errori, capacità e osservabilità per il carico di lavoro nel suo complesso, incluso il gateway. Valutare la ridondanza zonale e regionale rispetto alle funzionalità del livello selezionato. Includi i costi del gateway, l'inserimento e la conservazione dei dati di telemetria e il trasferimento dei dati nel modello di costo.
Supporto degli sviluppatori lato client
Fornire ai consumer di API la documentazione per l'autenticazione, le operazioni, i parametri, i tipi di dati e i codici di risposta.
Documentare le operazioni REST per un'API Web
Pubblicare una definizione OpenAPI che descrive le operazioni, i parametri, gli schemi di richiesta e risposta dell'API e i requisiti di sicurezza. Mantenerlo sotto controllo versione con l'implementazione e verificare che corrisponda al comportamento effettivo dell'API.
Integrare il riferimento API con indicazioni su come gli utenti devono utilizzare correttamente l'API:
- Requisiti di autenticazione e autorizzazioni per ogni operazione.
- Richieste rappresentative, risposte riuscite e risposte di errore.
- Regole di convalida dell'input, limiti di payload, paginazione e limiti di frequenza.
- Comportamento di timeout, sicurezza dei tentativi e requisiti di idempotenza.
- Stato e recupero dei risultati per le operazioni a esecuzione prolungata.
- Aspettative sul versioning e sulla compatibilità.
Mantenere aggiornata la documentazione e gli esempi quando cambia il contratto API.
Implementare un client SDK
Valutare la possibilità di fornire un SDK per i consumer di API. L'SDK può esporre metodi tipizzati che costruiscono richieste, analizzano le risposte e presentano gli errori documentati dell'API.
Valutare la possibilità di generare client tipiti dalla definizione OpenAPI dell'API, ma convalidare il comportamento generato rispetto al servizio. Autenticazione dei documenti, timeout, annullamento, paginazione, risposte agli errori e quali operazioni sono sicure per riprovare. Mantenere allineata la politica di compatibilità del client e dell'API. Il codice generato non rimuove la necessità di test di integrazione.
Monitoraggio di un'API Web
Monitorare l'API, le relative dipendenze e qualsiasi gateway insieme. Definire gli obiettivi e gli avvisi a livello di servizio in base all'impatto sul cliente anziché basarsi solo sull'integrità dell'host.
Monitoraggio diretto di un'API Web
Usare la strumentazione OpenTelemetry per raccogliere tracce, metriche e log ed esportare i segnali in Application Insights o in un altro back-end supportato. Per l’instrumentazione .NET, Node.js e Python, seguire le indicazioni di Microsoft OpenTelemetry Distro. Java usa la distribuzione Monitoraggio di Azure OpenTelemetry. Seguire le linee guida specifiche per il linguaggio per l'abilitazione di OpenTelemetry.
Segnali di monitoraggio che descrivono il comportamento dell'API:
- Volume delle richieste, frequenza di errori e percentili di latenza per operazione
- Latenza, malfunzionamenti e timeout delle dipendenze
- Rifiuti dovuti al rate limit, lavoro simultaneo e saturazione delle risorse
- Anzianità della coda delle operazioni in background, tempo di completamento, errori e tentativi
- Efficacia della cache, quando la memorizzazione nella cache fa parte della progettazione
I dati di telemetria raccolti automaticamente da uno strumento di monitoraggio variano a seconda del linguaggio, delle librerie e della configurazione. Aggiungere la telemetria per le operazioni di dominio e il lavoro in background. Non presupporre che le sessioni del browser, i ruoli utente o tutti i dettagli della richiesta siano automaticamente disponibili. Propagare il contesto di traccia nel gateway, nell'applicazione e nei worker. Configurare il campionamento e la conservazione per bilanciare le esigenze di diagnostica, la riservatezza dei dati e i costi di telemetria.
Usare i test di disponibilità Standard di Application Insights per controlli esterni ricorrenti, se appropriato. Controllare un endpoint di integrità o operazione significativo senza esporre dati sensibili, definire avvisi attuabili e gestire un runbook di risposta.
Monitoraggio di un'API Web tramite Gestione API
Usare le metriche di Monitoraggio di Azure, i log, l'analisi e la diagnostica supportati da API Management per distinguere gli errori del gateway dagli errori back-end. Correlare i dati di telemetria del gateway e dell'applicazione e monitorare gli errori dei criteri, la capacità, la latenza delle richieste e la limitazione della frequenza. I segnali disponibili dipendono dalla configurazione del piano e del gateway.
Seguire le raccomandazioni relative all'osservabilità e alla capacità nelle linee guida del servizio Well-Architected per API Management.
Passaggi successivi
- Panoramica di OData in ASP.NET Core descrive come creare servizi API REST conformi al protocollo OData usando ASP.NET Core.
- ASP.NET Core procedure consigliate illustra le operazioni di I/O asincrone, uso delle risorse e gestione delle risposte.
- Il modello consumer Idempotente fornisce indicazioni sull'implementazione per tenere traccia degli ID dei messaggi elaborati e gestire il recapito duplicato.
- HTTP Semantics definisce i codici di stato HTTP.
- Il modello di Request-Reply asincrono descrive le risorse di stato e lavoro in background durevoli.
- Le procedure consigliate per l'architettura per Gestione API di Azure riguardano affidabilità, sicurezza, costi, operazioni e prestazioni.
- Test di carico di Azure descrive la generazione del carico e i controlli delle prestazioni automatizzati.
- L'opzione OpenTelemetry fornisce indicazioni per la strumentazione e l'esportazione specifiche del linguaggio.