API tasarımıAPI design

Birçok modern web uygulaması, istemcilerin uygulama ile etkileşimde bulunmak için kullanabileceği API'leri kullanıma sunar.Most modern web applications expose APIs that clients can use to interact with the application. İyi tasarlanmış bir web API’si şunları hedeflemeyi destekler:A well-designed web API should aim to support:

  • Platform bağımsızlığı.Platform independence. API’nin içeride nasıl uygulandığına bakılmaksızın API’yi herhangi bir istemci çağırabilmelidir.Any client should be able to call the API, regardless of how the API is implemented internally. Bunun için standart protokollerin kullanılması ve istemci ile web hizmetinin değişimi yapılacak veriler üzerinde anlaşabileceği bir mekanizmaya sahip olunması gerekir.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.

  • Hizmet gelişimi.Service evolution. Web API’si gelişebilmeli ve istemci uygulamalardan bağımsız olarak işlevsellik ekleyebilmelidir.The web API should be able to evolve and add functionality independently from client applications. API geliştikçe mevcut istemci uygulamalar değişiklik olmadan çalışmaya devam etmelidir.As the API evolves, existing client applications should continue to function without modification. İstemci uygulamalarını tam olarak bunu kullanabilmesi için tüm işlevselliği bulunabilir olması gerekir.All functionality should be discoverable so that client applications can fully use it.

Bu rehber bir web API’si tasarlarken dikkate almanız gereken sorunları açıklamaktadır.This guidance describes issues that you should consider when designing a web API.

REST'e girişIntroduction to REST

2000 yılında Roy Fielding, web hizmetleri tasarlamaya yönelik mimari bir yaklaşım olarak Temsili Durum Transferi’ni (REST) önerdi.In 2000, Roy Fielding proposed Representational State Transfer (REST) as an architectural approach to designing web services. REST, hiper medyayı temel alan dağıtılmış sistemler oluşturmaya yönelik bir mimari stilidir.REST is an architectural style for building distributed systems based on hypermedia. REST, temel alınan herhangi bir protokolden bağımsızdır ve mutlaka HTTP’ye bağlı olması gerekmez.REST is independent of any underlying protocol and is not necessarily tied to HTTP. Bununla birlikte en yaygın REST uygulamaları, uygulama protokolü olarak HTTP kullanır ve bu rehber, HTTP için REST API'leri tasarlamaya odaklanmıştır.However, most common REST implementations use HTTP as the application protocol, and this guide focuses on designing REST APIs for HTTP.

HTTP üzerinden REST birincil avantajı açık standartlar kullanması ve API uygulaması ya da istemci uygulamalar için herhangi bir uygulamaya bağlamamasıdır, ' dir.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. Örneğin, bir REST web hizmeti ASP.NET ile yazılabilir ve istemci uygulamalar, HTTP istekleri oluşturabilen ve HTTP yanıtlarını ayrıştırabilen herhangi bir dil ya da araç takımı kullanabilir.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.

HTTP kullanan RESTful API’lerinin temel tasarım ilkelerinden bazıları şunlardır:Here are some of the main design principles of RESTful APIs using HTTP:

  • REST API'leri, istemci tarafından erişilebilen herhangi bir nesne, veri ya da hizmet olabilecek kaynaklar çevresinde tasarlanır.REST APIs are designed around resources, which are any kind of object, data, or service that can be accessed by the client.

  • Bir kaynak, kendisini benzersiz bir şekilde tanımlayan URI biçiminde bir tanımlayıcıya sahiptir.A resource has an identifier, which is a URI that uniquely identifies that resource. Örneğin, belirli bir müşterinin siparişine ait URI şu şekilde olabilir:For example, the URI for a particular customer order might be:

    https://adventure-works.com/orders/1
    
  • İstemciler, kaynakların gösterimlerini takas ederek bir hizmetle etkileşimde bulunur.Clients interact with a service by exchanging representations of resources. Birçok web API’si takas biçimi olarak JSON kullanır.Many web APIs use JSON as the exchange format. Örneğin, yukarıda listelenen URI’ya gönderilen bir GET isteği şu yanıt gövdesini döndürebilir:For example, a GET request to the URI listed above might return this response body:

    {"orderId":1,"orderValue":99.90,"productId":1,"quantity":1}
    
  • REST API’leri, istemci ve hizmet uygulamalarını birbirinden ayırmaya yardımcı olan tek tip arabirim kullanır.REST APIs use a uniform interface, which helps to decouple the client and service implementations. HTTP üzerinde derlenmiş REST API'leri için tek tip arabirim, kaynaklar üzerinde işlem gerçekleştirmek için standart HTTP fiillerini kullanarak içerir.For REST APIs built on HTTP, the uniform interface includes using standard HTTP verbs to perform operations on resources. En yaygın işlemler GET, POST, PUT, PATCH ve DELETE işlemleridir.The most common operations are GET, POST, PUT, PATCH, and DELETE.

  • REST API’leri durum bilgisiz istek modeli kullanır.REST APIs use a stateless request model. HTTP istekleri bağımsız olmalıdır ve herhangi bir sırayla gerçekleşebilir; bu nedenle, istekler arasında geçici durum bilgilerinin tutulması uygun değildir.HTTP requests should be independent and may occur in any order, so keeping transient state information between requests is not feasible. Bilgiler yalnızca kaynaklarda depolanır ve her istek atomik bir işlem olmalıdır.The only place where information is stored is in the resources themselves, and each request should be an atomic operation. İstemciler ile belirli sunucular arasında herhangi bir benzeşim sürdürmek gerekmediğinden bu kısıtlama, web hizmetlerinin yüksek oranda ölçeklenebilir olmasını sağlar.This constraint enables web services to be highly scalable, because there is no need to retain any affinity between clients and specific servers. Herhangi bir sunucu, herhangi bir istemciden gelen herhangi bir isteği işleyebilir.Any server can handle any request from any client. Bununla birlikte, ölçeklenebilirlik diğer faktörlerle sınırlanabilir.That said, other factors can limit scalability. Örneğin, birçok web hizmeti ölçek genişletme işleminin zor olduğu bir arka uç veri deposuna yazar. (Veri Bölümleme makalesinde bir veri deposunun ölçeğini artırmaya yönelik stratejiler açıklanmıştır.)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.)

  • REST API'leri, gösterimde yer alan hiper medya bağlantıları ile yönlendirilir.REST APIs are driven by hypermedia links that are contained in the representation. Örneğin, aşağıda bir siparişin JSON gösterimi gösterilmektedir.For example, the following shows a JSON representation of an order. Siparişle ilişkili müşteriyi alma veya güncelleştirme bağlantılarını içerir.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" }
        ]
    }
    

2008 yılında Leonard Richardson, web API’leri için aşağıdaki olgunluk modelini önerdi:In 2008, Leonard Richardson proposed the following maturity model for web APIs:

  • Düzey 0: Bir URI tanımlar ve tüm işlemler bu URI'ye yönelik POST istekleri gerçekleştirilir.Level 0: Define one URI, and all operations are POST requests to this URI.
  • Düzey 1: Bağımsız kaynaklar için ayrı URI'ler oluşturma.Level 1: Create separate URIs for individual resources.
  • 2. düzey: Kaynaklar üzerinde işlemleri tanımlamak için HTTP yöntemleri kullanın.Level 2: Use HTTP methods to define operations on resources.
  • 3. düzey: Dağıtılır (aşağıda açıklanan HATEOAS) kullanın.Level 3: Use hypermedia (HATEOAS, described below).

Düzey 3, Fielding'in tanımına göre gerçek bir RESTful API'sine karşılık gelir.Level 3 corresponds to a truly RESTful API according to Fielding's definition. Uygulamada, yayımlanan birçok web API'leri yaklaşık olarak Düzey 2 yerde ayrılır.In practice, many published web APIs fall somewhere around level 2.

API’yi kaynaklar çevresinde düzenlemeOrganize the API around resources

Web API’sinin kullanıma sunduğu iş varlıklarına odaklanın.Focus on the business entities that the web API exposes. Örneğin, bir e-ticaret sisteminde birincil varlıklar müşteriler ve siparişler olabilir.For example, in an e-commerce system, the primary entities might be customers and orders. Sipariş bilgilerini içeren bir HTTP POST isteği gönderilerek sipariş oluşturulabilir.Creating an order can be achieved by sending an HTTP POST request that contains the order information. HTTP yanıtı, siparişin başarılı bir şekilde oluşturulup oluşturulmadığını gösterir.The HTTP response indicates whether the order was placed successfully or not. Mümkün olduğunda, kaynak URI'leri fiiller (kaynak üzerindeki işlemler) yerine isimleri (kaynak) temel almalıdır.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

Kaynak tek bir fiziksel veri öğesini temel almak zorunda değildir.A resource does not have to be based on a single physical data item. Örneğin, bir sipariş kaynağı, ilişkisel bir veritabanı içinde birkaç tablo halinde uygulanabilir ancak istemciye tek varlık olarak sunulur.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. Yalnızca bir veritabanının iç yapısını yansıtan API’ler oluşturmaktan kaçının.Avoid creating APIs that simply mirror the internal structure of a database. REST’in amacı, varlıkları ve bir uygulamanın bu varlıklar üzerinde gerçekleştirebileceği işlemleri modellemektir.The purpose of REST is to model entities and the operations that an application can perform on those entities. İstemci bir iç uygulamanın kullanımına sunulmamalıdır.A client should not be exposed to the internal implementation.

Varlıklar genellikle koleksiyonlar (siparişler, müşteriler) halinde gruplandırılır.Entities are often grouped together into collections (orders, customers). Koleksiyon, koleksiyon içindeki öğeden ayrı bir kaynaktır ve kendi URI’sine sahip olmalıdır.A collection is a separate resource from the item within the collection, and should have its own URI. Örneğin, aşağıdaki URI, sipariş koleksiyonunu temsil edebilir:For example, the following URI might represent the collection of orders:

https://adventure-works.com/orders

Koleksiyon URI’sine bir HTTP GET isteği gönderildiğinde koleksiyondaki öğelerin listesi alınır.Sending an HTTP GET request to the collection URI retrieves a list of items in the collection. Koleksiyondaki her bir öğe kendi benzersiz URI'sine de sahiptir.Each item in the collection also has its own unique URI. Öğenin URI'sine gönderilen bir HTTP GET isteği bu öğenin ayrıntılarını döndürür.An HTTP GET request to the item's URI returns the details of that item.

URI'de tutarlı bir adlandırma kuralı benimseyin.Adopt a consistent naming convention in URIs. Genel olarak, koleksiyonlara başvuran URI’ler için çoğul isimler kullanmak faydalı olur.In general, it helps to use plural nouns for URIs that reference collections. Koleksiyon ve öğeler için URI'leri bir hiyerarşiye göre düzenlemek iyi bir uygulamadır.It's a good practice to organize URIs for collections and items into a hierarchy. Örneğin, /customers müşteri koleksiyonunun yolu, /customers/5 ise müşterinin yoludur ve kimlik 5'e eşittir.For example, /customers is the path to the customers collection, and /customers/5 is the path to the customer with ID equal to 5. Bu yaklaşım, web API’sinin sezgiselliğini korumaya yardımcı olur.This approach helps to keep the web API intuitive. Ayrıca, birçok web API çerçevesi, /customers/{id} yolu için bir rota tanımlayabilmeniz amacıyla istekleri parametreli URI yollarına yönlendirebilir.Also, many web API frameworks can route requests based on parameterized URI paths, so you could define a route for the path /customers/{id}.

Farklı kaynak türleri arasındaki ilişkileri ve bu ilişkileri nasıl kullanıma sunabileceğinize göz önünde bulundurun.Also consider the relationships between different types of resources and how you might expose these associations. Örneğin /customers/5/orders, müşteri 5 için tüm siparişleri temsil edebilir.For example, the /customers/5/orders might represent all of the orders for customer 5. Ayrıca diğer yönde gidebilir ve bir siparişin /orders/99/customer gibi bir URI’si olan müşteri ile ilişkisini açıklayabilirsiniz.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. Ancak, bu modelin çok fazla genişletilmesi zahmetli bir uygulama olabilir.However, extending this model too far can become cumbersome to implement. HTTP yanıt iletisinin gövdesindeki ilişkili kaynakların gezinilebilir bağlantılarını sağlamak daha iyi bir çözümdür.A better solution is to provide navigable links to associated resources in the body of the HTTP response message. Bu mekanizma, bölümünde daha ayrıntılı olarak açıklanan kullanın ilgili kaynaklarda gezinmeyi etkinleştirme HATEOAS.This mechanism is described in more detail in the section Use HATEOAS to enable navigation to related resources.

Daha karmaşık sistemlerde bir istemcinin /customers/1/orders/99/products gibi birkaç ilişki düzeyinde gezinmesini sağlayan URI’ler sağlamak cazip olabilir.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. Ancak, bu karmaşıklık düzeyinin sürdürülmesi zor olabilir ve gelecekte kaynaklar arasındaki ilişkiler değişirse esnekliği olmaz.However, this level of complexity can be difficult to maintain and is inflexible if the relationships between resources change in the future. Bunun yerine, URI’leri oldukça basit tutmaya çalışın.Instead, try to keep URIs relatively simple. Bir uygulama bir kaynağa başvurduğunda bu başvuruyu o kaynakla ilgili öğeleri bulmak için kullanmak mümkündür.Once an application has a reference to a resource, it should be possible to use this reference to find items related to that resource. Yukarıdaki sorgu, müşteri 1’in tüm siparişlerini bulmak için /customers/1/orders URI’si ile, sonra da siparişteki ürünleri bulmak için /orders/99/products ile değiştirilebilir.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.

İpucu

koleksiyon/öğe/koleksiyon biçiminden daha karmaşık kaynak URI’leri gerektirmemeye özen gösterin.Avoid requiring resource URIs more complex than collection/item/collection.

Tüm web isteklerinin web sunucusu üzerinde bir yük oluşturması ise başka bir faktördür.Another factor is that all web requests impose a load on the web server. İstek sayısı arttıkça yük büyür.The more requests, the bigger the load. Bu nedenle, çok sayıda küçük kaynağı kullanıma sunan "geveze" web API’lerinden kaçınmaya çalışın.Therefore, try to avoid "chatty" web APIs that expose a large number of small resources. Bu tür bir API, gereken tüm verileri bulmak için istemcinin birden fazla istek göndermesini gerektirebilir.Such an API may require a client application to send multiple requests to find all of the data that it requires. Bunun yerine, verileri normalleştirilmişlikten çıkarmak ve ilgili bilgileri tek bir istekle alınabilen daha büyük kaynaklar halinde birleştirmek isteyebilirsiniz.Instead, you might want to denormalize the data and combine related information into bigger resources that can be retrieved with a single request. Ancak, bu yaklaşımı istemcinin ihtiyaç duymadığı verileri getirme yükü ile dengelemeniz gerekir.However, you need to balance this approach against the overhead of fetching data that the client doesn't need. Büyük nesnelerin alınması bir isteğin gecikme süresini artırabilir ve ek bant genişliği maliyetleri doğurabilir.Retrieving large objects can increase the latency of a request and incur additional bandwidth costs. Bu performans anti-desenleri hakkında daha fazla bilgi için bkz. Chatty G/Ç ve Fazlalık Getirme.For more information about these performance antipatterns, see Chatty I/O and Extraneous Fetching.

Web API’si ile temel alınan veri kaynakları arasında bağımlılıklar oluşturmaktan kaçının.Avoid introducing dependencies between the web API and the underlying data sources. Örneğin, verileriniz ilişkisel bir veritabanında depolanıyorsa, web API’sinin her bir tabloyu bir kaynak koleksiyonu olarak kullanıma sunması gerekmez.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. Aslında bu, büyük olasılıkla kötü bir tasarım olacaktır.In fact, that's probably a poor design. Bunun yerine, web API’sini veritabanının bir özeti olarak düşünün.Instead, think of the web API as an abstraction of the database. Gerekirse, veritabanı ile web API’si arasında bir eşleme katmanı oluşturun.If necessary, introduce a mapping layer between the database and the web API. Bu şekilde, istemci uygulamalar değişikliklerden temel alınan veritabanı düzenine doğru yalıtılır.That way, client applications are isolated from changes to the underlying database scheme.

Son olarak, bir web API’si tarafından uygulanan her işlemin belirli bir kaynakla eşlenmesi mümkün olmayabilir.Finally, it might not be possible to map every operation implemented by a web API to a specific resource. Bu tür kaynak dışı senaryoları bir işlev çağıran ve sonuçları bir HTTP yanıt iletisi olarak döndüren HTTP istekleri aracılığıyla işleyebilirsiniz.You can handle such non-resource scenarios through HTTP requests that invoke a function and return the results as an HTTP response message. Örneğin, toplama ve çıkarma gibi basit hesap makinesi işlemleri uygulayan bir web API’si, bu işlemleri sahte kaynak olarak kullanıma sunan ve gerekli parametreleri belirtmek üzere sorgu dizesini kullanan URI’ler sağlayabilir.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. Örneğin /add?operand1=99&operand2=1 URI’sine gönderilen bir GET isteği, gövdesi 100 değerini içeren bir yanıt iletisi döndürür.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. Ancak, bu tür URI'leri tedbirli şekilde kullanın.However, only use these forms of URIs sparingly.

HTTP yöntemleri olarak işlem tanımlamaDefine operations in terms of HTTP methods

HTTP protokolü bir isteğe anlam atayan birkaç yöntemi tanımlar.The HTTP protocol defines a number of methods that assign semantic meaning to a request. Çoğu RESTful web API’si tarafından kullanılan yaygın HTTP yöntemleri şunlardır:The common HTTP methods used by most RESTful web APIs are:

  • GET, belirtilen URI’de kaynağın bir gösterimini alır.GET retrieves a representation of the resource at the specified URI. Yanıt iletisinin gövdesinde, istenen kaynağın ayrıntıları bulunur.The body of the response message contains the details of the requested resource.
  • POST, belirtilen URI’de yeni bir kaynak oluşturur.POST creates a new resource at the specified URI. İstek iletisinin gövdesi, yeni kaynağın ayrıntılarını sağlar.The body of the request message provides the details of the new resource. POST işleminin gerçekte kaynak oluşturmayan işlemleri tetiklemek için de kullanılabileceğini unutmayın.Note that POST can also be used to trigger operations that don't actually create resources.
  • PUT, belirtilen URI’de kaynağı oluşturur veya yenisiyle değiştirir.PUT either creates or replaces the resource at the specified URI. İstek iletisinin gövdesi, oluşturulacak veya güncelleştirilecek kaynağı belirtir.The body of the request message specifies the resource to be created or updated.
  • PATCH, kaynağın kısmi bir güncelleştirmesini yapar.PATCH performs a partial update of a resource. İstek gövdesi, kaynağa uygulanacak değişiklik kümesini belirtir.The request body specifies the set of changes to apply to the resource.
  • DELETE, belirtilen URI’deki kaynağı kaldırır.DELETE removes the resource at the specified URI.

Belirli bir isteğin etkisi, kaynağın bir koleksiyon ya da tek öğe olmasına bağlı olmalıdır.The effect of a specific request should depend on whether the resource is a collection or an individual item. Aşağıdaki tabloda, e-ticaret örneği kullanılarak birçok RESTful uygulaması tarafından benimsenen genel kurallar özetlenmiştir.The following table summarizes the common conventions adopted by most RESTful implementations using the ecommerce example. Bu isteklerin tümünün uygulanamayabileceğini unutmayın; uygulanabilirlik, senaryoya bağlıdır.Note that not all of these requests might be implemented; it depends on the specific scenario.

KaynakResource POSTPOST GETGET PUTPUT DELETEDELETE
/customers/customers Yeni müşteri oluşturmaCreate a new customer Tüm müşterileri almaRetrieve all customers Müşterileri toplu güncelleştirmeBulk update of customers Tüm müşterileri kaldırmaRemove all customers
/customers/1/customers/1 HataError Müşteri 1’in ayrıntılarını almaRetrieve the details for customer 1 Varsa müşteri 1’in ayrıntılarını güncelleştirmeUpdate the details of customer 1 if it exists Müşteri 1’i kaldırmaRemove customer 1
/customers/1/orders/customers/1/orders Müşteri 1 için yeni bir sipariş oluşturmaCreate a new order for customer 1 Müşteri 1 için tüm siparişleri almaRetrieve all orders for customer 1 Müşteri 1 için siparişleri toplu güncelleştirmeBulk update of orders for customer 1 Müşteri 1 için tüm siparişleri kaldırmaRemove all orders for customer 1

POST, PUT ve PATCH işlemleri arasındaki farklılıklar kafa karıştırıcı olabilir.The differences between POST, PUT, and PATCH can be confusing.

  • POST isteği bir kaynak oluşturur.A POST request creates a resource. Sunucu yeni kaynak için bir URI atar ve bu URI’yi istemciye döndürür.The server assigns a URI for the new resource, and returns that URI to the client. REST modelinde sıklıkla koleksiyonlara POST istekleri uygularsınız.In the REST model, you frequently apply POST requests to collections. Yeni kaynak, koleksiyona eklenir.The new resource is added to the collection. Yeni bir kaynak oluşturmadan verileri işlenmek üzere var olan bir kaynağa göndermek için de POST isteği kullanılabilir.A POST request can also be used to submit data for processing to an existing resource, without any new resource being created.

  • PUT isteği bir kaynak oluşturur veya var olan bir kaynağı güncelleştirir.A PUT request creates a resource or updates an existing resource. İstemci, kaynağın URI’sini belirtir.The client specifies the URI for the resource. İstek gövdesi, kaynağın tam gösterimini içerir.The request body contains a complete representation of the resource. Bu URI’ye sahip bir kaynak zaten varsa, değiştirilir.If a resource with this URI already exists, it is replaced. Aksi takdirde, sunucu tarafından destekleniyorsa yeni bir kaynak oluşturulur.Otherwise a new resource is created, if the server supports doing so. PUT istekleri, koleksiyonlar yerine en sık olarak belirli bir müşteri gibi tek öğeler halindeki kaynaklara uygulanır.PUT requests are most frequently applied to resources that are individual items, such as a specific customer, rather than collections. Bir sunucu, PUT işlemiyle güncelleştirmeleri destekleyebilir ancak oluşturmayı desteklemez.A server might support updates but not creation via PUT. PUT işlemiyle oluşturmanın desteklenip desteklenmediği, istemcinin bir kaynağa var olmadan önce anlamlı bir şekilde URI atayıp atayamayacağına bağlıdır.Whether to support creation via PUT depends on whether the client can meaningfully assign a URI to a resource before it exists. Bu durum geçerli değilse, kaynakları oluşturmak için POST, güncelleştirmek için PUT veya PATCH işlemini kullanın.If not, then use POST to create resources and PUT or PATCH to update.

  • Bir PATCH isteği, var olan bir kaynak üzerinde kısmi güncelleştirme uygular.A PATCH request performs a partial update to an existing resource. İstemci, kaynağın URI’sini belirtir.The client specifies the URI for the resource. İstek gövdesi, kaynağa uygulanacak bir değişiklik kümesini belirtir.The request body specifies a set of changes to apply to the resource. İstemci, kaynağın tüm gösterimini değil yalnızca değişiklikleri gönderdiği için, bu işlem PUT kullanmaktan daha verimli olabilir.This can be more efficient than using PUT, because the client only sends the changes, not the entire representation of the resource. Teknik olarak, sunucu tarafından destekleniyorsa PATCH ayrıca yeni bir kaynak oluşturabilir ("null" bir kaynağa bir güncelleştirme kümesi belirterek).Technically PATCH can also create a new resource (by specifying a set of updates to a "null" resource), if the server supports this.

PUT istekleri bir kez etkili olmalıdır.PUT requests must be idempotent. Bir istemci aynı PUT isteğini birden çok kez gönderirse, sonuçlar her zaman aynı olur (aynı kaynak, aynı değerlerle değiştirilir).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). POST ve PATCH isteklerinin bir kez etkili olması garanti edilmez.POST and PATCH requests are not guaranteed to be idempotent.

HTTP semantiğine uygunlukConform to HTTP semantics

Bu bölümde, HTTP belirtimine uygun bir API tasarlamaya yönelik bazı genel konular açıklanmaktadır.This section describes some typical considerations for designing an API that conforms to the HTTP specification. Ancak, her olası ayrıntı veya senaryo ele alınmamıştır.However, it doesn't cover every possible detail or scenario. Şüpheye düştüğünüzde HTTP belirtimlerine başvurun.When in doubt, consult the HTTP specifications.

Medya türleriMedia types

Daha önce belirtildiği gibi istemciler ve sunucular, kaynakların gösterimlerini takas eder.As mentioned earlier, clients and servers exchange representations of resources. Örneğin, bir POST isteğinde istek gövdesi, oluşturulacak kaynağın bir gösterimini içerir.For example, in a POST request, the request body contains a representation of the resource to create. Bir GET isteğinde ise yanıt gövdesi, getirilen kaynağın gösterimini içerir.In a GET request, the response body contains a representation of the fetched resource.

HTTP protokolünde biçimler, aynı zamanda MIME türleri olarak bilinen medya türleri kullanılarak belirtilir.In the HTTP protocol, formats are specified through the use of media types, also called MIME types. İkili olmayan veriler için çoğu web API’si, JSON (medya türü = uygulama/json) ve muhtemelen XML (medya türü = uygulama/xml) desteği içerir.For non-binary data, most web APIs support JSON (media type = application/json) and possibly XML (media type = application/xml).

Bir istek veya yanıttaki Content-Type üst bilgisi, gösterimin biçimini belirtir.The Content-Type header in a request or response specifies the format of the representation. JSON verilerini içeren bir POST isteğinin örneği aşağıda verilmiştir: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}

Sunucu medya türünü desteklemiyorsa, 415 (Desteklenmeyen Medya Türü) HTTP durum kodunu döndürmelidir.If the server doesn't support the media type, it should return HTTP status code 415 (Unsupported Media Type).

Bir istemci isteği, istemcinin yanıt iletisinde sunucudan kabul edeceği medya türlerinin listesini içeren bir Accept üst bilgisi içerebilir.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. Örneğin:For example:

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

Sunucu, listedeki medya türlerinin hiçbiri ile eşleşmiyorsa 406 (Kabul Edilemez) HTTP durum kodunu döndürmelidir.If the server cannot match any of the media type(s) listed, it should return HTTP status code 406 (Not Acceptable).

GET yöntemleriGET methods

Başarılı bir GET yöntemi genellikle 200 (Tamam) HTTP durum kodunu döndürür.A successful GET method typically returns HTTP status code 200 (OK). Kaynak bulunamazsa yöntem, 404 (Bulunamadı) kodunu döndürmelidir.If the resource cannot be found, the method should return 404 (Not Found).

POST yöntemleriPOST methods

POST yöntemi yeni bir kaynak oluşturursa 201 (Oluşturuldu) HTTP durum kodunu döndürür.If a POST method creates a new resource, it returns HTTP status code 201 (Created). Yeni kaynağın URI'si, yanıtın Location üst bilgisine dahil edilir.The URI of the new resource is included in the Location header of the response. Yanıt gövdesi, kaynağın bir gösterimini içerir.The response body contains a representation of the resource.

Yöntem aynı işlemi yapmasına rağmen yeni bir kaynak oluşturmazsa, 200 HTTP durum kodunu döndürebilir ve yanıt gövdesinde işlemin sonucunu içerebilir.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. Alternatif olarak, döndürülecek sonuç yoksa yöntem herhangi bir yanıt gövdesi olmadan 204 (İçerik Yok) HTTP durum kodunu döndürebilir.Alternatively, if there is no result to return, the method can return HTTP status code 204 (No Content) with no response body.

İstemci isteğe geçersiz veriler yerleştirirse, sunucu 400 (Hatalı İstek) HTTP durum kodunu döndürmelidir.If the client puts invalid data into the request, the server should return HTTP status code 400 (Bad Request). Yanıt gövdesi, hata hakkında ek bilgiler veya daha fazla ayrıntı sağlayan bir URI bağlantısı içerebilir.The response body can contain additional information about the error or a link to a URI that provides more details.

PUT yöntemleriPUT methods

PUT yöntemi yeni bir kaynak oluşturursa POST yönteminde olduğu gibi 201 (Oluşturuldu) HTTP durum kodunu döndürür.If a PUT method creates a new resource, it returns HTTP status code 201 (Created), as with a POST method. Yöntem var olan bir kaynağı güncelleştirirse 200 (Tamam) ya da 204 (İçerik Yok) durum kodunu döndürür.If the method updates an existing resource, it returns either 200 (OK) or 204 (No Content). Bazı durumlarda, var olan bir kaynağı güncelleştirmek mümkün olmayabilir.In some cases, it might not be possible to update an existing resource. Bu durumda 409 (Çakışma) HTTP durum kodunu döndürmeyi düşünün.In that case, consider returning HTTP status code 409 (Conflict).

Bir koleksiyondaki birden fazla kaynağı toplu olarak güncelleştirebilen toplu HTTP PUT işlemleri uygulamayı düşünün.Consider implementing bulk HTTP PUT operations that can batch updates to multiple resources in a collection. PUT isteği, koleksiyonun URI’sini belirtmelidir ve istek gövdesi, değiştirilecek kaynakların ayrıntılarını belirtmelidir.The PUT request should specify the URI of the collection, and the request body should specify the details of the resources to be modified. Bu yaklaşım, sık iletişim kurma sorununu azaltmaya ve performansı artırmaya yardımcı olabilir.This approach can help to reduce chattiness and improve performance.

PATCH yöntemleriPATCH methods

İstemci PATCH isteğini kullanarak var olan bir kaynağa yama belgesi biçiminde bir güncelleştirme kümesi gönderir.With a PATCH request, the client sends a set of updates to an existing resource, in the form of a patch document. Sunucu, güncelleştirmeyi gerçekleştirmek için yama belgesini işler.The server processes the patch document to perform the update. Yama belgesi kaynağın tamamını değil, yalnızca uygulanacak değişiklikler kümesini açıklar.The patch document doesn't describe the whole resource, only a set of changes to apply. PATCH yönteminin belirtimi (RFC 5789), yama belgeleri için belirli bir biçim tanımlamaz.The specification for the PATCH method (RFC 5789) doesn't define a particular format for patch documents. Biçim, istekteki medya türünden anlaşılmalıdır.The format must be inferred from the media type in the request.

Web API’leri için en sık kullanılan veri biçimi büyük olasılıkla JSON biçimidir.JSON is probably the most common data format for web APIs. JSON yaması ve JSON birleştirme yaması adlı iki ana JSON temelli yama biçimi vardır.There are two main JSON-based patch formats, called JSON patch and JSON merge patch.

JSON birleştirme yaması biraz daha basittir.JSON merge patch is somewhat simpler. Yama belgesi, özgün JSON kaynağı ile aynı yapıda olmasına karşın yalnızca değiştirilmesi veya eklenmesi gereken alanların alt kümesini içerir.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. Ayrıca, yama belgesindeki alan değeri için null belirtilerek bir alan silinebilir.In addition, a field can be deleted by specifying null for the field value in the patch document. (Diğer bir deyişle, özgün kaynak açıkça null değerler alabiliyorsa birleştirme yaması uygun değildir.)(That means merge patch is not suitable if the original resource can have explicit null values.)

Örneğin, özgün kaynağın aşağıdaki JSON gösterimine sahip olduğunu varsayın:For example, suppose the original resource has the following JSON representation:

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

Bu kaynak için olası bir JSON birleştirme yaması şu şekildedir:Here is a possible JSON merge patch for this resource:

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

Bu sunucunun güncelleştirilecek bildirir price, silme colorve ekleme sizename ve category değil değiştirilir.This tells the server to update price, delete color, and add sizename and category are not modified. JSON birleştirme yamasının tam ayrıntıları için bkz. RFC 7396.For the exact details of JSON merge patch, see RFC 7396. JSON birleştirme yaması için medya türü application/merge-patch+json.The media type for JSON merge patch is application/merge-patch+json.

Özgün kaynak açıkça null değerler içerebiliyorsa, null değerinin yama belgesindeki özel anlamı nedeniyle birleştirme yaması uygun değildir.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. Ayrıca yama belgesi, sunucunun güncelleştirmeleri uygulaması gereken sırayı belirtmez.Also, the patch document doesn't specify the order that the server should apply the updates. Bu durum, verilere ve etki alanına bağlı olarak önemli veya önemsiz olabilir.That may or may not matter, depending on the data and the domain. RFC 6902 içinde tanımlanan JSON yaması daha esnektir.JSON patch, defined in RFC 6902, is more flexible. Değişiklikleri, uygulanacak işlemlerin sırası olarak belirtir.It specifies the changes as a sequence of operations to apply. Ekleme, kaldırma, değiştirme, kopyalama ve test etme (değerleri doğrulamak için) işlemleri mevcuttur.Operations include add, remove, replace, copy, and test (to validate values). JSON yaması için medya türü application/json-patch+json.The media type for JSON patch is application/json-patch+json.

Bir PATCH isteği işlenirken karşılaşılabilecek tipik hata koşullarından bazıları, uygun HTTP durum kodu ile birlikte aşağıda verilmiştir.Here are some typical error conditions that might be encountered when processing a PATCH request, along with the appropriate HTTP status code.

Hata koşuluError condition HTTP durum koduHTTP status code
Yama belgesinin biçimi desteklenmiyor.The patch document format isn't supported. 415 (Desteklenmeyen Medya Türü)415 (Unsupported Media Type)
Hatalı biçimlendirilmiş yama belgesi.Malformed patch document. 400 (Hatalı İstek)400 (Bad Request)
Yama belgesi geçerli, ancak değişiklikler mevcut durumunda kaynağa uygulanamıyor.The patch document is valid, but the changes can't be applied to the resource in its current state. 409 (Çakışma)409 (Conflict)

DELETE yöntemleriDELETE methods

Silme işlemi başarılı olursa web sunucusu, işlemin başarıyla gerçekleştirildiğini ancak yanıt gövdesinin başka bir bilgi içermediğini belirten 204 HTTP durum kodu ile yanıt vermelidir.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. Kaynak mevcut değilse, web sunucusu HTTP 404 (Bulunamadı) kodunu döndürebilir.If the resource doesn't exist, the web server can return HTTP 404 (Not Found).

Zaman uyumsuz işlemlerAsynchronous operations

Bazı durumlarda bir POST, PUT, PATCH veya DELETE işlemi, tamamlanması zaman alan işleme gerektirebilir.Sometimes a POST, PUT, PATCH, or DELETE operation might require processing that takes awhile to complete. Bir yanıtı istemciye göndermeden önce tamamlanmasını beklerseniz kabul edilemez bir gecikmeye neden olabilir.If you wait for completion before sending a response to the client, it may cause unacceptable latency. Bu durumda, işlemi zaman uyumsuz hale getirmeyi düşünün.If so, consider making the operation asynchronous. İsteğin işleme alındığını ancak tamamlanmadığını belirtmek üzere 202 (Kabul Edildi) HTTP durum kodunu döndürün.Return HTTP status code 202 (Accepted) to indicate the request was accepted for processing but is not completed.

İstemcinin durum uç noktasını yoklayarak durumu izleyebilmesi için, zaman uyumsuz bir isteğin durumunu döndüren bir uç noktayı kullanıma sunmanız gerekir.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. Durum uç noktasının URI’sini 202 yanıtının Location üst bilgisine ekleyin.Include the URI of the status endpoint in the Location header of the 202 response. Örneğin:For example:

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

İstemci bu uç noktaya bir GET isteği gönderirse yanıt, isteğin geçerli durumunu içermelidir.If the client sends a GET request to this endpoint, the response should contain the current status of the request. İsteğe bağlı olarak, tahmini bir tamamlama süresi veya işlemi iptal etme bağlantısı da içerebilir.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" }
}

Zaman uyumsuz işlem yeni bir kaynak oluşturursa, işlem tamamlandıktan sonra durum uç noktası 303 (Diğerine Bakın) durum kodunu döndürmelidir.If the asynchronous operation creates a new resource, the status endpoint should return status code 303 (See Other) after the operation completes. 303 yanıtına, yeni kaynağın URI’sini veren bir Location üst bilgisi ekleyin: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

Daha fazla bilgi için bkz. REST’te zaman uyumsuz işlemler.For more information, see Asynchronous operations in REST.

Verileri filtreleme ve sayfalandırmaFilter and paginate data

Bir kaynak koleksiyonunu tek bir URI aracılığıyla kullanıma sunmak, uygulamaların yalnızca bir bilgi alt kümesi gerekliyken büyük miktarlarda veri getirmesine neden olabilir.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. Örneğin, bir istemci uygulamanın, maliyeti belirli bir değerin üzerinde olan tüm siparişleri bulması gerektiğini varsayalım.For example, suppose a client application needs to find all orders with a cost over a specific value. Tüm siparişleri /orders URI’sinden alıp sonra bu siparişleri istemci tarafında fitreleyebilir.It might retrieve all orders from the /orders URI and then filter these orders on the client side. Açıkçası bu işlem son derece verimsizdir.Clearly this process is highly inefficient. Web API’sini barındıran sunucuda gereksiz ağ bant genişliği ve işlem gücü harcar.It wastes network bandwidth and processing power on the server hosting the web API.

Bunun yerine API, /orders?minCost=n gibi URI’nin sorgu dizesine bir filtre geçirmeye izin verebilir.Instead, the API can allow passing a filter in the query string of the URI, such as /orders?minCost=n. Web API'si, ardından ayrıştırıp işlemekten sorumludur minCost sorgu dizesi ve sunucu tarafında filtrelenmiş sonuçları döndüren parametresi.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.

Koleksiyon kaynakları üzerindeki GET istekleri, çok sayıda öğe döndürebilir.GET requests over collection resources can potentially return a large number of items. Tek bir istek tarafından döndürülen veri miktarını sınırlamak için bir web API’si tasarlamanız gerekir.You should design a web API to limit the amount of data returned by any single request. Alınacak en fazla öğe sayısını ve koleksiyon ile başlangıç uzaklığını belirten sorgu dizelerini desteklemeyi düşünün.Consider supporting query strings that specify the maximum number of items to retrieve and a starting offset into the collection. Örneğin:For example:

/orders?limit=25&offset=50

Ayrıca, Hizmet Reddi saldırılarını önlemeye yardımcı olmak amacıyla, döndürülen öğe sayısına bir üst sınır getirmeyi düşünün.Also consider imposing an upper limit on the number of items returned, to help prevent Denial of Service attacks. İstemci uygulamalara yardımcı olmak için, sayfalandırılmış veriler döndüren GET istekleri koleksiyondaki kullanılabilir kaynakların toplam sayısını belirten bir tür meta veri içermelidir.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.

Değer olarak /orders?sort=ProductID gibi bir alan adı alan sıralama parametresi sağlayarak, verileri getirildiği gibi sıralamak için benzer bir strateji kullanabilirsiniz.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. Ancak, sorgu dizesi parametreleri önbelleğe alınmış verilerin anahtarı olarak çok sayıda önbellek uygulaması tarafından kullanılan kaynak tanımlayıcısının bir kısmını oluşturduğundan, bu yaklaşım önbelleğe almayı olumsuz yönde etkileyebilir.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.

Her öğe büyük miktarda veri içeriyorsa, bu yaklaşımı her bir öğe için döndürülen alanları sınırlayacak şekilde genişletebilirsiniz.You can extend this approach to limit the fields returned for each item, if each item contains a large amount of data. Örneğin, /orders?fields=ProductID,Quantity gibi alanların virgülle ayrılmış listesini kabul eden bir sorgu dizesi parametresini kullanabilirsiniz.For example, you could use a query string parameter that accepts a comma-delimited list of fields, such as /orders?fields=ProductID,Quantity.

Sorgu dizelerindeki tüm isteğe bağlı parametrelere anlamlı varsayılanlar atayın.Give all optional parameters in query strings meaningful defaults. Örneğin, sayfalama uyguluyorsanız limit parametresini 10 ve offset parametresini 0 olarak ayarlayın, sıralama uyguluyorsanız sıralama parametresini kaynağın anahtarına ayarlayın ve projeksiyonları destekliyorsanız fields parametresini kaynağın tüm alanlarına ayarlayın.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.

Büyük ikili kaynaklar için kısmi yanıtları desteklemeSupport partial responses for large binary resources

Bir kaynak, dosya ya da görüntü gibi büyük ikili alanlar içerebilir.A resource may contain large binary fields, such as files or images. Güvenilmez ve aralıklı bağlantıların neden olduğu sorunları aşmak ve yanıt sürelerini iyileştirmek için, bu tür kaynakların öbek halinde alınmasını sağlayın.To overcome problems caused by unreliable and intermittent connections and to improve response times, consider enabling such resources to be retrieved in chunks. Bunu yapmak için, web API’si büyük kaynaklara yönelik GET istekleri için Accept-Ranges üst bilgisini desteklemelidir.To do this, the web API should support the Accept-Ranges header for GET requests for large resources. Bu üst bilgi, GET işleminin kısmi istekleri desteklediğini gösterir.This header indicates that the GET operation supports partial requests. İstemci uygulama, bayt aralığı cinsinden belirtilen bir kaynak alt kümesi döndüren GET istekleri gönderebilir.The client application can submit GET requests that return a subset of a resource, specified as a range of bytes.

Ayrıca, bu kaynaklar için HTTP HEAD isteklerini uygulamayı düşünün.Also, consider implementing HTTP HEAD requests for these resources. HEAD isteği, boş bir ileti gövdesi ile yalnızca kaynağı tanımlayan HTTP üst bilgileri döndürmesi dışında bir GET isteği ile benzerdir.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. İstemci uygulama, kısmi GET istekleri kullanarak bir kaynağın getirilip getirilmeyeceğini belirlemek üzere HEAD isteği gönderebilir.A client application can issue a HEAD request to determine whether to fetch a resource by using partial GET requests. Örneğin:For example:

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

Örnek bir yanıt iletisi aşağıda verilmiştir:Here is an example response message:

HTTP/1.1 200 OK

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

Content-Length üst bilgisi, kaynağın toplam boyutunu verirken Accept-Ranges üst bilgisi, ilgili GET işleminin kısmi sonuçları desteklediğini gösterir.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. İstemci uygulama bu bilgileri kullanarak görüntüyü daha küçük öbekler halinde alabilir.The client application can use this information to retrieve the image in smaller chunks. İlk istek, Range üst bilgisini kullanarak ilk 2500 baytı getirir: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

Yanıt iletisi, 206 HTTP durum kodunu döndürerek bunun kısmi bir yanıt olduğunu gösterir.The response message indicates that this is a partial response by returning HTTP status code 206. Content-Length üst bilgisi, ileti gövdesinde döndürülen gerçek bayt sayısını (kaynağın boyutunu değil) belirtirken Content-Range üst bilgisi, bunun kaynağın hangi kısmı olduğunu gösterir (4580 bayt içinden 0-2499 bayt):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

[...]

İstemci uygulamadan alınan sonraki bir istek, kaynağın geri kalanını alabilir.A subsequent request from the client application can retrieve the remainder of the resource.

REST’in ardında yatan başlıca motivasyonlardan biri, URI şemasının önceden bilinmesine gerek olmadan tüm kaynak kümesinde gezinmenin mümkün olması gerekliliğidir.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. Her HTTP GET isteği, yanıta eklenen köprü bağlantılarla istenen nesne ile doğrudan ilgili kaynakları bulmak için gereken bilgileri döndürmeli ve ayrıca bu kaynakların her birinde kullanılabilen işlemleri açıklayan bilgiler her isteğe sağlanmalıdır.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. Bu ilke, HATEOAS ya da Uygulama Durumu Altyapısı Olarak Köprü Metni olarak bilinir.This principle is known as HATEOAS, or Hypertext as the Engine of Application State. Sistem aslında sınırlı bir durum makinesidir ve her bir isteğe verilen yanıt, bir durumdan diğerine geçmek için gereken bilgileri içerir; başka bir bilgi gerekli olmamalıdır.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.

Not

Şu anda, HATEOAS ilkesinin nasıl modelleneceğini açıklayan bir standart ya da belirtim bulunmamaktadır.Currently there are no standards or specifications that define how to model the HATEOAS principle. Bu bölümde gösterilen örnekler tek bir olası çözümü göstermektedir.The examples shown in this section illustrate one possible solution.

Örneğin, bir sipariş ile müşteri arasındaki ilişkiyi işlemek için sipariş gösterimine siparişin müşterisi için kullanılabilir işlemleri tanımlayan bağlantılar eklenebilir.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. Olası bir gösterim şu şekildedir: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":[]
    }]
}

Bu örnekte links dizisi bir bağlantı kümesi içerir.In this example, the links array has a set of links. Her bağlantı, ilgili bir varlık üzerindeki bir işlemi temsil eder.Each link represents an operation on a related entity. Her bağlantının verileri ilişki ("müşteri"), URI (https://adventure-works.com/customers/3), HTTP yöntemi ve desteklenen MIME türlerini içerir.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. Bir istemci uygulamanın işlemi çağırabilmesi için gereken tüm bilgiler bunlardır.This is all the information that a client application needs to be able to invoke the operation.

links dizisi ayrıca alınmış kaynak hakkında kendi kendine başvuran bilgiler içerir.The links array also includes self-referencing information about the resource itself that has been retrieved. Bunlar kendi ilişkisine sahiptir.These have the relationship self.

Döndürülen bağlantı kümesi, kaynağın durumuna bağlı olarak değişebilir.The set of links that are returned may change, depending on the state of the resource. Köprü metninin "uygulama durumu altyapısı" olması bu anlama gelir.This is what is meant by hypertext being the "engine of application state."

RESTful web API'si sürümü oluşturmaVersioning a RESTful web API

Bir web API'sinin statik kalma olasılığı düşüktür.It is highly unlikely that a web API will remain static. İş gereksinimleri değiştikçe yeni kaynak koleksiyonları eklenebilir, kaynaklar arasındaki ilişkiler değişebilir ve kaynaklardaki verilerin yapısı değiştirilebilir.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. Bir web API'sini yeni ya da farklı gereksinimleri karşılayacak şekilde güncelleştirmek oldukça basit bir işlem olsa da, bu tür değişikliklerin web API'sini kullanan istemci uygulamalar üzerinde bırakacağı etkileri göz önünde bulundurmanız gerekir.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. Sorun şu ki, bir web API’sini tasarlayan ve uygulayan geliştirici bu API üzerinde tam denetime sahip olsa da, uzaktan çalışan üçüncü taraf kuruluşlar tarafından derlenebilecek istemci uygulamalar üzerinde aynı derecede denetime sahip değildir.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. Mevcut istemci uygulamaların değişmeden çalışmaya devam etmesini sağlarken yeni istemci uygulamaların yeni özellik ve kaynaklardan yararlanmasına olanak tanımak birincil zorunluluktur.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.

Sürüm oluşturma, bir web API’sinin kullanıma sunduğu özellik ve kaynakları göstermesini sağlar ve bir istemci uygulama, bir özellik ya da kaynağın belirli bir sürümüne yöneltilmiş istekler gönderebilir.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. Aşağıdaki bölümlerde, her biri kendi avantaj ve dezavantajlarına sahip birkaç farklı yaklaşım açıklanmaktadır.The following sections describe several different approaches, each of which has its own benefits and trade-offs.

Sürüm oluşturma yokNo versioning

En basit yaklaşımdır ve bazı iç API'ler için kabul edilebilir.This is the simplest approach, and may be acceptable for some internal APIs. Büyük değişiklikler yeni kaynak ya da yeni bağlantılar halinde gösterilebilir.Big changes could be represented as new resources or new links. Değişikliği görmeyi beklemeyen istemci uygulamalar basitçe yok sayacağı için, var olan kaynaklara içerik eklemek önemli bir değişiklik oluşturmayabilir.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.

Örneğin, istek URI'si için https://adventure-works.com/customers/3 içeren tek bir müşterinin ayrıntılarını döndürmelidir id, name, ve address istemci uygulama tarafından beklenen alanlar: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"}

Not

Kolaylık olması için bu bölümde gösterilen örnek yanıtlar HATEOAS bağlantılarını içermez.For simplicity, the example responses shown in this section do not include HATEOAS links.

DateCreated alanı, müşteri kaynağının şemasına eklenirse yanıt şu şekilde görünür: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"}

Mevcut istemci uygulamalar tanınmayan alanları yok sayma becerisine sahipse doğru şekilde çalışmaya devam edebilir, yeni istemci uygulamalar ise bu yeni alanı işleyecek şekilde tasarlanabilir.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. Ancak, kaynak şemasında çok daha köklü değişiklikler (alanları kaldırma veya yeniden adlandırma gibi) oluşur ya da kaynaklar arasındaki ilişki değişirse, bunlar mevcut istemci uygulamaların doğru şekilde çalışmasını engelleyen önemli değişiklikler olabilir.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. Bu durumlarda, aşağıdaki yaklaşımlardan birini düşünmelisiniz.In these situations you should consider one of the following approaches.

URI sürümü oluşturmaURI versioning

Web API’sini veya kaynak şemasını değiştirdiğiniz her durumda, her bir kaynak için URI’ye bir sürüm numarası eklersiniz.Each time you modify the web API or change the schema of resources, you add a version number to the URI for each resource. Önceden var olan URI'ler önceki gibi çalışmaya devam etmeli ve özgün şemalarına uygun kaynakları döndürmelidir.The previously existing URIs should continue to operate as before, returning resources that conform to their original schema.

Önceki örnekte, genişletme address alanı oluşturan her kısmı adresini içeren alt alanlar halinde (gibi streetAddress, city, state, ve zipCode), kaynağın bu sürümü olabilir bir sürüm numarası içeren bir URI kullanıma sunulan https://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 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}}

Bu sürüm oluşturma mekanizması çok basittir, ancak isteği uygun uç noktaya yönlendiren sunucuya bağlıdır.This versioning mechanism is very simple but depends on the server routing the request to the appropriate endpoint. Ancak, web API’si birkaç yineleme ile olgunlaştığından ve sunucunun birkaç farklı sürümü desteklemesi gerektiğinden bu mekanizmanın uygulanması giderek zorlaşabilir.However, it can become unwieldy as the web API matures through several iterations and the server has to support a number of different versions. Ayrıca, sadeci bir bakış açısıyla, istemci uygulamalar her durumda aynı verileri (müşteri 3) getirdiği için URI sürüme bağlı olarak farklılık göstermemelidir.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. Tüm bağlantıların URI’lerine sürüm numarasını eklemesi gerekeceğinden, bu düzen HATEOAS uygulamasını da karmaşık hale getirir.This scheme also complicates implementation of HATEOAS as all links will need to include the version number in their URIs.

Sorgu dizesi sürümü oluşturmaQuery string versioning

Birden fazla URI sağlamak yerine, kaynağın sürümünü gibi HTTP isteğine eklenmiş sorgu dizesi içinde bir parametre kullanarak belirtebilirsiniz 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. Sürüm parametresi, eski istemci uygulamalar tarafından çıkarılması durumunda varsayılan olarak 1 gibi anlamlı bir değerde olmalıdır.The version parameter should default to a meaningful value such as 1 if it is omitted by older client applications.

Bu yaklaşım, aynı kaynağın her zaman aynı URI’den alınmasını sağlayan semantik avantaja sahiptir, ancak sorgu dizesini ayrıştırmak ve uygun HTTP yanıtını geri göndermek için isteği işleyen koda bağımlıdır.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. Bu yaklaşım ayrıca URI sürümü oluşturma mekanizması ile aynı HATEOAS uygulama zorluklarını yaşar.This approach also suffers from the same complications for implementing HATEOAS as the URI versioning mechanism.

Not

Bazı eski web tarayıcıları ve web ara sunucuları, URI’ye sorgu dizesi ekleyen isteklere yönelik yanıtları önbelleğe almaz.Some older web browsers and web proxies will not cache responses for requests that include a query string in the URI. Bu, bu tür bir web tarayıcısında çalıştırın ve bir web API'sini kullanan web uygulamaları için performansı düşürebilir.This can degrade performance for web applications that use a web API and that run from within such a web browser.

Üst bilgi sürümü oluşturmaHeader versioning

Sürüm numarasını bir sorgu dizesi parametresi olarak ekleme yerine, kaynağın sürümünü belirten özel bir üst bilgi uygulayabilirsiniz.Rather than appending the version number as a query string parameter, you could implement a custom header that indicates the version of the resource. Bu yaklaşım, sürüm üst bilgisi kullanılmazsa istemci isteğini işleyen kodun varsayılan bir değer (sürüm 1) kullanabilmesine karşın, istemci uygulamanın herhangi bir isteğe uygun üst bilgiyi eklemesini gerektirir.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. Adlı bir özel üst bilgi aşağıdaki örneklerde Custom-Header.The following examples use a custom header named Custom-Header. Bu üst bilginin değeri, web API’sinin sürümünü gösterir.The value of this header indicates the version of web API.

Sürüm 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"}

Sürüm 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}}

Önceki iki yaklaşımda olduğu gibi, HATEOAS uygulamanın da herhangi bir bağlantıya uygun özel üst bilgiyi eklemeyi gerektirdiğini unutmayın.Note that as with the previous two approaches, implementing HATEOAS requires including the appropriate custom header in any links.

Medya türü sürümü oluşturmaMedia type versioning

İstemci uygulama bir web sunucusuna HTTP GET isteği gönderdiğinde, bu rehberin önceki kısımlarında anlatıldığı gibi bir Accept üst bilgisi kullanarak, işleyebileceği içeriğin biçimini belirtmelidir.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. Accept üst bilgisinin amacı genellikle yanıt gövdesinin XML, JSON ya da istemci tarafından ayrıştırılabilen başka bir yaygın biçim olup olmadığının istemci uygulama tarafından belirtilmesine olanak tanımaktır.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. Ancak, istemci uygulamanın hangi kaynak türünü beklediğini belirtmesini sağlayan bilgiler içeren özel medya türleri tanımlamak mümkündür.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. Aşağıdaki örnekte, application/vnd.adventure-works.v1+json değeri ile Accept üst bilgisi belirten bir istek gösterilmiştir.The following example shows a request that specifies an Accept header with the value application/vnd.adventure-works.v1+json. vnd.adventure-works.v1 öğesi, web sunucusuna kaynağın sürüm 1’ini döndürmesi gerektiğini, json öğesi ise yanıt gövdesi biçiminin JSON olması gerektiğini belirtir: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

İsteği işleyen kod, Accept üst bilgisini işlemekten ve mümkün olduğunca uzak onaylamaktan sorumludur (istemci uygulama, Accept üst bilgisinde birden fazla biçim belirtebilir ve bu durumda web sunucusu, yanıt gövdesi için en uygun biçimi seçebilir).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). Web sunucusu, Content-Type üst bilgisini kullanarak yanıt gövdesindeki verilerin biçimi onaylar: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"}

Accept üst bilgisi bilinen bir medya türü belirtmezse, web sunucusu bir HTTP 406 (Kabul Edilemez) yanıt iletisi oluşturur ya da varsayılan medya türünü içeren bir ileti döndürür.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.

Bu yaklaşım tartışmaya açık bir şekilde sürüm oluşturma mekanizmalarının en sade olanıdır ve kendisini, kaynak bağlantılarında ilgili verilerin MIME türünü içerebilen HATEOAS seçeneğine borçludur.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.

Not

Bir sürüm oluşturma stratejisi seçerken, başta web sunucusunda önbelleğe alma olmak üzere performansa etkilerini de göz önünde bulundurmanız gerekir.When you select a versioning strategy, you should also consider the implications on performance, especially caching on the web server. URI sürümü oluşturma ve Sorgu Dizesi sürümü oluşturma düzenleri, URI/sorgu dizesi birleşimi her seferinde aynı verilere başvurduğu sürece önbelleğe almaya uygundur.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.

Üst Bilgi sürümü oluşturma ve Medya Türü sürümü oluşturma mekanizmaları genellikle özel üst bilgi veya Accept üst bilgisi içindeki değerleri incelemek için ilave bir mantık gerektirir.The Header versioning and Media Type versioning mechanisms typically require additional logic to examine the values in the custom header or the Accept header. Büyük ölçekli bir ortamda, bir web API'sinin farklı sürümlerini kullanan çok sayıda istemci, sunucu tarafı önbelleğinde önemli miktarda yinelenen veri ile sonuçlanabilir.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. Bir istemci uygulama, önbelleğe alma işlemini uygulayan bir ara sunucu üzerinden bir web sunucusu ile iletişim kurarsa ve o anda önbelleğinde istenen verilerin bir kopyasını tutmaması durumunda bu iletişim yalnızca web sunucusuna bir istek iletiyorsa, bu sorun ağırlaşabilir.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

Open API Initiative, farklı satıcıların REST API açıklamalarını standart hale getirmek için bir sektör konsorsiyumu tarafından oluşturulmuştur.The Open API Initiative was created by an industry consortium to standardize REST API descriptions across vendors. Bu girişimin bir parçası olarak Swagger 2.0 belirtimi, OpenAPI Belirtimi (OAS) olarak yeniden adlandırılmış ve Open API Initiative kapsamına alınmıştır.As part of this initiative, the Swagger 2.0 specification was renamed the OpenAPI Specification (OAS) and brought under the Open API Initiative.

Web API'leriniz için OpenAPI’yi benimsemek isteyebilirsiniz.You may want to adopt OpenAPI for your web APIs. Dikkat edilmesi gereken bazı noktalar:Some points to consider:

  • OpenAPI Belirtimi, bir REST API’nin nasıl tasarlanması gerektiğine ilişkin görüşler içeren bazı yönergelerle birlikte gönderilir.The OpenAPI Specification comes with a set of opinionated guidelines on how a REST API should be designed. Bu seçenek, birlikte çalışabilirlik için avantajlar sunmasına karşın API’nizi tasarlarken belirtime uymak için daha fazla dikkat gerektirir.That has advantages for interoperability, but requires more care when designing your API to conform to the specification.

  • OpenAPI, uygulama öncelikli yaklaşım yerine sözleşme öncelikli bir yaklaşımı destekler.OpenAPI promotes a contract-first approach, rather than an implementation-first approach. Sözleşme öncelikli yaklaşım, önce API sözleşmesini (arabirim) tasarlamanız ve sonra sözleşmeyi uygulayan kodu yazmanız anlamına gelir.Contract-first means you design the API contract (the interface) first and then write code that implements the contract.

  • Swagger gibi araçlar, API sözleşmelerinden istemci kitaplıkları veya belgeler oluşturabilir.Tools like Swagger can generate client libraries or documentation from API contracts. Örneğin bkz. Swagger Kullanarak ASP.NET Web API Yardım Sayfaları.For example, see ASP.NET Web API Help Pages using Swagger.

Daha fazla bilgiMore information