Návrh rozhraní APIAPI design

Většina moderních webových aplikací zveřejňuje rozhraní API, které můžou klienti používat k interakci s aplikací.Most modern web applications expose APIs that clients can use to interact with the application. Dobře navržené webové rozhraní API by mělo být zaměřené na podporu následujících aspektů:A well-designed web API should aim to support:

  • Nezávislost platformy.Platform independence. Rozhraní API by měl být schopný volat jakýkoli klient bez ohledu na to, jak je rozhraní API implementované interně.Any client should be able to call the API, regardless of how the API is implemented internally. To vyžaduje použití standardních protokolů a přijetí mechanismu, pomocí kterého se klient a webová služba můžou dohodnout na formátu vyměňovaných dat.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.

  • Vývoj služby.Service evolution. Webové rozhraní API by mělo mít možnost se vyvíjet a přidávat funkce nezávisle na klientských aplikacích.The web API should be able to evolve and add functionality independently from client applications. Jak se rozhraní API vyvíjí, existující klientské aplikace by měly být nadále schopné fungovat bez úprav.As the API evolves, existing client applications should continue to function without modification. Všechny funkce musí být zjistitelné, aby je klientské aplikace mohly plně využít.All functionality should be discoverable, so that client applications can fully utilize it.

Tento návod popisuje problémy, které byste měli při návrhu webového rozhraní API vzít v úvahu.This guidance describes issues that you should consider when designing a web API.

Seznámení s RESTIntroduction to REST

V roce 2000 Roy Fielding navrhl REST (Representational State Transfer) jako architektonický přístup k navrhování webových služeb.In 2000, Roy Fielding proposed Representational State Transfer (REST) as an architectural approach to designing web services. REST je styl architektury pro vytváření distribuovaných systémů založených na hypermédiích.REST is an architectural style for building distributed systems based on hypermedia. REST je nezávislý na všech podřízených protokolech a není nutně svázán s HTTP.REST is independent of any underlying protocol and is not necessarily tied to HTTP. Většina běžných implementací REST ale jako aplikační protokol používá protokol HTTP a tato příručka se zaměřuje na návrh rozhraní REST API pro protokol HTTP.However, most common REST implementations use HTTP as the application protocol, and this guide focuses on designing REST APIs for HTTP.

Primární výhoda REST přes protokol HTTP je, že používá otevřené standardy a neváže implementaci rozhraní API nebo klientské aplikace na žádnou konkrétní implementaci.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 any specific implementation. Například webová služba REST může být napsaná v ASP.NET a klientské aplikace můžou používat libovolný jazyk nebo sadu nástrojů, které dovedou generovat požadavky HTTP a parsovat odpovědi 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.

Tady jsou některé z hlavní zásad rozhraní RESTful API pomocí protokolu HTTP:Here are some of the main design principles of RESTful APIs using HTTP:

  • Rozhraní REST API jsou navržená kolem prostředků, což je jakýkoli druh objektu, dat nebo služby, ke kterým může klient přistupovat.REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client.

  • Prostředek má identifikátor, což je identifikátor URI, který jednoznačně tento prostředek identifikuje.A resource has an identifier, which is a URI that uniquely identifies that resource. Například identifikátor URI pro konkrétní objednávku zákazníka může být následující:For example, the URI for a particular customer order might be:

    http://adventure-works.com/orders/1
    
  • Klienti komunikují se službou tak, že si vyměňují reprezentace prostředků.Clients interact with a service by exchanging representations of resources. Mnoho webových rozhraní API používá jako formát výměny JSON.Many web APIs use JSON as the exchange format. Například požadavek GET na identifikátor URI uvedený výš může vrátit toto tělo odpovědi:For example, a GET request to the URI listed above might return this response body:

    {"orderId":1,"orderValue":99.90,"productId":1,"quantity":1}
    
  • Rozhraní REST API používají jednotné rozhraní, které pomáhá oddělit implementace klienta a služby.REST APIs use a uniform interface, which helps to decouple the client and service implementations. Rozhraní REST API založený na protokolu HTTP jednotné rozhraní obsahuje pomocí standardních operací protokolu HTTP k provedení operací s prostředky.For REST APIs built on HTTP, the uniform interface includes using standard HTTP verbs to perform operations on resources. Nejběžnější operace jsou GET, POST, PUT, PATCH a DELETE.The most common operations are GET, POST, PUT, PATCH, and DELETE.

  • Rozhraní REST API používají bezstavový model požadavků.REST APIs use a stateless request model. Požadavky HTTP by měly být nezávislé a může k nim dojít v libovolném pořadí, takže udržování přechodných informací o stavu mezi požadavky není vhodné.HTTP requests should be independent and may occur in any order, so keeping transient state information between requests is not feasible. Jediným místem, kde se informace ukládají, jsou samotné prostředky a každý požadavek by měl být atomickou operací.The only place where information is stored is in the resources themselves, and each request should be an atomic operation. Toto omezení umožňuje webovým službám být vysoce škálovatelné, protože není nutné zachovávat žádné vztahy mezi klienty a konkrétními servery.This constraint enables web services to be highly scalable, because there is no need to retain any affinity between clients and specific servers. Každý server může zpracovat jakýkoli požadavek od jakéhokoli klienta.Any server can handle any request from any client. Je ale nutné dodat, že škálovatelnost můžou omezit jiné faktory.That said, other factors can limit scalability. Například mnoho webových služeb zapisuje do backendového úložiště dat, u kterého může být horizontální navýšení kapacity obtížné. (Článek Dělení dat popisuje strategie horizontálního navýšení kapacity úložiště dat.)For example, many web services write to a backend data store, which may be hard to scale out. (The article Data Partitioning describes strategies to scale out a data store.)

  • Rozhraní REST API se řídí hypermediálními odkazy, které jsou obsaženy v reprezentaci.REST APIs are driven by hypermedia links that are contained in the representation. Následující příklad ukazuje reprezentaci objednávky JSON.For example, the following shows a JSON representation of an order. Obsahuje odkazy pro získání nebo aktualizaci zákazníka přidruženého objednávce.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":"http://adventure-works.com/customers/3", "action":"GET" },
            {"rel":"product","href":"http://adventure-works.com/customers/3", "action":"PUT" } 
        ]
    } 
    

V roce 2008 Leonard Richardson navrhl následující model vyspělosti pro webová rozhraní API:In 2008, Leonard Richardson proposed the following maturity model for web APIs:

  • Úroveň 0: Definujte jeden identifikátor URI a všechny operace jako požadavky POST na tento identifikátor URI.Level 0: Define one URI, and all operations are POST requests to this URI.
  • Úroveň 1: Vytvořte oddělené identifikátory URI pro jednotlivé prostředky.Level 1: Create separate URIs for individual resources.
  • Úroveň 2: K definování operací s prostředky používejte metody HTTP.Level 2: Use HTTP methods to define operations on resources.
  • Úroveň 3: Používejte hypermédia (HATEOAS, viz dál).Level 3: Use hypermedia (HATEOAS, described below).

Úroveň 3 odpovídá skutečnému rozhraní RESTful API podle definice Fieldinga.Level 3 corresponds to a truly RESTful API according to Fielding's definition. V praxi mnoho publikovaných webových rozhraní API spadají někam kolem úrovně 2.In practice, many published web APIs fall somewhere around level 2.

Uspořádání rozhraní API kolem prostředkůOrganize the API around resources

Soustřeďte se na obchodní entity, které webové rozhraní API zveřejňuje.Focus on the business entities that the web API exposes. V systému elektronického obchodování můžou být primárními entitami například zákazníci a objednávky.For example, in an e-commerce system, the primary entities might be customers and orders. Vytvoření objednávky lze dosáhnout odesláním požadavku HTTP POST, který obsahuje informace o objednávce.Creating an order can be achieved by sending an HTTP POST request that contains the order information. Odpověď HTTP označuje, zda byla objednávka zadána úspěšně, nebo ne.The HTTP response indicates whether the order was placed successfully or not. Pokud je to možné, identifikátory URI by měly vycházet z podstatných jmen (prostředků), a ne sloves (operací s prostředkem).When possible, resource URIs should be based on nouns (the resource) and not verbs (the operations on the resource).

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

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

Prostředek byl neměl být založený na jednotlivé fyzické datové položce.A resource does not have to be based on a single physical data item. Prostředek objednávky může být například implementován interně jako několik tabulek v relační databázi, ale zobrazuje se klientovi jako jedna entita.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. Vyhněte se vytváření rozhraní API, která jednoduše zrcadlí interní strukturu databáze.Avoid creating APIs that simply mirror the internal structure of a database. Účelem REST je modelovat entity a operace, které aplikace může s těmito entitami provádět.The purpose of REST is to model entities and the operations that an application can perform on those entities. Klientovi by neměla být zveřejněna interní implementace.A client should not be exposed to the internal implementation.

Entity jsou často seskupené do kolekcí (objednávky, zákazníci).Entities are often grouped together into collections (orders, customers). Kolekce je samostatný prostředek, který nesouvisí s položkou v kolekci a musí mít svůj vlastní identifikátor URI.A collection is a separate resource from the item within the collection, and should have its own URI. Následující identifikátor URI může například představovat kolekci objednávek:For example, the following URI might represent the collection of orders:

http://adventure-works.com/orders

Odeslání požadavku HTTP GET identifikátoru URI kolekce načte seznam položek v kolekci.Sending an HTTP GET request to the collection URI retrieves a list of items in the collection. Každá položka v kolekci má také svůj vlastní jedinečný identifikátor URI.Each item in the collection also has its own unique URI. Požadavek HTTP GET na identifikátor URI položky vrátí podrobnosti o této položce.An HTTP GET request to the item's URI returns the details of that item.

Přijměte konzistentní zásady vytváření názvů pro identifikátory URI.Adopt a consistent naming convention in URIs. Obecně platí, že je dobré pro identifikátory URI odkazující na kolekce používat podstatná jména v množném čísle.In general, it helps to use plural nouns for URIs that reference collections. Je dobrým zvykem organizovat identifikátory URI pro kolekce a položky do hierarchie.It's a good practice to organize URIs for collections and items into a hierarchy. Například /customers je cesta ke kolekci zákazníků a /customers/5 je cesta k zákazníkovi s ID hodnoty 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. Tento přístup pomáhá, aby webové rozhraní API bylo intuitivní.This approach helps to keep the web API intuitive. Navíc mnoho architektur webových rozhraní API může směrovat požadavky na parametrizované cesty identifikátorů URI, takže můžete třeba definovat trasu pro cestu /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}.

Zvažte také vztahy mezi různými typy prostředků a jak je možné tato přidružení zveřejnit.Also consider the relationships between different types of resources and how you might expose these associations. Například /customers/5/orders může představovat všechny objednávky zákazníka číslo 5.For example, the /customers/5/orders might represent all of the orders for customer 5. Můžete také postupovat opačným směrem a reprezentovat přidružení od objednávky zpátky k zákazníkovi pomocí identifikátoru URI, jako je /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. Rozšíření tohoto model příliš daleko ale může vést k poněkud těžkopádné implementaci.However, extending this model too far can become cumbersome to implement. Lepším řešením je poskytnout v těle zprávy s odpovědí HTTP odkazy na související prostředky s možností navigace.A better solution is to provide navigable links to associated resources in the body of the HTTP response message. Tento mechanismus je podrobně popsaný v další části o přístupu HATEOAS pro povolení navigace k souvisejícím prostředkům.This mechanism is described in more detail in the section Using the HATEOAS Approach to Enable Navigation To Related Resources later.

Ve složitějších systémech může být lákavé poskytovat identifikátory URI, které umožní klientovi procházet několik úrovní relací, jako například /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. Tuto úroveň složitosti ale může být poměrně obtížné udržovat a není flexibilní, pokud se v budoucnu vztahy mezi prostředky změní.However, this level of complexity can be difficult to maintain and is inflexible if the relationships between resources change in the future. Raději zkuste udržovat identifikátory URI poměrně jednoduché.Instead, try to keep URIs relatively simple. Jakmile aplikace obsahuje odkaz na prostředek, mělo by být možné použít tento odkaz k nalezení položek souvisejících s tímto prostředkem.Once an application has a reference to a resource, it should be possible to use this reference to find items related to that resource. Předchozí dotaz lze nahradit identifikátorem URI /customers/1/orders a vyhledat všechny objednávky pro zákazníka 1, a potom pomocí /orders/99/products najít produkty v této objednávce.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.

Tip

Vyhněte se nutnosti používat identifikátory URI prostředků složitější než kolekce/položka/kolekce.Avoid requiring resource URIs more complex than collection/item/collection.

Dalším faktorem je, že všechny webové požadavky vytvářejí zatížení webového serveru.Another factor is that all web requests impose a load on the web server. Čím je požadavků víc, tím je zatížení větší.The more requests, the bigger the load. Proto se pokuste vyhnout příliš „upovídaným“ webovým rozhraním API, která zveřejňují velké množství malých prostředků.Therefore, try to avoid "chatty" web APIs that expose a large number of small resources. Taková rozhraní API můžou od klientské aplikace vyžadovat odesílání více požadavků k vyhledání všech dat, která jsou potřeba.Such an API may require a client application to send multiple requests to find all of the data that it requires. Místo toho se můžete snažit denormalizovat data a kombinovat související informace do větších prostředků, které jde načíst jedním požadavkem.Instead, you might want to denormalize the data and combine related information into bigger resources that can be retrieved with a single request. Je ale potřeba tento přístup vyvážit s režií při načítání dat, která klient nepotřebuje.However, you need to balance this approach against the overhead of fetching data that the client doesn't need. Načítání velkých objektů můžete zvýšit latenci požadavku a generovat další náklady na šířku pásma.Retrieving large objects can increase the latency of a request and incur additional bandwidth costs. Další informace o těchto antivzorech výkonu najdete v tématech Přetížení vstupně-výstupních operací a Nadbytečné načítání.For more information about these performance antipatterns, see Chatty I/O and Extraneous Fetching.

Vyhněte se zavedení závislostí mezi webovým rozhraním API a podkladovými zdroji dat.Avoid introducing dependencies between the web API and the underlying data sources. Například pokud jsou vaše data uložená v relační databázi, webové rozhraní API nemusí nutně zveřejňovat každou tabulku jako kolekci prostředků.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. Ve skutečnosti je to pravděpodobně špatný návrh.In fact, that's probably a poor design. Místo toho přemýšlejte o webovém rozhraní API jako o abstrakci databáze.Instead, think of the web API as an abstraction of the database. V případě potřeby zaveďte vrstvu mapování mezi databází a webovým rozhraním API.If necessary, introduce a mapping layer between the database and the web API. Tím způsobem jsou klientské aplikace izolované od změn schématu podkladové databáze.That way, client applications are isolated from changes to the underlying database scheme.

Navíc nemusí být možné mapovat každou operaci implementovanou webovým rozhraním API na konkrétní prostředek.Finally, it might not be possible to map every operation implemented by a web API to a specific resource. Můžete například zpracovávat takové neprostředkové scénáře, kdy se pomocí požadavku HTTP vyvolá funkce a výsledek se vrátí jako zpráva s odpovědí HTTP.You can handle such non-resource scenarios through HTTP requests that invoke a function and return the results as an HTTP response message. Webové rozhraní API, které implementuje jednoduché operace kalkulačky, jako je sčítání a odečítání, může například poskytovat identifikátory URI, které zveřejňují tyto operace jako pseudoprostředky a používají řetězec dotazu k určení požadovaných parametrů.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. Například požadavek GET na identifikátor URI /add?operand1=99&operand2=1 by vrátil zprávu s odpovědí, která by v těle obsahovala hodnotu 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. Tyto tvary identifikátorů URI ale používejte přiměřeně.However, only use these forms of URIs sparingly.

Definování operací z hlediska metod HTTPDefine operations in terms of HTTP methods

Protokol HTTP definuje několik metod, které žádosti přiřazují sémantický význam.The HTTP protocol defines a number of methods that assign semantic meaning to a request. Běžné metody HTTP, které používá většina webových rozhraní RESTful API, jsou následující:The common HTTP methods used by most RESTful web APIs are:

  • GET načte reprezentaci prostředku se zadaným identifikátorem URI.GET retrieves a representation of the resource at the specified URI. Tělo zprávy s odpovědí obsahuje podrobnosti o požadovaném prostředku.The body of the response message contains the details of the requested resource.
  • POST vytvoří nový prostředek se zadaným identifikátorem URI.POST creates a new resource at the specified URI. Tělo zprávy požadavku obsahuje podrobnosti o novém prostředku.The body of the request message provides the details of the new resource. Metodu POST jde také použít k aktivaci operací, které ve skutečnosti nevytváří prostředky.Note that POST can also be used to trigger operations that don't actually create resources.
  • PUT vytvoří nebo nahradí prostředek se zadaným identifikátorem URI.PUT either creates or replaces the resource at the specified URI. Tělo zprávy požadavku určuje prostředek, který se má vytvořit nebo aktualizovat.The body of the request message specifies the resource to be created or updated.
  • PATCH provede částečnou aktualizaci prostředku.PATCH performs a partial update of a resource. Tělo požadavku určuje sadu změn, které se mají použít na prostředek.The request body specifies the set of changes to apply to the resource.
  • DELETE odebere prostředek se zadaným identifikátorem URI.DELETE removes the resource at the specified URI.

Účinek konkrétního požadavku by měl záviset na tom, jestli je prostředek kolekce, nebo jednotlivá položka.The effect of a specific request should depend on whether the resource is a collection or an individual item. Následující tabulka shrnuje běžné konvence přijaté většinou implementací RESTful pomocí příkladů z elektronického obchodování.The following table summarizes the common conventions adopted by most RESTful implementations using the ecommerce example. Všimněte si, že ne všechny tyto požadavky se musí implementovat. Závisí to na konkrétním scénáři.Note that not all of these requests might be implemented; it depends on the specific scenario.

ProstředekResource POSTPOST GETGET PUTPUT DELETEDELETE
/customers/customers Vytvoření nového zákazníkaCreate a new customer Načtení všech zákazníkůRetrieve all customers Hromadná aktualizace zákazníkůBulk update of customers Odebrání všech zákazníkůRemove all customers
/customers/1/customers/1 ChybaError Načtení podrobností pro zákazníka 1Retrieve the details for customer 1 Aktualizace podrobností pro zákazníka 1, pokud existujeUpdate the details of customer 1 if it exists Odebrání zákazníka 1Remove customer 1
/customers/1/orders/customers/1/orders Vytvoření nové objednávky pro zákazníka 1Create a new order for customer 1 Načtení všech objednávek pro zákazníka 1Retrieve all orders for customer 1 Hromadná aktualizace objednávek pro zákazníka 1Bulk update of orders for customer 1 Odebrání všech objednávek pro zákazníka 1Remove all orders for customer 1

Rozdíly mezi metodami POST, PUT a PATCH můžou být matoucí.The differences between POST, PUT, and PATCH can be confusing.

  • Požadavek POST vytvoří prostředek.A POST request creates a resource. Server přiřadí novému prostředku identifikátor URI a vrátí tento identifikátor URI klientovi.The server assigns a URI for the new resource, and returns that URI to the client. V modelu REST se často používají požadavky POST na kolekce.In the REST model, you frequently apply POST requests to collections. Nový prostředek se přidá do kolekce.The new resource is added to the collection. Požadavek POST jde také použít k odeslání dat ke zpracování pro existující prostředek, bez jakéhokoli vytváření nového prostředku.A POST request can also be used to submit data for processing to an existing resource, without any new resource being created.

  • Požadavek PUT vytvoří prostředek nebo aktualizuje existující prostředek.A PUT request creates a resource or updates an existing resource. Klient určuje identifikátor URI pro prostředek.The client specifies the URI for the resource. Tělo požadavku obsahuje úplnou reprezentaci prostředku.The request body contains a complete representation of the resource. Pokud prostředek s tímto identifikátorem URI už existuje, nahradí se.If a resource with this URI already exists, it is replaced. V opačném případě se vytvoří nový prostředek, pokud to server podporuje.Otherwise a new resource is created, if the server supports doing so. Požadavky PUT se nejčastěji používají na prostředky, které jsou jednotlivými položkami, jako je například konkrétní zákazník, nikoli kolekce.PUT requests are most frequently applied to resources that are individual items, such as a specific customer, rather than collections. Server může prostřednictvím požadavku PUT podporovat aktualizace, ale ne vytvoření.A server might support updates but not creation via PUT. Podpora vytváření prostřednictvím požadavků PUT závisí na tom, jestli klient může smysluplně přiřadit identifikátor URI prostředku před jeho existencí.Whether to support creation via PUT depends on whether the client can meaningfully assign a URI to a resource before it exists. Pokud ne, pak k vytváření prostředků používejte POST a pomocí PUT nebo PATCH aktualizujte.If not, then use POST to create resources and PUT or PATCH to update.

  • Požadavek PATCH provede částečnou aktualizaci existujícího prostředku.A PATCH request performs a partial update to an existing resource. Klient určuje identifikátor URI pro prostředek.The client specifies the URI for the resource. Tělo požadavku určuje sadu změn, které se mají použít na prostředek.The request body specifies a set of changes to apply to the resource. To může být efektivnější než použití PUT, protože klient odešle jenom změny, ne celou reprezentaci prostředku.This can be more efficient than using PUT, because the client only sends the changes, not the entire representation of the resource. Technicky může PATCH taky vytvořit nový prostředek (zadáním sady aktualizací na „nulový“ prostředek), pokud to server podporuje.Technically PATCH can also create a new resource (by specifying a set of updates to a "null" resource), if the server supports this.

Požadavky PUT musí být idempotentní.PUT requests must be idempotent. Pokud klient odešle stejný požadavek PUT víckrát, výsledky by měly být vždycky stejné (stejný prostředek bude upravený pomocí stejných hodnot).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). U požadavků POST a PATCH není idempotence zaručená.POST and PATCH requests are not guaranteed to be idempotent.

Soulad se sémantikou HTTPConform to HTTP semantics

Tato část popisuje některé typické aspekty návrhu rozhraní API, které splňuje specifikace protokolu HTTP.This section describes some typical considerations for designing an API that conforms to the HTTP specification. Nezahrnuje ale všechny možné podrobnosti nebo scénáře.However, it doesn't cover every possible detail or scenario. V případě pochybností si přečtěte specifikaci protokolu HTTP.When in doubt, consult the HTTP specifications.

Typy médiíMedia types

Jak už bylo zmíněno dříve, klienti a servery si vyměňují reprezentace prostředků.As mentioned earlier, clients and servers exchange representations of resources. Například v požadavku POST obsahuje tělo požadavku reprezentaci vytvářeného prostředku.For example, in a POST request, the request body contains a representation of the resource to create. V požadavek GET obsahuje tělo odpovědi reprezentaci načítaného prostředku.In a GET request, the response body contains a representation of the fetched resource.

V protokolu HTTP jsou formáty určené prostřednictvím typů médií, označovaných taky jako typy MIME.In the HTTP protocol, formats are specified through the use of media types, also called MIME types. Pro nebinární data většin webových rozhraní API podporuje JSON (typ média = application/json) a případně XML (typ média = application/xml).For non-binary data, most web APIs support JSON (media type = application/json) and possibly XML (media type = application/xml).

Hlavička Content-Type v požadavku nebo odpovědi určuje formát reprezentace.The Content-Type header in a request or response specifies the format of the representation. Tady je příklad požadavku POST, který obsahuje data JSON:Here is an example of a POST request that includes JSON data:

POST http://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}

Pokud server nepodporuje typ média, měl by vrátit stavový kód HTTP 415 (Nepodporovaný typ média).If the server doesn't support the media type, it should return HTTP status code 415 (Unsupported Media Type).

Požadavek klienta může obsahovat hlavičku Accept, která obsahuje seznam typů médií, které klient ve zprávě s odpovědí ze serveru přijme.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. Příklad:For example:

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

Pokud server nemůže splnit žádný z uvedených typů médií, měl by vrátit stavový kód HTTP 406 (Nepřijatelné).If the server cannot match any of the media type(s) listed, it should return HTTP status code 406 (Not Acceptable).

Metody GETGET methods

Úspěšná metoda GET obvykle vrátí stavový kód HTTP 200 (OK).A successful GET method typically returns HTTP status code 200 (OK). Pokud se prostředek nenašel, metoda by měla vrátit kód 404 (Nenalezeno).If the resource cannot be found, the method should return 404 (Not Found).

Metody POSTPOST methods

Pokud metoda POST vytvoří nový prostředek, vrátí stavový kód HTTP 201 (Vytvořeno).If a POST method creates a new resource, it returns HTTP status code 201 (Created). Identifikátor URI nového prostředku je součástí hlavičky Location v odpovědi.The URI of the new resource is included in the Location header of the response. Tělo odpovědi obsahuje reprezentaci prostředku.The response body contains a representation of the resource.

Pokud metoda provede nějaké zpracování, ale nevytvoří nový prostředek, můžete metoda vrátit stavový kód HTTP 200 a zahrnout výsledek operace do těla odpovědi.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. Případně pokud neexistuje žádný výsledek určený k vrácení, metoda může vrátit stavový kód HTTP 204 (Bez obsahu) s žádnou odpovědí.Alternatively, if there is no result to return, the method can return HTTP status code 204 (No Content) with no response body.

Pokud klient vloží do požadavku neplatná data, server by měl vrátit stavový kód HTTP 400 (Chybný požadavek).If the client puts invalid data into the request, the server should return HTTP status code 400 (Bad Request). Tělo odpovědi může obsahovat další informace o chybě nebo odkaz na identifikátor URI, který obsahuje další podrobnosti.The response body can contain additional information about the error or a link to a URI that provides more details.

Metody PUTPUT methods

Pokud metoda PUT vytvoří nový prostředek, vrátí stavový kód HTTP 201 (Vytvořeno), stejně jako metoda POST.If a PUT method creates a new resource, it returns HTTP status code 201 (Created), as with a POST method. Pokud metoda aktualizuje existující prostředek, vrátí hodnotu 200 (OK) nebo 204 (Bez obsahu).If the method updates an existing resource, it returns either 200 (OK) or 204 (No Content). V některých případech nemusí být možné aktualizovat existující prostředek.In some cases, it might not be possible to update an existing resource. V takovém případě zvažte vrácení stavového kódu protokolu HTTP 409 (Konflikt).In that case, consider returning HTTP status code 409 (Conflict).

Zvažte implementaci hromadné operace HTTP PUT, která může hromadně aktualizovat víc prostředků v kolekci.Consider implementing bulk HTTP PUT operations that can batch updates to multiple resources in a collection. Požadavek PUT musí určovat identifikátor URI kolekce a tělo požadavku musí určovat podrobnosti o měněných prostředcích.The PUT request should specify the URI of the collection, and the request body should specify the details of the resources to be modified. Tento přístup může pomoct snížit upovídanost a zlepšit výkon.This approach can help to reduce chattiness and improve performance.

Metody PATCHPATCH methods

S požadavkem PATCH klient odešle sadu aktualizací pro existující prostředek ve tvaru dokumentu opravy.With a PATCH request, the client sends a set of updates to an existing resource, in the form of a patch document. Server zpracuje dokument opravy a provede aktualizaci.The server processes the patch document to perform the update. Dokument opravy nepopisuje celý prostředek, ale jen sadu změn k použití.The patch document doesn't describe the whole resource, only a set of changes to apply. Specifikace pro metodu PATCH (RFC 5789) nedefinuje konkrétní formát pro dokumenty opravy.The specification for the PATCH method (RFC 5789) doesn't define a particular format for patch documents. Formát musí být odvozený od typu média v požadavku.The format must be inferred from the media type in the request.

JSON je pravděpodobně nejběžnější formát dat pro webová rozhraní API.JSON is probably the most common data format for web APIs. Existují dva hlavní formáty oprav založené na JSON, oprava JSON a sloučená oprava JSON.There are two main JSON-based patch formats, called JSON patch and JSON merge patch.

Sloučená oprava JSON je poněkud jednodušší.JSON merge patch is somewhat simpler. Dokument opravy má stejnou strukturu jako původní prostředek JSON, ale zahrnuje jen dílčí sadu polí, která by se měla změnit nebo přidat.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. Kromě toho lze v dokumentu opravy pole odstranit zadáním hodnoty pole null.In addition, a field can be deleted by specifying null for the field value in the patch document. (To znamená, že sloučená oprava není vhodná, pokud původní prostředek může mít explicitní hodnoty null.)(That means merge patch is not suitable if the original resource can have explicit null values.)

Předpokládejme například, že původní prostředek má následující reprezentaci JSON:For example, suppose the original resource has the following JSON representation:

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

Tady je možná sloučená oprava JSON pro tento prostředek:Here is a possible JSON merge patch for this resource:

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

Říká serveru, aby aktualizoval pole „price“, odstranil pole „color“ a přidal pole „size“.This tells the server to update "price", delete "color", and add "size". Pole „name“ a „category“ zůstávají nezměněná."Name" and "category" are not modified. Podrobnosti o sloučené opravě JSON najdete v dokumentu RFC 7396.For the exact details of JSON merge patch, see RFC 7396. Typ média pro sloučenou opravu JSON je application/merge-patch+json.The media type for JSON merge patch is "application/merge-patch+json".

Sloučená oprava není vhodná, pokud původní prostředek může obsahovat explicitní hodnoty null, z důvodu zvláštního významu hodnoty null v dokumentu opravy.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. Dokument opravy také neurčuje pořadí, v jakém má server provádět aktualizace.Also, the patch document doesn't specify the order that the server should apply the updates. To může nebo nemusí vadit, v závislosti na datech a doméně.That may or may not matter, depending on the data and the domain. Oprava JSON, definovaná v dokumentu RFC 6902, je flexibilnější.JSON patch, defined in RFC 6902, is more flexible. Určuje změny jako posloupnost operací, které se mají použít.It specifies the changes as a sequence of operations to apply. Operace zahrnují přidání, odebrání, náhradu, kopírování a testování (k ověření hodnot).Operations include add, remove, replace, copy, and test (to validate values). Typ média pro opravu JSON je application/json-patch+json.The media type for JSON patch is "application/json-patch+json".

Tady jsou uvedené některé typické chybové stavy, které můžou nastat při zpracování požadavku PATCH, spolu s odpovídajícím stavovým kódem HTTP.Here are some typical error conditions that might be encountered when processing a PATCH request, along with the appropriate HTTP status code.

Chybový stavError condition Stavový kód HTTPHTTP status code
Formát dokument opravy není podporovaný.The patch document format isn't supported. 415 (Nepodporovaný typ média)415 (Unsupported Media Type)
Chybný formát dokumentu opravy.Malformed patch document. 400 (Chybný požadavek)400 (Bad Request)
Dokumentu opravy je platný, ale změny nejde použít na prostředek v jeho aktuálním stavu.The patch document is valid, but the changes can't be applied to the resource in its current state. 409 (Konflikt)409 (Conflict)

Metody DELETEDELETE methods

Pokud je operace odstranění úspěšná, webový server by měl odpovědět stavovým kódem HTTP 204, který určuje, že proces byl úspěšně zpracován, ale že tělo odpovědi neobsahuje žádné další informace.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. Pokud prostředek neexistuje, může webový server vrátit chybu HTTP 404 (Nenalezeno).If the resource doesn't exist, the web server can return HTTP 404 (Not Found).

Asynchronních operaceAsynchronous operations

Někdy můžou operace POST, PUT, PATCH nebo DELETE v některých případech vyžadovat zpracování, jehož dokončení chvíli trvá.Sometimes a POST, PUT, PATCH, or DELETE operation might require processing that takes awhile to complete. Pokud čekáte na dokončení, než odešlete odpověď klientovi, může to způsobit nepřijatelnou latenci.If you wait for completion before sending a response to the client, it may cause unacceptable latency. V takovém případě zvažte provedení operace asynchronně.If so, consider making the operation asynchronous. Vraťte stavový kód HTTP 202 (Přijato) k označení, že žádost byla přijata ke zpracování, ale není dokončená.Return HTTP status code 202 (Accepted) to indicate the request was accepted for processing but is not completed.

Je potřeba zveřejnit koncový bod, který vrací stav asynchronního požadavku, aby klient mohl sledovat stav pomocí cyklického dotazování na koncový bod stavu.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. Zahrňte identifikátor URI koncového bodu stavu do hlavičky Location odpovědi 202.Include the URI of the status endpoint in the Location header of the 202 response. Příklad:For example:

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

Pokud klient odešle požadavek GET na tento koncový bod, odpověď by měla obsahovat aktuální stav požadavku.If the client sends a GET request to this endpoint, the response should contain the current status of the request. Volitelně může obsahovat také odhadovaný čas dokončení nebo odkaz na zrušení operace.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" }
}

Pokud asynchronní operace vytvoří nový prostředek, koncový bod stavu by měl po dokončení operace vrátit stavový kód 303 (Zobrazit jiné).If the asynchronous operation creates a new resource, the status endpoint should return status code 303 (See Other) after the operation completes. V odpovědi 303 uveďte hlavičku Location, která obsahuje identifikátor URI nového prostředku: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

Další informace najdete v popisu asynchronních operací v REST.For more information, see Asynchronous operations in REST.

Filtrování a stránkování datFilter and paginate data

Zveřejnění kolekce prostředků prostřednictvím jednoho identifikátoru URI může vést k tomu, že aplikace načítají velké objemy dat, i když potřebují jenom část informací.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. Předpokládejme například, že klientská aplikace potřebuje najít objednávky s cenou vyšší než daná hodnota.For example, suppose a client application needs to find all orders with a cost over a specific value. Může načíst všechny objednávky z identifikátoru URI /orders a pak tyto objednávky vyfiltrovat na straně klienta.It might retrieve all orders from the /orders URI and then filter these orders on the client side. Tento proces je zjevně vysoce neefektivní.Clearly this process is highly inefficient. Zbytečně plýtvá šířkou pásma a výkonem serveru, který je hostitelem webového rozhraní API.It wastes network bandwidth and processing power on the server hosting the web API.

Místo toho může rozhraní API umožnit předání filtru v řetězci dotazu identifikátoru URI, například /orders?minCost=n.Instead, the API can allow passing a filter in the query string of the URI, such as /orders?minCost=n. Webové rozhraní API je poté zodpovědné za parsování a zpracování parametru minCost v řetězci dotazu a vrácení filtrovaných výsledků na straně serveru.The web API is then responsible for parsing and handling the minCost parameter in the query string and returning the filtered results on the sever side.

Požadavky GET na prostředky kolekce můžou potenciálně vrátit velký počet položek.GET requests over collection resources can potentially return a large number of items. Měli byste navrhnout webové rozhraní API tak, aby omezovalo množství dat vrácených každým jednotlivým požadavkem.You should design a web API to limit the amount of data returned by any single request. Zvažte podporu řetězců dotazu, které určují maximální počet položek k načtení a počáteční posun v kolekci.Consider supporting query strings that specify the maximum number of items to retrieve and a starting offset into the collection. Příklad:For example:

/orders?limit=25&offset=50

Zvažte taky nastavení horního limitu počtu vrácených položek, aby se zabránilo útokům typu Denial of Service.Also consider imposing an upper limit on the number of items returned, to help prevent Denial of Service attacks. Požadavky GET, které vracejí stránkovaná data, by měly pomáhat klientským aplikacím tak, že budou také obsahovat určitou formu metadata indikující celkový počet prostředků dostupných v kolekci.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. Můžete také zvážit další strategie inteligentního stránkování. Další informace najdete v poznámkách k návrhu rozhraní API – inteligentní stránkování.You might also consider other intelligent paging strategies; for more information, see API Design Notes: Smart Paging

Podobné strategie můžete použít k řazení dat během jejich načítání tím, že zavedete parametr řazení, který přebírá název pole jako hodnotu, například /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. Tento postup však může mít negativní vliv na ukládání do mezipaměti, protože parametry řetězce dotazu tvoří část identifikátoru prostředku, který mnoho implementací mezipaměti používá jako klíč pro uložená data.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.

Tento přístup můžete rozšířit, abyste omezili počet polí vracených pro každou položku, pokud každá položka obsahuje velké množství dat.You can extend this approach to limit the fields returned for each item, if each item contains a large amount of data. Můžete například použít parametr řetězce dotazu, který přijímá čárkami oddělený seznam polí, například /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.

Dejte všem volitelným parametrům v řetězcích dotazů smysluplné výchozí hodnoty.Give all optional parameters in query strings meaningful defaults. Například nastavte parametr limit na hodnotu 10 a parametr offset na hodnotu 0, pokud implementujete stránkování, nastavte parametr řazení na klíč prostředku, pokud implementujete řazení, a nastavte parametr fields na všechna pole v prostředku, pokud podporujete projekce.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.

Podpora částečných odpovědí pro velké binární prostředkySupport partial responses for large binary resources

Prostředek může obsahovat velká binární pole, například soubory nebo obrázky.A resource may contain large binary fields, such as files or images. Abyste vyřešili problémy způsobené nespolehlivým a přerušovaným připojením a vylepšili dobu odezvy, zvažte, jestli u těchto prostředků nepovolit načítání v blocích.To overcome problems caused by unreliable and intermittent connections and to improve response times, consider enabling such resources to be retrieved in chunks. K tomuto účelu by webové rozhraní API mělo pro požadavky GET pro velké prostředky podporovat hlavičku Accept-Ranges.To do this, the web API should support the Accept-Ranges header for GET requests for large resources. Tyto hlavička označuje, že operace GET podporuje částečné požadavky.This header indicates that the GET operation supports partial requests. Klientská aplikace může odesílat požadavky GET, které vrátí podmnožinu prostředku, určenou jako rozsah bajtů.The client application can submit GET requests that return a subset of a resource, specified as a range of bytes.

Zvažte také pro tyto prostředky implementaci požadavku HTTP HEAD.Also, consider implementing HTTP HEAD requests for these resources. Požadavek HEAD je podobný požadavku GET s tím rozdílem, že vrátí jenom hlavičky HTTP, které prostředek popisují, s prázdným tělem zprávy.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. Klientská aplikace může vydat požadavek HEAD k určení, jestli se má prostředek načíst pomocí částečných požadavků GET.A client application can issue a HEAD request to determine whether to fetch a resource by using partial GET requests. Příklad:For example:

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

Tady je ukázková zpráva odpovědi:Here is an example response message:

HTTP/1.1 200 OK

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

Hlavička Content-Length dává celkovou velikost prostředku a hlavička Accept-Ranges označuje, že odpovídající operace GET podporuje částečné výsledky.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. Klientská aplikace můžete použít tyto informace k načtení obrázku po menších částech.The client application can use this information to retrieve the image in smaller chunks. První požadavek načte prvních 2 500 bajtů pomocí hlavičky Range:The first request fetches the first 2500 bytes by using the Range header:

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

Zpráva odpovědi označuje, že se jedná o částečnou odpověď, vrácením stavového kódu HTTP 206.The response message indicates that this is a partial response by returning HTTP status code 206. Hlavička Content-Length určuje skutečný počet bajtů vrácených v tělu zprávy (nikoli velikost prostředku), a hlavička Content-Range označuje, o kterou část prostředku se jedná (bajty 0 až 2499 z 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

[...]

Následná žádost z klientské aplikace může načíst zbytek prostředku.A subsequent request from the client application can retrieve the remainder of the resource.

Jednou z primárních motivací REST je, aby bylo možné projít celou sadu prostředků bez nutnosti předchozí znalosti schématu identifikátorů 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. Každý požadavek HTTP GET by měl vrátit informace potřebné k vyhledání prostředků souvisejících přímo s vyžádaným objektem prostřednictvím hypertextových odkazů obsažených v odpovědi a měl by také dostat informace, které popisují operace dostupné pro každý z těchto prostředků.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. Tento princip se označuje zkratkou HATEOAS (Hypertext as the Engine of Application State).This principle is known as HATEOAS, or Hypertext as the Engine of Application State. Systém je efektivně konečný automat a odpověď na každý požadavek obsahuje informace potřebné k přesunu z jednoho stavu do jiného; žádné další informace by měly být nutné.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.

Poznámka

Aktuálně neexistují žádné standardy nebo specifikace, které definují modelování principu HATEOAS.Currently there are no standards or specifications that define how to model the HATEOAS principle. Příklady uvedené v této části ilustrují jedno z možných řešení.The examples shown in this section illustrate one possible solution.

Pro zpracování relace mezi objednávkou a zákazníkem může například reprezentace objednávky zahrnovat odkazy, které určují dostupné operace pro zákazníka objednávky.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. Tady je možná reprezentace:Here is a possible representation:

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

V tomto příkladu pole links obsahuje sadu odkazů.In this example, the links array has a set of links. Každý odkaz představuje operaci se související entitou.Each link represents an operation on a related entity. Data pro každý odkaz zahrnují relaci (customer), identifikátor URI (http://adventure-works.com/customers/3), metodu HTTP a podporované typy MIME.The data for each link includes the relationship ("customer"), the URI (http://adventure-works.com/customers/3), the HTTP method, and the supported MIME types. Toto jsou veškeré informace, které klientská aplikace potřebuje k vyvolání operace.This is all the information that a client application needs to be able to invoke the operation.

Pole links obsahuje také informace s odkazem na vlastní prostředek, který byl načten.The links array also includes self-referencing information about the resource itself that has been retrieved. Ty mají relaci self.These have the relationship self.

Sada odkazů, které jsou vrácené, se může změnit v závislosti na stavu prostředku.The set of links that are returned may change, depending on the state of the resource. Toto je naplnění pojmu „Hypertext as the Engine of Application State“ (Hypertext jako aplikační stav).This is what is meant by hypertext being the "engine of application state."

Správa verzí webového rozhraní RESTful APIVersioning a RESTful web API

Je vysoce nepravděpodobné, že webové rozhraní API zůstane statické.It is highly unlikely that a web API will remain static. Se změnami obchodních požadavků můžou být přidány nové kolekce prostředků, můžou se změnit relace mezi prostředky a může se upravit struktura dat v prostředcích.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. Zatímco aktualizace webového rozhraní API, aby zpracovávalo nové nebo odlišné požadavky, je poměrně přímočarý proces, musíte zvážit důsledky, které tyto změny budou mít na klientské aplikace využívající webové rozhraní API.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. Problém je, že i když vývojář navrhující a implementující webové rozhraní API má plnou kontrolu nad tímto rozhraním API, vývojář nemá stejnou úroveň kontroly nad klientskými aplikacemi, které můžou vytvářet jiné, vzdáleně působící organizace.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. Primární pravidlo je umožnit existujícím klientským aplikacím, aby fungovaly beze změny, a současně umožnit novým klientským aplikacím, aby mohly využívat nové funkce a prostředky.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.

Správa verzí umožňuje webovému rozhraní API označovat funkce a prostředky, které zveřejňuje, a klientské aplikace můžou odesílat požadavky, které jsou směrované na konkrétní verzi funkce nebo prostředku.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. Následující části popisují několik různých přístupů, kdy každý má své výhody a kompromisy.The following sections describe several different approaches, each of which has its own benefits and trade-offs.

Bez správy verzíNo versioning

Toto je nejjednodušší přístup a může být přijatelný pro některá interní rozhraní API.This is the simplest approach, and may be acceptable for some internal APIs. Velké změny můžou být reprezentované jako nové prostředky nebo nové odkazy.Big changes could be represented as new resources or new links. Přidávání obsahu do existujících prostředků nemusí znamenat velkou změnu, protože klientské aplikace, které nečekají zobrazení tohoto obsahu, ho jednoduše ignorují.Adding content to existing resources might not present a breaking change as client applications that are not expecting to see this content will simply ignore it.

Například požadavek na identifikátor URI http://adventure-works.com/customers/3 by měla vrátit podrobnosti jednoho zákazníka obsahující id, name, a address pole očekávanou klientská aplikace:For example, a request to the URI http://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"}

Poznámka

Pro jednoduchost ukázkové odpovědi uvedené v této části nezahrnují odkazy HATEOAS.For simplicity, the example responses shown in this section do not include HATEOAS links.

Pokud se do schématu prostředku zákazníka přidá pole DateCreated, bude odpověď vypadat takto: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"}

Existující klientské aplikace můžou dál fungovat správně, pokud jsou schopné ignorovat nerozpoznaná pole, zatímco nové klientské aplikace můžou být navržené tak, aby toto nové pole zapracovávaly.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. Ale pokud dojde k radikálnější změně schématu prostředků (například odebrání nebo přejmenování polí) nebo ke změně relací mezi prostředky, pak můžou představovat velké změny, které zabraňují existujícím klientským aplikacím fungovat správně.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. V těchto situacích zvažte jeden z následujících přístupů.In these situations you should consider one of the following approaches.

Správa verzí pomocí identifikátoru URIURI versioning

Pokaždé, když upravíte webové rozhraní API nebo změníte schéma prostředků, přidejte číslo verze do identifikátoru URI každého prostředku.Each time you modify the web API or change the schema of resources, you add a version number to the URI for each resource. Dříve existující identifikátory URI by měly nadále fungovat jako předtím a vracet prostředky, které odpovídají jejich původnímu schématu.The previously existing URIs should continue to operate as before, returning resources that conform to their original schema.

Rozšíření na předchozí příklad, pokud address pole je změnili do každé základní část adresy obsahující dílčí pole (například streetAddress, city, state, a zipCode), může být tato verze prostředku k dispozici prostřednictvím identifikátoru URI obsahující číslo verze, jako například http://adventure-works.com/v2/customers/3:Extending the previous example, if the address field is restructured into sub-fields 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 http://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}}

Tento mechanismus správy verzí je velmi jednoduchý, ale závisí na směrování požadavků serverem na příslušný koncový bod.This versioning mechanism is very simple but depends on the server routing the request to the appropriate endpoint. Během času, jak se webové rozhraní API vyvíjí prostřednictvím několika iterací a server musí podporovat několik různých verzí, se ale může stát těžkopádným.However, it can become unwieldy as the web API matures through several iterations and the server has to support a number of different versions. Navíc z puristického pohledu ve všech případech klientské aplikace načítají stejná data (zákazník 3), takže identifikátor URI by se ve skutečnosti neměl lišit v závislosti na verzi.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. Toto schéma také komplikuje implementaci HATEOAS, protože všechny odkazy musí v identifikátorech URI obsahovat číslo verze.This scheme also complicates implementation of HATEOAS as all links will need to include the version number in their URIs.

Správa verzí pomocí řetězce dotazuQuery string versioning

Místo poskytuje více identifikátory URI, můžete zadat verzi prostředku pomocí parametr řetězce dotazu, připojí k požadavku HTTP, jako například http://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 http://adventure-works.com/customers/3?version=2. Parametr verze by měl mít smysluplnou výchozí hodnotu, například 1, pokud ho starší klientské aplikace neuvádějí.The version parameter should default to a meaningful value such as 1 if it is omitted by older client applications.

Tento přístup má sémantickou výhodu, že stejný prostředek se vždycky načítá pomocí stejného identifikátoru URI, ale závisí na kódu, který zpracovává požadavek, aby parsoval řetězec dotazu a odeslal zpátky odpovídající odpověď HTTP.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. Tento přístup také vykazuje stejné komplikace při implementaci HATEOAS jako mechanismus správy verzí pomocí identifikátoru URI.This approach also suffers from the same complications for implementing HATEOAS as the URI versioning mechanism.

Poznámka

Některé starší webové prohlížeče a webové proxy servery nebudou ukládat do mezipaměti odpovědi pro požadavky, které obsahují řetězec dotazu v identifikátoru URI.Some older web browsers and web proxies will not cache responses for requests that include a query string in the URI. To může mít negativní dopad na výkon webových aplikací, které využívají webové rozhraní API a které běží v rámci takového webového prohlížeče.This can have an adverse impact on performance for web applications that use a web API and that run from within such a web browser.

Správa verzí pomocí hlavičkyHeader versioning

Místo přidávání čísla verze jako parametru řetězce dotazu může implementovat vlastní hlavičku, která určuje verzi prostředku.Rather than appending the version number as a query string parameter, you could implement a custom header that indicates the version of the resource. Tento přístup vyžaduje, aby klientská aplikace přidala odpovídající hlavičku do všech požadavků, i když kód, který zpracovává požadavek klienta, může použít výchozí hodnotu (verze 1), když je hlavička verze vynechaná.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. Následující příklady využívají vlastní hlavičku s názvem Custom-Header.The following examples utilize a custom header named Custom-Header. Hodnotu této hlavičky určuje verzi webového rozhraní API.The value of this header indicates the version of web API.

Verze 1:Version 1:

GET http://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"}

Verze 2:Version 2:

GET http://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}}

Všimněte si, že stejně jako u předchozích dvou přístupů vyžaduje implementace HATEOAS vložení odpovídající vlastní hlavičky do všech odkazů.Note that as with the previous two approaches, implementing HATEOAS requires including the appropriate custom header in any links.

Správa verzí pomocí typu médiaMedia type versioning

Když klientská aplikace odesílá požadavek HTTP GET na webový server, měla by specifikovat formát obsahu, který dokáže zpracovat, pomocí hlavičky Accept, jak je popsáno výše v tomto návodu.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. Často účel hlavičky Accept je umožnit klientské aplikaci určit, zda má být tělo odpovědi XML, JSON nebo některý jiný běžný formát, který umí klient parsovat.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. Nicméně je možné definovat vlastní typy médií, které obsahují informace umožňující klientské aplikaci označit, která verze prostředku se očekává.However, 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. Následující příklad ukazuje požadavek, který určuje hlavičku Accept s hodnotou 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. Element vnd.adventure-works.v1 webovému serveru říká, že má být vrácena verze 1 prostředku, zatímco element json určuje, že formát těla odpovědi má být 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 http://adventure-works.com/customers/3 HTTP/1.1
Accept: application/vnd.adventure-works.v1+json

Kód, který zpracovává požadavek, je zodpovědný za zpracování hlavičky Accept a její co možná největší dodržení (klientská aplikace může v hlavičce Accept určit víc formátů, v takovém případě může webový server zvolit pro tělo odpovědi nejvhodnější formát).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). Webový server potvrdí formát dat v těle odpovědi pomocí hlavičku 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"}

Pokud hlavička Accept neurčuje žádné známé typy médií, webový server by měl generovat zprávu odpovědi HTTP 406 (Nepřijatelné) nebo vrátit zprávu s výchozím typem média.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.

Tento přístup je pravděpodobně nejčistší z mechanismů správy verzí a přirozeně se propůjčuje HATEOAS, kdy odkazy na prostředky můžou zahrnovat typ MIME souvisejících dat.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.

Poznámka

Když vybíráte strategii správy verzí, měli byste také zvážit dopad na výkon, hlavně na ukládání do mezipaměti na webovém serveru.When you select a versioning strategy, you should also consider the implications on performance, especially caching on the web server. Schémata správy verzí pomocí identifikátoru URI a správy verzí pomocí řetězec dotazu jsou k mezipaměti ohleduplná, protože stejná kombinace identifikátoru URI nebo řetězce dotazu vždycky odkazuje na stejná data.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.

Mechanismy správy verzí pomocí hlavičky a pomocí typu média obvykle vyžadují další logiku ke kontrole hodnot ve vlastní hlavičce nebo hlavičce 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. V rozsáhlých prostředích může to, že mnoho klientů používá různé verze webového rozhraní API, způsobit významné množství duplicitních dat v mezipaměti na straně serveru.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. Tento problém se může akutním, pokud klientská aplikace komunikuje s webovým serverem prostřednictvím proxy serveru, který implementuje ukládání do mezipaměti a který pouze předává požadavky na webový server, pokud aktuálně nemá kopii požadovaných dat v mezipaměti.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.

Open API InitiativeOpen API Initiative

Iniciativa Open API Initiative byla vytvořena odvětvovým konsorciem, aby došlo ke standardizaci popisů rozhraní REST API mezi dodavateli.The Open API Initiative was created by an industry consortium to standardize REST API descriptions across vendors. V rámci této iniciativy se specifikace Swagger 2.0 přejmenovala na specifikaci OpenAPI (OAS) a začlenila se do Open API Initiative.As part of this initiative, the Swagger 2.0 specification was renamed the OpenAPI Specification (OAS) and brought under the Open API Initiative.

Můžete pro svá webová rozhraní API přijmout OpenAPI.You may want to adopt OpenAPI for your web APIs. Některé body ke zvážení:Some points to consider:

  • Specifikace OpenAPI obsahuje sadu závazných pokynů, jak by se měla navrhovat rozhraní REST API.The OpenAPI Specification comes with a set of opinionated guidelines on how a REST API should be designed. Přináší výhody z hlediska spolupráce, ale vyžaduje větší péči při navrhování rozhraní API tak, aby odpovídalo specifikaci.That has advantages for interoperability, but requires more care when designing your API to conform to the specification.
  • OpenAPI podporuje přístup, který začíná kontraktem, nikoli implementací.OpenAPI promotes a contract-first approach, rather than an implementation-first approach. Začít kontraktem znamená, že nejprve navrhnete kontrakt rozhraní API, a teprve pak píšete kód, který kontrakt implementuje.Contract-first means you design the API contract (the interface) first and then write code that implements the contract.
  • Nástroje jako Swagger dokážou z kontraktů rozhraní API vygenerovat klientské knihovny nebo dokumentaci.Tools like Swagger can generate client libraries or documentation from API contracts. Přečtěte si například téma s popisem generování stránek nápovědy webového rozhraní ASP.NET API pomocí Swaggeru.For example, see ASP.NET Web API Help Pages using Swagger.

Další informaceMore information