Progettazione APIAPI design

La maggior parte delle applicazioni Web moderne espone API che possono essere usate dai client per interagire con l'applicazione.Most modern web applications expose APIs that clients can use to interact with the application. Un'API Web progettata in modo adeguato deve supportare:A well-designed web API should aim to support:

  • Indipendenza dalla piattaforma.Platform independence. Qualsiasi client deve poter chiamare l'API indipendentemente da come è implementata internamente.Any client should be able to call the API, regardless of how the API is implemented internally. A questo scopo è necessario usare protocolli standard e un meccanismo che consenta al client e al servizio Web di concordare il formato dei dati da scambiare.This requires using standard protocols, and having a mechanism whereby the client and the web service can agree on the format of the data to exchange.

  • Evoluzione del servizio.Service evolution. L'API Web deve avere la possibilità di evolversi e aggiungere funzionalità indipendentemente dalle applicazioni client.The web API should be able to evolve and add functionality independently from client applications. Con l'evoluzione dell'API, le applicazioni client dovranno continuare a funzionare senza modifiche.As the API evolves, existing client applications should continue to function without modification. Tutte le funzionalità dovranno essere individuabili per poter essere usate appieno dalle applicazioni client.All functionality should be discoverable so that client applications can fully use it.

Queste linee guida descrivono gli aspetti da considerare durante la progettazione di un'API Web.This guidance describes issues that you should consider when designing a web API.

Introduzione a RESTIntroduction to REST

Nel 2000, Roy Fielding ha proposto REST (Representational State Transfer) come approccio di architettura per la progettazione di servizi Web.In 2000, Roy Fielding proposed Representational State Transfer (REST) as an architectural approach to designing web services. REST è uno stile architetturale per la creazione di sistemi distribuiti basati su ipermedia.REST is an architectural style for building distributed systems based on hypermedia. REST è indipendente da qualsiasi protocollo sottostante e non è necessariamente collegato a HTTP.REST is independent of any underlying protocol and is not necessarily tied to HTTP. Le implementazioni REST più comuni, tuttavia, usano HTTP come protocollo applicativo e questa guida è incentrata sulla progettazione di API REST per HTTP.However, most common REST implementations use HTTP as the application protocol, and this guide focuses on designing REST APIs for HTTP.

Uno dei vantaggi principali di REST su HTTP è costituito dal fatto che usa standard aperti e non vincola l'implementazione dell'API o le applicazioni client a un'implementazione specifica.A primary advantage of REST over HTTP is that it uses open standards, and does not bind the implementation of the API or the client applications to any specific implementation. Per un servizio Web REST scritto in ASP.NET, ad esempio, le applicazioni client possono usare qualsiasi linguaggio o set di strumenti che può generare richieste HTTP e analizzare risposte HTTP.For example, a REST web service could be written in ASP.NET, and client applications can use any language or toolset that can generate HTTP requests and parse HTTP responses.

Di seguito sono riportati alcuni fondamentali principi di progettazione delle API RESTful che usano HTTP:Here are some of the main design principles of RESTful APIs using HTTP:

  • Le API REST sono progettate in base a risorse, che possono essere costituite da qualsiasi tipologia di oggetto, servizio o dati accessibile dal client.REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client.

  • Una risorsa ha un identificatore, costituito da un URI che identifica in modo univoco la risorsa.A resource has an identifier, which is a URI that uniquely identifies that resource. L'URI per uno specifico ordine cliente può essere ad esempio:For example, the URI for a particular customer order might be:

    https://adventure-works.com/orders/1
    
  • I client interagiscono con un servizio scambiando rappresentazioni delle risorse.Clients interact with a service by exchanging representations of resources. Molte API Web usano JSON come formato di scambio.Many web APIs use JSON as the exchange format. Una richiesta GET all'URI riportato sopra, ad esempio, potrebbe restituire questo corpo della risposta:For example, a GET request to the URI listed above might return this response body:

    {"orderId":1,"orderValue":99.90,"productId":1,"quantity":1}
    
  • Le API REST usano un'interfaccia uniforme che consente di separare le implementazioni del client e del servizio.REST APIs use a uniform interface, which helps to decouple the client and service implementations. Per le API REST basate su HTTP, l'interfaccia uniforme include l'uso di verbi HTTP standard per l'esecuzione di operazioni sulle risorse.For REST APIs built on HTTP, the uniform interface includes using standard HTTP verbs to perform operations on resources. Le operazioni più comuni sono GET, POST, PUT, PATCH e DELETE.The most common operations are GET, POST, PUT, PATCH, and DELETE.

  • Le API REST usano un modello di richiesta senza stato.REST APIs use a stateless request model. Le richieste HTTP devono essere indipendenti e possono essere eseguite in qualsiasi ordine, di conseguenza non è possibile mantenere informazioni temporanee sullo stato tra le richieste.HTTP requests should be independent and may occur in any order, so keeping transient state information between requests is not feasible. L'unico punto in cui sono memorizzate le informazioni sono le risorse stesse e ogni richiesta deve essere un'operazione atomica.The only place where information is stored is in the resources themselves, and each request should be an atomic operation. Questo vincolo garantisce ai servizi Web un'elevata scalabilità, perché non è necessario mantenere alcuna affinità tra i client e server specifici.This constraint enables web services to be highly scalable, because there is no need to retain any affinity between clients and specific servers. Qualsiasi server può gestire qualsiasi richiesta proveniente da qualsiasi client.Any server can handle any request from any client. La scalabilità può tuttavia essere limitata da altri fattori.That said, other factors can limit scalability. Molti servizi Web, ad esempio, eseguono la scrittura in un archivio dati back-end di cui potrebbe essere difficile aumentare il numero di istanze. Per altre informazioni sulle strategie per scalare orizzontalmente un archivio dati, vedere partizionamento dei dati orizzontali, verticali e funzionali.For example, many web services write to a backend data store, which may be hard to scale out. For more information about strategies to scale out a data store, see Horizontal, vertical, and functional data partitioning.

  • Le API REST si basano su collegamenti ipermediali contenuti nella rappresentazione.REST APIs are driven by hypermedia links that are contained in the representation. Di seguito viene ad esempio illustrata una rappresentazione JSON di un ordineFor example, the following shows a JSON representation of an order. che contiene collegamenti per recuperare o aggiornare il cliente associato all'ordine.It contains links to get or update the customer associated with the order.

    {
        "orderID":3,
        "productID":2,
        "quantity":4,
        "orderValue":16.60,
        "links": [
            {"rel":"product","href":"https://adventure-works.com/customers/3", "action":"GET" },
            {"rel":"product","href":"https://adventure-works.com/customers/3", "action":"PUT" }
        ]
    }
    

Nel 2008, Leonard Richardson ha proposto per le API Web il modello di maturità seguente.In 2008, Leonard Richardson proposed the following maturity model for web APIs:

  • Livello 0: definizione di un URI e operazioni interamente costituite da richieste POST a tale URI.Level 0: Define one URI, and all operations are POST requests to this URI.
  • Livello 1: creazione di URI separati per le singole risorse.Level 1: Create separate URIs for individual resources.
  • Livello 2: uso di metodi HTTP per definire le operazioni sulle risorse.Level 2: Use HTTP methods to define operations on resources.
  • Livello 3: uso di ipermedia (principio HATEOAS descritto di seguito).Level 3: Use hypermedia (HATEOAS, described below).

Il livello 3 corrisponde a un'API realmente RESTful in base alla definizione di Fielding.Level 3 corresponds to a truly RESTful API according to Fielding's definition. In pratica, molte API Web pubblicate rientrano all'incirca nel livello 2.In practice, many published web APIs fall somewhere around level 2.

Organizzare l'API in base alle risorseOrganize the API around resources

Concentrarsi sulle entità di business esposte dall'API Web.Focus on the business entities that the web API exposes. In un sistema di e-commerce, ad esempio, le entità primarie potrebbero essere i clienti e gli ordini.For example, in an e-commerce system, the primary entities might be customers and orders. Un ordine può essere creato inviando una richiesta HTTP POST contenente le informazioni dell'ordine.Creating an order can be achieved by sending an HTTP POST request that contains the order information. La risposta HTTP indica se l'ordine è stato inserito correttamente o meno.The HTTP response indicates whether the order was placed successfully or not. Quando possibile, gli URI delle risorse devono essere basati su sostantivi (ovvero sulla risorsa) e non su verbi (ossia sulle operazioni sulla risorsa).When possible, resource URIs should be based on nouns (the resource) and not verbs (the operations on the resource).

https://adventure-works.com/orders // Good

https://adventure-works.com/create-order // Avoid

Una risorsa non deve essere basata su un elemento di dati fisico singolo.A resource doesn't have to be based on a single physical data item. Una risorsa ordine, ad esempio, potrebbe essere implementata internamente in diverse tabelle di un database relazionale, ma essere presentata al client come una singola entità.For example, an order resource might be implemented internally as several tables in a relational database, but presented to the client as a single entity. Evitare di creare API che rispecchiano semplicemente la struttura interna di un database.Avoid creating APIs that simply mirror the internal structure of a database. Lo scopo di REST è modellare entità e le operazioni che possono essere eseguite da un'applicazione su tali entità.The purpose of REST is to model entities and the operations that an application can perform on those entities. L'implementazione interna non dovrebbe essere esposta a un client.A client should not be exposed to the internal implementation.

Le entità sono spesso raggruppate in raccolte (ad esempio, ordini e clienti).Entities are often grouped together into collections (orders, customers). Una raccolta è una risorsa separata dall'elemento al suo interno e deve avere un proprio URI.A collection is a separate resource from the item within the collection, and should have its own URI. L'URI seguente, ad esempio, potrebbe rappresentare la raccolta degli ordini:For example, the following URI might represent the collection of orders:

https://adventure-works.com/orders

Inviando una richiesta HTTP GET all'URI della raccolta viene recuperato un elenco degli elementi al suo interno.Sending an HTTP GET request to the collection URI retrieves a list of items in the collection. Ogni elemento della raccolta ha anche un proprio URI univoco.Each item in the collection also has its own unique URI. Una richiesta HTTP GET all'URI di un elemento restituisce i dettagli di tale elemento.An HTTP GET request to the item's URI returns the details of that item.

Adottare una convenzione di denominazione coerente negli URI.Adopt a consistent naming convention in URIs. In generale, per gli URI che fanno riferimento alle raccolte è utile usare sostantivi plurali.In general, it helps to use plural nouns for URIs that reference collections. È consigliabile organizzare gli URI per le raccolte e gli elementi in una gerarchia.It's a good practice to organize URIs for collections and items into a hierarchy. Se /customers è il percorso della raccolta dei clienti, ad esempio, /customers/5 sarà il percorso del cliente il cui ID è 5.For example, /customers is the path to the customers collection, and /customers/5 is the path to the customer with ID equal to 5. Questo approccio consente di mantenere l'API Web intuitiva.This approach helps to keep the web API intuitive. Molti framework API Web, inoltre, possono indirizzare le richieste in base a percorsi URI con parametri ed è quindi possibile definire una route per il percorso /customers/{id}.Also, many web API frameworks can route requests based on parameterized URI paths, so you could define a route for the path /customers/{id}.

Considerare anche le relazioni tra i diversi tipi di risorse e come si potrebbero esporre tali associazioni.Also consider the relationships between different types of resources and how you might expose these associations. Ad esempio, /customers/5/orders potrebbe rappresentare tutti gli ordini per il cliente 5.For example, the /customers/5/orders might represent all of the orders for customer 5. Si potrebbe procedere anche nella direzione opposta e rappresentare l'associazione da un ordine a un cliente con un URI come /orders/99/customer.You could also go in the other direction, and represent the association from an order back to a customer with a URI such as /orders/99/customer. Se questo modello viene esteso eccessivamente, tuttavia, la relativa implementazione può diventare complessa.However, extending this model too far can become cumbersome to implement. È preferibile fornire collegamenti esplorabili alle risorse associate nel corpo del messaggio di risposta HTTP.A better solution is to provide navigable links to associated resources in the body of the HTTP response message. Questo meccanismo è descritto più dettagliatamente nella sezione usare HATEOAS per consentire lo spostamento a risorse correlate.This mechanism is described in more detail in the section Use HATEOAS to enable navigation to related resources.

Nei sistemi più complessi si può essere tentati di fornire URI che consentono a un client di spostarsi tra diversi livelli di relazioni, ad esempio /customers/1/orders/99/products.In more complex systems, it can be tempting to provide URIs that enable a client to navigate through several levels of relationships, such as /customers/1/orders/99/products. Tuttavia questo livello di complessità può essere difficile da mantenere e non è flessibile se le relazioni tra le risorse cambiano in futuro.However, this level of complexity can be difficult to maintain and is inflexible if the relationships between resources change in the future. Provare invece a mantenere gli URI relativamente semplici.Instead, try to keep URIs relatively simple. Quando un'applicazione contiene un riferimento a una risorsa, dovrebbe essere possibile usare questo riferimento per trovare gli elementi correlati a tale risorsa.Once an application has a reference to a resource, it should be possible to use this reference to find items related to that resource. La query precedente può essere sostituita con l'URI /customers/1/orders per trovare tutti gli ordini per il cliente 1 e quindi /orders/99/products per trovare i prodotti in tale ordine.The preceding query can be replaced with the URI /customers/1/orders to find all the orders for customer 1, and then /orders/99/products to find the products in this order.

Suggerimento

Evitare di richiedere URI di risorse più complessi di raccolta/elemento/raccolta.Avoid requiring resource URIs more complex than collection/item/collection.

Un altro fattore è che tutte le richieste Web impongono un carico sul server Web.Another factor is that all web requests impose a load on the web server. Maggiore è il numero di richieste, maggiore è il carico.The more requests, the bigger the load. Provare quindi a evitare API Web "frammentate" che espongono un numero elevato di risorse di piccole dimensioni.Therefore, try to avoid "chatty" web APIs that expose a large number of small resources. Un'API di questo tipo può richiedere che un'applicazione client invii più richieste per trovare tutti i dati necessari.Such an API may require a client application to send multiple requests to find all of the data that it requires. Potrebbe essere invece opportuno denormalizzare i dati e combinare le informazioni correlate in risorse di maggiori dimensioni recuperabili con una singola richiesta.Instead, you might want to denormalize the data and combine related information into bigger resources that can be retrieved with a single request. Questo approccio deve tuttavia essere bilanciato rispetto al sovraccarico associato al recupero di dati non necessari al client.However, you need to balance this approach against the overhead of fetching data that the client doesn't need. Il recupero di oggetti di grandi dimensioni può aumentare la latenza di una richiesta e comportare costi aggiuntivi in termini di larghezza di banda.Retrieving large objects can increase the latency of a request and incur additional bandwidth costs. Per altre informazioni su questi anti-modelli delle prestazioni, vedere gli articoli relativi a I/O frammentato e recupero estraneo.For more information about these performance antipatterns, see Chatty I/O and Extraneous Fetching.

Evitare di introdurre dipendenze tra l'API Web e le origini dati sottostanti.Avoid introducing dependencies between the web API and the underlying data sources. Se i dati sono archiviati in un database relazionale, ad esempio, non è necessario che l'API Web esponga ogni tabella come raccolta di risorse.For example, if your data is stored in a relational database, the web API doesn't need to expose each table as a collection of resources. Questo potrebbe probabilmente rivelarsi un errore di progettazione.In fact, that's probably a poor design. Considerare invece l'API Web come un'astrazione del database.Instead, think of the web API as an abstraction of the database. Se necessario, introdurre un livello di mapping tra il database e l'API Web.If necessary, introduce a mapping layer between the database and the web API. In questo modo, le applicazioni client vengono isolate dalle modifiche allo schema di database sottostante.That way, client applications are isolated from changes to the underlying database scheme.

Infine, potrebbe non essere possibile eseguire il mapping di ogni operazione implementata da un'API Web a una risorsa specifica.Finally, it might not be possible to map every operation implemented by a web API to a specific resource. È possibile gestire tali scenari non corrispondenti a una risorsa tramite richieste HTTP che richiamano una funzione e restituiscono i risultati come messaggio di risposta HTTP.You can handle such non-resource scenarios through HTTP requests that invoke a function and return the results as an HTTP response message. Un'API Web che implementa semplici operazioni aritmetiche come addizione e sottrazione, ad esempio, potrebbe fornire URI che espongono tali operazioni come pseudo-risorse e usare la stringa di query per specificare i parametri necessari.For example, a web API that implements simple calculator operations such as add and subtract could provide URIs that expose these operations as pseudo resources and use the query string to specify the parameters required. Ad esempio, una richiesta GET all'URI /Add? operand1 = 99 & operand2 = 1 restituirà un messaggio di risposta con il corpo contiene il valore 100.For example, a GET request to the URI /add?operand1=99&operand2=1 would return a response message with the body containing the value 100. Utilizzare tuttavia questi formati di URI solo in casi limitati.However, only use these forms of URIs sparingly.

Definire le operazioni in termini di metodi HTTPDefine operations in terms of HTTP methods

Il protocollo HTTP definisce una serie di metodi che assegnano un significato semantico a una richiesta.The HTTP protocol defines a number of methods that assign semantic meaning to a request. I metodi HTTP usati dalla maggior parte delle API Web RESTful sono:The common HTTP methods used by most RESTful web APIs are:

  • GET recupera una rappresentazione della risorsa nell'URI specificato.GET retrieves a representation of the resource at the specified URI. Il corpo del messaggio di risposta contiene i dettagli della risorsa richiesta.The body of the response message contains the details of the requested resource.
  • POST crea una nuova risorsa nell'URI specificato.POST creates a new resource at the specified URI. Il corpo del messaggio di richiesta fornisce i dettagli della nuova risorsa.The body of the request message provides the details of the new resource. Si noti che POST può anche essere usato per avviare operazioni che in realtà non creano risorse.Note that POST can also be used to trigger operations that don't actually create resources.
  • PUT crea o sostituisce la risorsa nell'URI specificato.PUT either creates or replaces the resource at the specified URI. Il corpo del messaggio di richiesta specifica la risorsa da creare o aggiornare.The body of the request message specifies the resource to be created or updated.
  • PATCH esegue un aggiornamento parziale di una risorsa.PATCH performs a partial update of a resource. Il corpo della richiesta specifica il set di modifiche da applicare alla risorsa.The request body specifies the set of changes to apply to the resource.
  • DELETE rimuove la risorsa nell'URI specificato.DELETE removes the resource at the specified URI.

L'effetto di una specifica richiesta varia a seconda che la risorsa sia una raccolta o un singolo elemento.The effect of a specific request should depend on whether the resource is a collection or an individual item. La tabella seguente riepiloga le convenzioni comuni adottate dalle implementazioni più RESTful usando l'esempio di e-commerce.The following table summarizes the common conventions adopted by most RESTful implementations using the e-commerce example. Non tutte le richieste potrebbero essere implementate—dipende dallo scenario specifico.Not all of these requests might be implemented—it depends on the specific scenario.

RisorsaResource POSTPOST GETGET PUTPUT DELETEDELETE
/customers./customers Creare un nuovo clienteCreate a new customer Recuperare tutti i clientiRetrieve all customers Eseguire l'aggiornamento in blocco dei clientiBulk update of customers Rimuovere tutti i clientiRemove all customers
/customers/1/customers/1 Tipi di erroreError Recuperare i dettagli per il cliente 1Retrieve the details for customer 1 Aggiornare i dettagli del cliente 1, se esistenteUpdate the details of customer 1 if it exists Rimuovere il cliente 1Remove customer 1
/customers/1/orders/customers/1/orders Creare un nuovo ordine per il cliente 1Create a new order for customer 1 Recuperare tutti gli ordini per il cliente 1Retrieve all orders for customer 1 Eseguire l'aggiornamento in blocco degli ordini per il cliente 1Bulk update of orders for customer 1 Rimuovere tutti gli ordini per il cliente 1Remove all orders for customer 1

Le differenze tra POST, PUT e PATCH possono risultare poco chiare.The differences between POST, PUT, and PATCH can be confusing.

  • Una richiesta POST crea una risorsa.A POST request creates a resource. Il server assegna un URI per la nuova risorsa e restituisce tale URI al client.The server assigns a URI for the new resource, and returns that URI to the client. Nel modello REST, le richieste POST vengono spesso applicate alle raccolte.In the REST model, you frequently apply POST requests to collections. La nuova risorsa viene aggiunta alla raccolta.The new resource is added to the collection. Una richiesta POST può essere usata anche per inviare dati a una risorsa esistente per l'elaborazione, senza che venga creata una nuova risorsa.A POST request can also be used to submit data for processing to an existing resource, without any new resource being created.

  • Una richiesta PUT crea una risorsa o aggiorna una risorsa esistente.A PUT request creates a resource or updates an existing resource. Il client specifica l'URI per la risorsa.The client specifies the URI for the resource. Il corpo della richiesta contiene una rappresentazione completa della risorsa.The request body contains a complete representation of the resource. Se esiste già una risorsa con tale URI, viene sostituita.If a resource with this URI already exists, it is replaced. In caso contrario viene creata una nuova risorsa, se questa operazione è supportata dal server.Otherwise a new resource is created, if the server supports doing so. Le richieste PUT vengono applicate con maggiore frequenza ai singoli elementi, come un cliente specifico, anziché alle raccolte.PUT requests are most frequently applied to resources that are individual items, such as a specific customer, rather than collections. Un server potrebbe supportare gli aggiornamenti ma non la creazione tramite PUT.A server might support updates but not creation via PUT. Il supporto o meno della creazione tramite PUT dipende dalla possibilità per il client di assegnare un URI significativo a una risorsa non ancora esistente.Whether to support creation via PUT depends on whether the client can meaningfully assign a URI to a resource before it exists. Se il client non può, usare POST per creare le risorse e PUT o PATCH per l'aggiornamento.If not, then use POST to create resources and PUT or PATCH to update.

  • Una richiesta PATCH esegue un aggiornamento parziale di una risorsa esistente.A PATCH request performs a partial update to an existing resource. Il client specifica l'URI per la risorsa.The client specifies the URI for the resource. Il corpo della richiesta specifica un set di modifiche da applicare alla risorsa.The request body specifies a set of changes to apply to the resource. Può essere più efficiente rispetto all'uso di PUT, perché il client invia solo le modifiche, non l'intera rappresentazione della risorsa.This can be more efficient than using PUT, because the client only sends the changes, not the entire representation of the resource. Tecnicamente, PATCH può anche creare una nuova risorsa, specificando un set di aggiornamenti per una risorsa "Null", se questa operazione è supportata dal server.Technically PATCH can also create a new resource (by specifying a set of updates to a "null" resource), if the server supports this.

Le richieste PUT devono essere idempotenti.PUT requests must be idempotent. Se un client invia la stessa richiesta PUT più volte, i risultati dovranno essere sempre uguali, ossia la stessa risorsa verrà modificata con gli stessi valori.If a client submits the same PUT request multiple times, the results should always be the same (the same resource will be modified with the same values). Non è invece garantito che le richieste POST e PATCH siano idempotenti.POST and PATCH requests are not guaranteed to be idempotent.

Mantenere la conformità alla semantica HTTPConform to HTTP semantics

Questa sezione descrive alcune considerazioni tipiche per la progettazione di un'API conforme alla specifica HTTP.This section describes some typical considerations for designing an API that conforms to the HTTP specification. Non illustra tuttavia ogni possibile dettaglio o scenario.However, it doesn't cover every possible detail or scenario. In caso di dubbi, consultare le specifiche HTTP.When in doubt, consult the HTTP specifications.

Tipi di supportoMedia types

Come indicato in precedenza, i client e i server si scambiano rappresentazioni delle risorse.As mentioned earlier, clients and servers exchange representations of resources. In una richiesta POST, ad esempio, il corpo della richiesta contiene una rappresentazione della risorsa da creare.For example, in a POST request, the request body contains a representation of the resource to create. In una richiesta GET, il corpo della risposta contiene una rappresentazione della risorsa recuperata.In a GET request, the response body contains a representation of the fetched resource.

Nel protocollo HTTP, i formati vengono specificati usando tipi di supporto, denominati anche tipi MIME.In the HTTP protocol, formats are specified through the use of media types, also called MIME types. Per i dati non binari, la maggior parte delle API Web supporta JSON (ovvero il tipo di supporto application/json) ed eventualmente XML (ossia il tipo di supporto application/xml).For non-binary data, most web APIs support JSON (media type = application/json) and possibly XML (media type = application/xml).

L'intestazione Content-Type in una richiesta o una risposta specifica il formato della rappresentazione.The Content-Type header in a request or response specifies the format of the representation. Di seguito è riportato un esempio di richiesta POST contenente dati JSON:Here is an example of a POST request that includes JSON data:

POST https://adventure-works.com/orders HTTP/1.1
Content-Type: application/json; charset=utf-8
Content-Length: 57

{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}

Se il server non supporta il tipo di supporto, deve restituire il codice di stato HTTP 415 (Tipo di supporto non supportato).If the server doesn't support the media type, it should return HTTP status code 415 (Unsupported Media Type).

Una richiesta client può includere un'intestazione Accept contenente un elenco dei tipi di supporto accettati dal client nel messaggio di risposta proveniente dal server.A client request can include an Accept header that contains a list of media types the client will accept from the server in the response message. Ad esempio:For example:

GET https://adventure-works.com/orders/2 HTTP/1.1
Accept: application/json

Se il server non può fornire un tipo di supporto corrispondente a quelli elencati, deve restituire il codice di stato HTTP 406 (Pagina non valida).If the server cannot match any of the media type(s) listed, it should return HTTP status code 406 (Not Acceptable).

Metodi GETGET methods

Un metodo GET riuscito restituisce in genere il codice di stato HTTP 200 (OK).A successful GET method typically returns HTTP status code 200 (OK). Se la risorsa non è stata trovata, il metodo deve restituire 404 (Non trovato).If the resource cannot be found, the method should return 404 (Not Found).

Metodi POSTPOST methods

Se un metodo POST crea una nuova risorsa, restituisce il codice di stato HTTP 201 (Creato).If a POST method creates a new resource, it returns HTTP status code 201 (Created). L'URI della nuova risorsa è incluso nell'intestazione Location della risposta.The URI of the new resource is included in the Location header of the response. Il corpo della risposta contiene una rappresentazione della risorsa.The response body contains a representation of the resource.

Se esegue alcune attività di elaborazione ma non crea una nuova risorsa, il metodo può restituire il codice di stato HTTP 200 e includere il risultato dell'operazione nel corpo della risposta.If the method does some processing but does not create a new resource, the method can return HTTP status code 200 and include the result of the operation in the response body. In alternativa, se non sono presenti risultati, il metodo può restituire il codice di stato HTTP 204 (Nessun contenuto) senza corpo della risposta.Alternatively, if there is no result to return, the method can return HTTP status code 204 (No Content) with no response body.

Se il client inserisce dati non validi nella richiesta, il server deve restituire il codice di stato HTTP 400 (Richiesta non valida).If the client puts invalid data into the request, the server should return HTTP status code 400 (Bad Request). Il corpo della risposta può contenere informazioni aggiuntive sull'errore o un collegamento a un URI che offre maggiori dettagli.The response body can contain additional information about the error or a link to a URI that provides more details.

Metodi PUTPUT methods

Se un metodo PUT crea una nuova risorsa, restituisce il codice di stato HTTP 201 (Creato), così come un metodo POST.If a PUT method creates a new resource, it returns HTTP status code 201 (Created), as with a POST method. Se il metodo aggiorna una risorsa esistente, restituisce 200 (OK) o 204 (Nessun contenuto).If the method updates an existing resource, it returns either 200 (OK) or 204 (No Content). In alcuni casi potrebbe non essere possibile aggiornare una risorsa esistente.In some cases, it might not be possible to update an existing resource. In tale circostanza, valutare la possibilità di restituire il codice di stato HTTP 409 (Conflitto).In that case, consider returning HTTP status code 409 (Conflict).

Prendere in considerazione l’implementazione di operazioni HTTP PUT in blocco in grado di eseguire aggiornamenti in batch di più risorse in una raccolta.Consider implementing bulk HTTP PUT operations that can batch updates to multiple resources in a collection. La richiesta PUT deve specificare l'URI della raccolta e il corpo della richiesta deve specificare i dettagli delle risorse da modificare.The PUT request should specify the URI of the collection, and the request body should specify the details of the resources to be modified. Questo approccio consente di ridurre la frammentarietà e migliorare le prestazioni.This approach can help to reduce chattiness and improve performance.

Metodi PATCHPATCH methods

Con una richiesta PATCH, il client invia un set di aggiornamenti a una risorsa esistente, sotto forma di documento di patch.With a PATCH request, the client sends a set of updates to an existing resource, in the form of a patch document. Il server elabora il documento di patch per eseguire l'aggiornamento.The server processes the patch document to perform the update. Il documento di patch non descrive l'intera risorsa, ma solo un set di modifiche da applicare.The patch document doesn't describe the whole resource, only a set of changes to apply. La specifica per il metodo PATCH (RFC 5789) non definisce un particolare formato per i documenti di patch.The specification for the PATCH method (RFC 5789) doesn't define a particular format for patch documents. Il formato deve essere dedotto dal tipo di supporto nella richiesta.The format must be inferred from the media type in the request.

Il formato di dati più comune per le API Web è probabilmente JSON.JSON is probably the most common data format for web APIs. Esistono due formati principali di patch basati su JSON, denominati patch JSON e patch JSON di tipo merge.There are two main JSON-based patch formats, called JSON patch and JSON merge patch.

La patch JSON di tipo merge è un po' più semplice.JSON merge patch is somewhat simpler. Il documento di patch presenta la stessa struttura della risorsa JSON originale, ma include solo il subset di campi da modificare o aggiungere.The patch document has the same structure as the original JSON resource, but includes just the subset of fields that should be changed or added. È anche possibile eliminare un campo specificando null come valore del campo nel documento di patch.In addition, a field can be deleted by specifying null for the field value in the patch document. La patch di tipo merge non è quindi adatta se la risorsa originale può contenere valori Null espliciti.(That means merge patch is not suitable if the original resource can have explicit null values.)

Si supponga ad esempio che la risorsa originale abbia la rappresentazione JSON seguente:For example, suppose the original resource has the following JSON representation:

{
    "name":"gizmo",
    "category":"widgets",
    "color":"blue",
    "price":10
}

Di seguito è riportata una possibile patch JSON di tipo merge per tale risorsa:Here is a possible JSON merge patch for this resource:

{
    "price":12,
    "color":null,
    "size":"small"
}

Ciò indica al server di aggiornamento price, eliminare color, quindi aggiungere size, mentre name e category non vengono modificati.This tells the server to update price, delete color, and add size, while name and category are not modified. Per informazioni dettagliate precise sulla patch JSON di tipo merge, vedere la specifica RFC 7396.For the exact details of JSON merge patch, see RFC 7396. Il tipo di supporto per la patch JSON di tipo merge è application/merge-patch+json.The media type for JSON merge patch is application/merge-patch+json.

La patch di tipo merge non è adatta se la risorsa originale può contenere valori Null espliciti, a causa del significato speciale di null nel documento di patch.Merge patch is not suitable if the original resource can contain explicit null values, due to the special meaning of null in the patch document. Il documento di patch, inoltre, non specifica l'ordine con cui il server dovrà applicare gli aggiornamenti.Also, the patch document doesn't specify the order that the server should apply the updates. Tale ordine può essere importante o meno a seconda dei dati e del dominio.That may or may not matter, depending on the data and the domain. La patch JSON, definita in RFC 6902, è più flessibileJSON patch, defined in RFC 6902, is more flexible. e specifica le modifiche come sequenza di operazioni da applicare.It specifies the changes as a sequence of operations to apply. Le operazioni includono aggiunta, rimozione, sostituzione, copia e test (per convalidare i valori).Operations include add, remove, replace, copy, and test (to validate values). Il tipo di supporto per la patch JSON è application/json-patch+json.The media type for JSON patch is application/json-patch+json.

Di seguito sono riportate alcune condizioni di errore tipiche che si possono verificare durante l'elaborazione di una richiesta PATCH, con il codice di stato HTTP appropriato.Here are some typical error conditions that might be encountered when processing a PATCH request, along with the appropriate HTTP status code.

Condizione di erroreError condition Stato codice HTTPHTTP status code
Il formato del documento di patch non è supportato.The patch document format isn't supported. 415 (Tipo di supporto non supportato)415 (Unsupported Media Type)
Il formato del documento di patch non è valido.Malformed patch document. 400 (Richiesta non valida)400 (Bad Request)
Il documento di patch è valido, ma le modifiche non possono essere applicate alla risorsa nello stato corrente.The patch document is valid, but the changes can't be applied to the resource in its current state. 409 (Conflitto)409 (Conflict)

Metodi DELETEDELETE methods

Se l'operazione di eliminazione ha esito positivo, il server Web risponderà con il codice di stato HTTP 204, che indica che il processo è stato gestito correttamente, ma il corpo della risposta non conterrà altre informazioni.If the delete operation is successful, the web server should respond with HTTP status code 204, indicating that the process has been successfully handled, but that the response body contains no further information. Se la risorsa non esiste, il server Web può restituire il codice di stato HTTP 404 (Non trovato).If the resource doesn't exist, the web server can return HTTP 404 (Not Found).

Operazioni asincroneAsynchronous operations

In alcuni casi un'operazione POST, PUT, PATCH o DELETE potrebbe richiedere l'elaborazione che richiede alcuni minuti.Sometimes a POST, PUT, PATCH, or DELETE operation might require processing that takes a while to complete. Attendere il completamento prima di inviare una risposta al client può causare una latenza inaccettabile.If you wait for completion before sending a response to the client, it may cause unacceptable latency. In tal caso, valutare la possibilità di rendere l'operazione asincrona.If so, consider making the operation asynchronous. Restituire il codice di stato HTTP 202 (Accettato) per indicare che la richiesta è stata accettata per l'elaborazione ma non è stata completata.Return HTTP status code 202 (Accepted) to indicate the request was accepted for processing but is not completed.

È consigliabile esporre un endpoint che restituisce lo stato di una richiesta asincrona, in modo che il client possa monitorare lo stato eseguendo il polling sull'endpoint di stato.You should expose an endpoint that returns the status of an asynchronous request, so the client can monitor the status by polling the status endpoint. Includere l'URI dell'endpoint di stato nell'intestazione Location della risposta 202.Include the URI of the status endpoint in the Location header of the 202 response. Ad esempio:For example:

HTTP/1.1 202 Accepted
Location: /api/status/12345

Se il client invia una richiesta GET a questo endpoint, la risposta dovrà contenere lo stato corrente della richiesta.If the client sends a GET request to this endpoint, the response should contain the current status of the request. Facoltativamente, potrà includere anche il tempo di completamento stimato o un collegamento per annullare l'operazione.Optionally, it could also include an estimated time to completion or a link to cancel the operation.

HTTP/1.1 200 OK
Content-Type: application/json

{
    "status":"In progress",
    "link": { "rel":"cancel", "method":"delete", "href":"/api/status/12345" }
}

Se l'operazione asincrona crea una nuova risorsa, l'endpoint di stato deve restituire il codice di stato 303 (Vedi altro) al termine dell'operazione.If the asynchronous operation creates a new resource, the status endpoint should return status code 303 (See Other) after the operation completes. Nella risposta 303 includere un'intestazione Location contenente l'URI della nuova risorsa:In the 303 response, include a Location header that gives the URI of the new resource:

HTTP/1.1 303 See Other
Location: /api/orders/12345

Per altre informazioni, vedere Asynchronous operations in REST (Operazioni asincrone in REST).For more information, see Asynchronous operations in REST.

Filtrare e impaginare i datiFilter and paginate data

Esponendo una raccolta di risorse tramite un singolo URI, le applicazioni potrebbero recuperare grandi quantità di dati quando è necessario solo un subset delle informazioni.Exposing a collection of resources through a single URI can lead to applications fetching large amounts of data when only a subset of the information is required. Si supponga ad esempio che un'applicazione client debba trovare tutti gli ordini con un costo superiore a un valore specificato.For example, suppose a client application needs to find all orders with a cost over a specific value. Potrebbe recuperare tutti gli ordini dall'URI /orders e quindi filtrare tali ordini sul lato client.It might retrieve all orders from the /orders URI and then filter these orders on the client side. Questo processo è chiaramente molto inefficiente,Clearly this process is highly inefficient. perché comporta uno spreco di larghezza di banda di rete e di potenza di elaborazione nel server che ospita l'API Web.It wastes network bandwidth and processing power on the server hosting the web API.

L'API può invece consentire di passare un filtro nella stringa di query dell'URI, ad esempio /orders?minCost=n.Instead, the API can allow passing a filter in the query string of the URI, such as /orders?minCost=n. L'API Web sarà quindi responsabile dell'analisi e della gestione del parametro minCost nella stringa di query e della restituzione dei risultati filtrati sul lato server.The web API is then responsible for parsing and handling the minCost parameter in the query string and returning the filtered results on the server side.

Le richieste GET su risorse raccolta potrebbero restituire un numero elevato di elementi.GET requests over collection resources can potentially return a large number of items. È consigliabile progettare un'API Web in modo da limitare la quantità di dati restituita da ogni singola richiesta.You should design a web API to limit the amount of data returned by any single request. Valutare la possibilità di supportare stringhe di query che specificano il numero massimo di elementi da recuperare e un offset iniziale nella raccolta.Consider supporting query strings that specify the maximum number of items to retrieve and a starting offset into the collection. Ad esempio:For example:

/orders?limit=25&offset=50

Valutare anche la possibilità di imporre un limite massimo al numero di elementi restituiti, per prevenire attacchi Denial of Service.Also consider imposing an upper limit on the number of items returned, to help prevent Denial of Service attacks. Per agevolare le applicazioni client, le richieste GET che restituiscono i dati impaginati devono includere anche un tipo di metadati che indichino il numero totale delle risorse disponibili nella raccolta.To assist client applications, GET requests that return paginated data should also include some form of metadata that indicate the total number of resources available in the collection.

È possibile usare una strategia simile per ordinare i dati mentre vengono recuperati, specificando un parametro sort che accetta il nome di un campo come valore, ad esempio /orders?sort=ProductID.You can use a similar strategy to sort data as it is fetched, by providing a sort parameter that takes a field name as the value, such as /orders?sort=ProductID. Questo approccio, tuttavia, può avere un effetto negativo sulla memorizzazione nella cache, perché i parametri della stringa di query formano parte dell'identificatore di risorsa usato da molte implementazioni di cache come chiave per i dati memorizzati nella cache.However, this approach can have a negative effect on caching, because query string parameters form part of the resource identifier used by many cache implementations as the key to cached data.

È possibile estendere questo approccio per limitare i campi restituiti per ogni elemento, se ognuno contiene una grande quantità di dati.You can extend this approach to limit the fields returned for each item, if each item contains a large amount of data. Si può usare, ad esempio, un parametro di stringa di query che accetta un elenco di campi delimitato da virgole, come /orders?fields=ProductID,Quantity.For example, you could use a query string parameter that accepts a comma-delimited list of fields, such as /orders?fields=ProductID,Quantity.

Assegnare valori predefiniti significativi a tutti i parametri facoltativi nelle stringhe di query.Give all optional parameters in query strings meaningful defaults. Ad esempio, impostare il parametro limit su 10 e il parametro offset su 0 se si implementa la paginazione, impostare il parametro Sort sulla chiave della risorsa se si implementa l’ordinamento e impostare il parametro fields su tutti i campi della risorsa se si supportano le proiezioni.For example, set the limit parameter to 10 and the offset parameter to 0 if you implement pagination, set the sort parameter to the key of the resource if you implement ordering, and set the fields parameter to all fields in the resource if you support projections.

Supportare risposte parziali per risorse binarie di grandi dimensioniSupport partial responses for large binary resources

Una risorsa può contenere campi binari di grandi dimensioni, come file o immagini.A resource may contain large binary fields, such as files or images. Per superare i problemi causati da connessioni intermittenti e inaffidabili e migliorare i tempi di risposta, valutare la possibilità di consentire il recupero di tali risorse in blocchi.To overcome problems caused by unreliable and intermittent connections and to improve response times, consider enabling such resources to be retrieved in chunks. A tale scopo, l'API Web deve supportare l'intestazione Accept-Ranges per le richieste GET relative a risorse di grandi dimensioni.To do this, the web API should support the Accept-Ranges header for GET requests for large resources. Questa intestazione indica che l'operazione GET supporta richieste parziali.This header indicates that the GET operation supports partial requests. L'applicazione client può inviare richieste GET che restituiscono un subset di una risorsa, specificato come un intervallo di byte.The client application can submit GET requests that return a subset of a resource, specified as a range of bytes.

Valutare anche la possibilità di implementare richieste HTTP HEAD per queste risorse.Also, consider implementing HTTP HEAD requests for these resources. Una richiesta HEAD è simile a una richiesta GET tranne per il fatto che restituisce solo le intestazioni HTTP che descrivono la risorsa, con un corpo del messaggio vuoto.A HEAD request is similar to a GET request, except that it only returns the HTTP headers that describe the resource, with an empty message body. Un'applicazione client può inviare una richiesta HEAD per determinare se recuperare una risorsa tramite richieste GET parziali.A client application can issue a HEAD request to determine whether to fetch a resource by using partial GET requests. Ad esempio:For example:

HEAD https://adventure-works.com/products/10?fields=productImage HTTP/1.1

Di seguito è riportato un messaggio di risposta di esempio:Here is an example response message:

HTTP/1.1 200 OK

Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 4580

L'intestazione Content-Length contiene le dimensioni totali della risorsa e l'intestazione Accept-Ranges indica che l'operazione GET corrispondente supporta risultati parziali.The Content-Length header gives the total size of the resource, and the Accept-Ranges header indicates that the corresponding GET operation supports partial results. L'applicazione client può usare queste informazioni per recuperare l'immagine in blocchi più piccoli.The client application can use this information to retrieve the image in smaller chunks. La prima richiesta recupera i primi 2500 byte mediante l'intestazione Range:The first request fetches the first 2500 bytes by using the Range header:

GET https://adventure-works.com/products/10?fields=productImage HTTP/1.1
Range: bytes=0-2499

Il codice di stato HTTP 206 restituito nel messaggio di risposta indica che si tratta di una risposta parziale.The response message indicates that this is a partial response by returning HTTP status code 206. L'intestazione Content-Length specifica il numero effettivo di byte restituiti nel corpo del messaggio (non le dimensioni della risorsa) e l'intestazione Content-Range indica di quale parte della risorsa si tratta (byte 0-2499 di 4580):The Content-Length header specifies the actual number of bytes returned in the message body (not the size of the resource), and the Content-Range header indicates which part of the resource this is (bytes 0-2499 out of 4580):

HTTP/1.1 206 Partial Content

Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 2500
Content-Range: bytes 0-2499/4580

[...]

Una richiesta successiva dall'applicazione client può recuperare la parte restante della risorsa.A subsequent request from the client application can retrieve the remainder of the resource.

Una delle principali motivazioni alla base dell’approccio REST è che dovrebbe essere possibile spostarsi nell'intero set di risorse senza conoscere a priori lo schema URI.One of the primary motivations behind REST is that it should be possible to navigate the entire set of resources without requiring prior knowledge of the URI scheme. Ogni richiesta HTTP GET deve restituire le informazioni necessarie a trovare le risorse correlate direttamente all'oggetto richiesto tramite collegamenti ipertestuali inclusi nella risposta e deve anche contenere informazioni che descrivono le operazioni disponibili in ciascuna di queste risorse.Each HTTP GET request should return the information necessary to find the resources related directly to the requested object through hyperlinks included in the response, and it should also be provided with information that describes the operations available on each of these resources. Tale principio è noto come HATEOAS o Hypertext as the Engine of Application State.This principle is known as HATEOAS, or Hypertext as the Engine of Application State. Il sistema è in realtà una macchina a stati finiti e la risposta a ogni richiesta contiene le informazioni necessarie per passare da uno stato all’altro. Non dovrebbero essere necessarie altre informazioni.The system is effectively a finite state machine, and the response to each request contains the information necessary to move from one state to another; no other information should be necessary.

Nota

Attualmente non esistono standard o specifiche che definiscono come modellare il principio HATEOAS.Currently there are no standards or specifications that define how to model the HATEOAS principle. Gli esempi mostrati in questa sezione illustrano una possibile soluzione.The examples shown in this section illustrate one possible solution.

Per gestire la relazione tra un ordine e un cliente, ad esempio, la rappresentazione di un ordine potrebbe includere collegamenti che identificano le operazioni disponibili per il cliente dell'ordine.For example, to handle the relationship between an order and a customer, the representation of an order could include links that identify the available operations for the customer of the order. Di seguito è riportata una possibile rappresentazione:Here is a possible representation:

{
  "orderID":3,
  "productID":2,
  "quantity":4,
  "orderValue":16.60,
  "links":[
    {
      "rel":"customer",
      "href":"https://adventure-works.com/customers/3",
      "action":"GET",
      "types":["text/xml","application/json"]
    },
    {
      "rel":"customer",
      "href":"https://adventure-works.com/customers/3",
      "action":"PUT",
      "types":["application/x-www-form-urlencoded"]
    },
    {
      "rel":"customer",
      "href":"https://adventure-works.com/customers/3",
      "action":"DELETE",
      "types":[]
    },
    {
      "rel":"self",
      "href":"https://adventure-works.com/orders/3",
      "action":"GET",
      "types":["text/xml","application/json"]
    },
    {
      "rel":"self",
      "href":"https://adventure-works.com/orders/3",
      "action":"PUT",
      "types":["application/x-www-form-urlencoded"]
    },
    {
      "rel":"self",
      "href":"https://adventure-works.com/orders/3",
      "action":"DELETE",
      "types":[]
    }]
}

In questo esempio, la matrice links contiene un set di collegamenti,In this example, the links array has a set of links. ognuno dei quali rappresenta un'operazione su un'entità correlata.Each link represents an operation on a related entity. I dati per ogni collegamento includono la relazione ("customer"), l'URI (https://adventure-works.com/customers/3), il metodo HTTP e i tipi MIME supportati.The data for each link includes the relationship ("customer"), the URI (https://adventure-works.com/customers/3), the HTTP method, and the supported MIME types. Queste sono tutte le informazioni necessarie a un'applicazione client per poter richiamare l'operazione.This is all the information that a client application needs to be able to invoke the operation.

La matrice links include anche informazioni autoreferenziali sulla risorsa che è stata recuperata.The links array also includes self-referencing information about the resource itself that has been retrieved. Queste informazioni presentano la relazione self.These have the relationship self.

Il set di collegamenti restituito può variare a seconda dello stato della risorsa.The set of links that are returned may change, depending on the state of the resource. È per questo motivo che l'ipertesto viene definito il "motore dello stato dell'applicazione" (Hypertext as the Engine of Application State).This is what is meant by hypertext being the "engine of application state."

Controllo delle versioni di un'API Web RESTfulVersioning a RESTful web API

È altamente improbabile che un'API Web rimanga statica.It is highly unlikely that a web API will remain static. Man mano che i requisiti aziendali cambiano, è possibile che vengano aggiunte nuove raccolte di risorse, che le relazioni tra le risorse cambino e che la struttura dei dati nelle risorse venga modificata.As business requirements change new collections of resources may be added, the relationships between resources might change, and the structure of the data in resources might be amended. Sebbene l'aggiornamento di un'API Web per gestire requisiti nuovi o diversi sia un processo relativamente semplice, è necessario considerare gli effetti delle modifiche sulle applicazioni client che utilizzano l'API Web.While updating a web API to handle new or differing requirements is a relatively straightforward process, you must consider the effects that such changes will have on client applications consuming the web API. Il problema è che sebbene sviluppatore che progetta e implementa un'API web ha il controllo completo su tale API, lo sviluppatore non ha lo stesso livello di controllo sulle applicazioni client, che possono essere compilate da organizzazioni di terze parti che operano in modalità remota.The issue is that although the developer designing and implementing a web API has full control over that API, the developer does not have the same degree of control over client applications, which may be built by third-party organizations operating remotely. L’imperativo è consentire alle applicazioni client esistenti di continuare a funzionare senza modifiche e allo stesso tempo permettere alle nuove applicazioni client di avvalersi di nuove funzionalità e risorse.The primary imperative is to enable existing client applications to continue functioning unchanged while allowing new client applications to take advantage of new features and resources.

Il controllo delle versioni consente a un’API Web di indicare le funzionalità e le risorse esposte e a un’applicazione client di inviare richieste dirette a una versione specifica di una funzionalità o di una risorsa.Versioning enables a web API to indicate the features and resources that it exposes, and a client application can submit requests that are directed to a specific version of a feature or resource. Le sezioni seguenti descrivono diversi approcci differenti, ognuno dei quali presenta vantaggi e compromessi.The following sections describe several different approaches, each of which has its own benefits and trade-offs.

Nessun controllo delle versioniNo versioning

Si tratta dell'approccio più semplice e può essere accettabile per alcune API interne.This is the simplest approach, and may be acceptable for some internal APIs. Modifiche significative potrebbero essere rappresentate come nuove risorse o nuovi collegamenti.Significant changes could be represented as new resources or new links. Aggiunta di contenuto per le risorse esistenti potrebbe non presentare una modifica sostanziale come le applicazioni client che non sono previsti per visualizzare che questo contenuto verrà ignorata.Adding content to existing resources might not present a breaking change as client applications that are not expecting to see this content will ignore it.

Una richiesta all'URI https://adventure-works.com/customers/3, ad esempio, restituirà i dettagli di un singolo cliente contenente i campi id, name e address previsti dall'applicazione client:For example, a request to the URI https://adventure-works.com/customers/3 should return the details of a single customer containing id, name, and address fields expected by the client application:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Nota

Per semplicità, le risposte di esempio illustrate in questa sezione non includono collegamenti HATEOAS.For simplicity, the example responses shown in this section do not include HATEOAS links.

Se il campo DateCreated viene aggiunto allo schema della risorsa customer, la risposta sarà simile alla seguente:If the DateCreated field is added to the schema of the customer resource, then the response would look like this:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":"1 Microsoft Way Redmond WA 98053"}

Le applicazioni client esistenti potrebbero continuare a funzionare correttamente se riescono a ignorare i campi non riconosciuti, mentre le nuove applicazioni client possono essere progettate per gestire questo nuovo campo.Existing client applications might continue functioning correctly if they are capable of ignoring unrecognized fields, while new client applications can be designed to handle this new field. Tuttavia, modifiche più radicali allo schema di risorse (ad esempio, la rimozione o la ridenominazione dei campi) o cambiamenti nelle relazioni tra le risorse possono costituire modifiche sostanziali che impediscono alle applicazioni client esistenti di funzionare correttamente.However, if more radical changes to the schema of resources occur (such as removing or renaming fields) or the relationships between resources change then these may constitute breaking changes that prevent existing client applications from functioning correctly. In queste situazioni, è necessario considerare uno degli approcci seguenti.In these situations, you should consider one of the following approaches.

Controllo delle versioni tramite l’URIURI versioning

Ogni volta che si modifica l'API Web o che si cambia lo schema di risorse, viene aggiunto un numero di versione all'URI per ciascuna risorsa.Each time you modify the web API or change the schema of resources, you add a version number to the URI for each resource. Gli URI già esistenti continueranno a funzionare come prima, restituendo risorse conformi al relativo schema originale.The previously existing URIs should continue to operate as before, returning resources that conform to their original schema.

Estendendo l'esempio precedente, se il address campo viene ristrutturato in campi secondari contenenti le singole parti costitutive dell'indirizzo (ad esempio streetAddress, city, state, e zipCode), questa versione della risorsa potrebbe essere esposti tramite un URI contenente un numero di versione, ad esempio https://adventure-works.com/v2/customers/3:Extending the previous example, if the address field is restructured into subfields containing each constituent part of the address (such as streetAddress, city, state, and zipCode), this version of the resource could be exposed through a URI containing a version number, such as https://adventure-works.com/v2/customers/3:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":{"streetAddress":"1 Microsoft Way","city":"Redmond","state":"WA","zipCode":98053}}

Questo meccanismo di controllo delle versioni è molto semplice, ma dipende dal server che esegue il routing della richiesta all'endpoint appropriato.This versioning mechanism is very simple but depends on the server routing the request to the appropriate endpoint. Tuttavia, può diventare scomodo man mano che l’API Web matura attraverso diverse iterazioni e il server deve supportare un numero elevato di versioni diverse.However, it can become unwieldy as the web API matures through several iterations and the server has to support a number of different versions. Inoltre, dal punto di vista di un purista, in tutti i casi le applicazioni client recuperano gli stessi dati (cliente 3), quindi l'URI non deve essere effettivamente diverso a seconda della versione.Also, from a purist’s point of view, in all cases the client applications are fetching the same data (customer 3), so the URI should not really be different depending on the version. Questo schema complica anche l'implementazione di HATEOAS perché tutti i collegamenti dovranno includere il numero di versione nei relativi URI.This scheme also complicates implementation of HATEOAS as all links will need to include the version number in their URIs.

Controllo delle versioni tramite la stringa di queryQuery string versioning

Anziché fornire più URI, è possibile specificare la versione della risorsa usando un parametro all'interno della stringa di query aggiunta alla richiesta HTTP, ad esempio https://adventure-works.com/customers/3?version=2.Rather than providing multiple URIs, you can specify the version of the resource by using a parameter within the query string appended to the HTTP request, such as https://adventure-works.com/customers/3?version=2. Il parametro della versione deve essere impostato su un valore predefinito significativo, ad esempio 1 se viene omesso dalle applicazioni client meno recenti.The version parameter should default to a meaningful value such as 1 if it is omitted by older client applications.

Questo approccio ha il vantaggio semantico che la stessa risorsa viene sempre recuperata dallo stesso URI, ma dipende dal codice che gestisce la richiesta analizzare la stringa di query e inviare la risposta HTTP appropriata.This approach has the semantic advantage that the same resource is always retrieved from the same URI, but it depends on the code that handles the request to parse the query string and send back the appropriate HTTP response. Questo approccio presenta anche le stesse complicazioni per l'implementazione di HATEOAS del meccanismo di controllo delle versioni tramite URI.This approach also suffers from the same complications for implementing HATEOAS as the URI versioning mechanism.

Nota

Alcuni Web browser e proxy Web meno recenti non memorizzano nella cache le risposte per le richieste che includono una stringa di query nell'URI.Some older web browsers and web proxies will not cache responses for requests that include a query string in the URI. Ciò può influire negativamente sulle prestazioni per le applicazioni web che usano un'API web e che vengono eseguite dall'interno di tali un browser web.This can degrade performance for web applications that use a web API and that run from within such a web browser.

Controllo delle versioni tramite l’intestazioneHeader versioning

Anziché aggiungere il numero di versione come parametro di stringa di query, è possibile implementare un'intestazione personalizzata che indica la versione della risorsa.Rather than appending the version number as a query string parameter, you could implement a custom header that indicates the version of the resource. Questo approccio richiede l’aggiunta, da parte dell'applicazione client, dell'intestazione appropriata a tutte le richieste, nonostante il codice che gestisce la richiesta del client possa usare un valore predefinito (versione 1) se l'intestazione della versione viene omessa.This approach requires that the client application adds the appropriate header to any requests, although the code handling the client request could use a default value (version 1) if the version header is omitted. Nell'esempio seguente viene usata un'intestazione personalizzata denominata Custom-Header.The following examples use a custom header named Custom-Header. Il valore di questa intestazione indica la versione dell'API Web.The value of this header indicates the version of web API.

Versione 1:Version 1:

GET https://adventure-works.com/customers/3 HTTP/1.1
Custom-Header: api-version=1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Versione 2:Version 2:

GET https://adventure-works.com/customers/3 HTTP/1.1
Custom-Header: api-version=2
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"id":3,"name":"Contoso LLC","dateCreated":"2014-09-04T12:11:38.0376089Z","address":{"streetAddress":"1 Microsoft Way","city":"Redmond","state":"WA","zipCode":98053}}

Come con i due approcci precedenti, implementazione di HATEOAS richiede l'inclusione dell'intestazione personalizzata appropriata in tutti i collegamenti.As with the previous two approaches, implementing HATEOAS requires including the appropriate custom header in any links.

Controllo delle versioni tramite il tipo di supportoMedia type versioning

Quando un'applicazione client invia una richiesta HTTP GET a un server Web, è necessario stabilire il formato del contenuto che è possibile gestire tramite un'intestazione Accept, come descritto in precedenza in queste linee guida.When a client application sends an HTTP GET request to a web server it should stipulate the format of the content that it can handle by using an Accept header, as described earlier in this guidance. L'intestazione Accept ha spesso lo scopo di consentire all'applicazione client di specificare se il corpo della risposta deve essere in formato XML, JSON o in un altro formato comune analizzabile dal client.Frequently the purpose of the Accept header is to allow the client application to specify whether the body of the response should be XML, JSON, or some other common format that the client can parse. Tuttavia, è possibile definire tipi di supporti personalizzati che includono informazioni che consentono all'applicazione client di indicare la versione di una risorsa prevista.163However, it is possible to define custom media types that include information enabling the client application to indicate which version of a resource it is expecting. Nell'esempio seguente viene illustrata una richiesta che specifica un'intestazione Accept con il valore application/vnd.adventure-works.v1+json.The following example shows a request that specifies an Accept header with the value application/vnd.adventure-works.v1+json. L'elemento vnd.adventure works.v1 indica al server Web che deve restituire la versione 1 della risorsa, mentre l'elemento json specifica che il corpo della risposta deve essere in formato JSON:The vnd.adventure-works.v1 element indicates to the web server that it should return version 1 of the resource, while the json element specifies that the format of the response body should be JSON:

GET https://adventure-works.com/customers/3 HTTP/1.1
Accept: application/vnd.adventure-works.v1+json

Il codice che gestisce la richiesta è responsabile dell'elaborazione dell'intestazione Accept rispettandola per quanto possibile. L'applicazione client può specificare più formati nell'intestazione Accept e in questo caso il server Web può scegliere il formato più appropriato per il corpo della risposta.The code handling the request is responsible for processing the Accept header and honoring it as far as possible (the client application may specify multiple formats in the Accept header, in which case the web server can choose the most appropriate format for the response body). Il server Web conferma il formato dei dati nel corpo della risposta mediante l'intestazione Content-Type:The web server confirms the format of the data in the response body by using the Content-Type header:

HTTP/1.1 200 OK
Content-Type: application/vnd.adventure-works.v1+json; charset=utf-8

{"id":3,"name":"Contoso LLC","address":"1 Microsoft Way Redmond WA 98053"}

Se l'intestazione Accept non specifica alcun tipo di supporto noto, il server Web potrebbe generare un messaggio di risposta HTTP 406 (Pagina non valida) o restituire un messaggio con un tipo di supporto predefinito.If the Accept header does not specify any known media types, the web server could generate an HTTP 406 (Not Acceptable) response message or return a message with a default media type.

Questo approccio è senza dubbio il meccanismo di controllo delle versioni più puro e si presta naturalmente a HATEOAS, che può includere il tipo MIME dei dati correlati nei collegamenti alle risorse.This approach is arguably the purest of the versioning mechanisms and lends itself naturally to HATEOAS, which can include the MIME type of related data in resource links.

Nota

Quando si seleziona una strategia di controllo delle versioni, è consigliabile tenere in considerazione anche le implicazioni sulle prestazioni, soprattutto la memorizzazione nella cache sul server Web.When you select a versioning strategy, you should also consider the implications on performance, especially caching on the web server. Il controllo delle versioni tramite URI e gli schemi di controllo delle versioni tramite la stringa di query sono adatti alla cache perché la stessa combinazione URI/stringa di query fa riferimento ogni volta agli stessi dati.The URI versioning and Query String versioning schemes are cache-friendly inasmuch as the same URI/query string combination refers to the same data each time.

I meccanismi di controllo delle versioni tramite intestazione e tipo di supporto in genere richiedono logica aggiuntiva per esaminare i valori nell’intestazione personalizzata o nell'intestazione Accept.The Header versioning and Media Type versioning mechanisms typically require additional logic to examine the values in the custom header or the Accept header. In un ambiente su larga scala, la presenza di molti client che usano versioni diverse di un'API Web può comportare una notevole quantità di dati duplicati in una cache lato server.In a large-scale environment, many clients using different versions of a web API can result in a significant amount of duplicated data in a server-side cache. Questo problema può diventare evidente se un'applicazione client comunica con un server Web tramite un proxy che implementa la memorizzazione nella cache e che inoltra una richiesta al server Web solo se attualmente non mantiene una copia dei dati richiesti nella propria cache.This issue can become acute if a client application communicates with a web server through a proxy that implements caching, and that only forwards a request to the web server if it does not currently hold a copy of the requested data in its cache.

Iniziativa OpenAPIOpen API Initiative

L'Iniziativa OpenAPI è stata creata da un consorzio di settore per standardizzare le descrizioni dell'API REST tra i fornitori.The Open API Initiative was created by an industry consortium to standardize REST API descriptions across vendors. Come parte di questa iniziativa, la specifica di Swagger 2.0 è stata rinominata Specifica OpenAPI ed è stata inserita nell'Iniziativa OpenAPI.As part of this initiative, the Swagger 2.0 specification was renamed the OpenAPI Specification (OAS) and brought under the Open API Initiative.

Si consiglia di adottare OpenAPI per le API Web.You may want to adopt OpenAPI for your web APIs. Alcune informazioni da considerare:Some points to consider:

  • La specifica OpenAPI include un set di dettagliate linee guida su come dovrebbe essere progettata un'API REST.The OpenAPI Specification comes with a set of opinionated guidelines on how a REST API should be designed. Questo presenta dei vantaggi per quanto riguarda l'interoperabilità, ma richiede una maggiore attenzione quando si progetta l'API in conformità con la specifica.That has advantages for interoperability, but requires more care when designing your API to conform to the specification.

  • OpenAPI promuove un approccio con priorità al contratto, anziché un approccio con priorità all'implementazione.OpenAPI promotes a contract-first approach, rather than an implementation-first approach. Priorità al contratto vuol dire che l'utente progetta prima di tutto il contratto dell'API, ovvero l'interfaccia, e poi scrive il codice che implementa il contratto.Contract-first means you design the API contract (the interface) first and then write code that implements the contract.

  • Strumenti come Swagger possono generare librerie o documentazione client dai contratti API.Tools like Swagger can generate client libraries or documentation from API contracts. Ad esempio, vedere pagine della Guida ASP.NET Web API con Swagger.For example, see ASP.NET Web API help pages using Swagger.

Altre informazioniMore information