Kısım II · İnşaat · Bölüm 35

HTTP, JSON ve REST

Web API dilinin parçaları (HTTP, JSON and REST in depth)

Neden burada · Neye dayanıyor

Neden burada: Önceki bölümde API sözleşmesini tanıdın. Şimdi aynı sözleşmenin ağda nasıl göründüğünü ayırıyoruz: istek yöntemi, sonuç kodu, veri biçimi ve kaynak tasarımı.

Neye dayanıyor: Bölüm 20.4: HTTP/HTTPS ile istek–yanıt; Bölüm 25.3: nesne ve dizi; Bölüm 34: API sözleşmesi ve güven sınırı.

  1. Kat 10Bizim uygulamamız: Go arka uç, Postgres ve istemciBu bölüm: HTTP, JSON ve REST. Bölüm 1'in kat planı üzerindeyiz.
  2. Kat 9 ve 8Web ve ağKullanıcı arayüzünden gelen istekler HTTP ile taşınır.
  3. Kat 7 ve 5İşletim sistemi, diller ve derleyiciProgram süreç olur; derleyici Go metnini çalıştırılabilir dosyaya çevirir.
  4. Kat 0–4 ve 6Fiziksel temel, makine dili ve açılışBellek, depolama ve işlemci alttaki işi sürdürür; burada yeni donanım yok.

Bölüm sonunda bir ağ isteğine bakıp ne istendiğini, hangi verinin taşındığını ve hatanın hangi katmanda olduğunu söyleyebileceksin. HTTP, JSON ve REST'i birbirine karıştırmadan aynı yolculukta birleştireceğiz.

35.1 HTTP isteği: yöntem, başlık, gövde

Bölüm 34.3'te API'yi iki programın sözleşmesi olarak kurduk. Şimdi sözleşmenin ağdaki cümlelerine bakıyoruz. HTTP, bu cümlelerin hangi parçalardan oluşacağını ve parçaların ne anlama geleceğini belirler. JSON ise bu cümlelerden birinin içinde taşınabilecek veri biçimidir. REST de böyle bir sistemi tasarlamak için kullanılan mimari üsluptur. Birbirinin yerine geçen üç ad değil, üç ayrı sorunun cevabıdır: nasıl konuşacağız, veriyi nasıl yazacağız, kapıları nasıl düzenleyeceğiz?156

İstek (request), istemcinin sunucuya gönderdiği mesajdır. Bir yöntem (method) ne yapılacağını; hedef adres hangi şey üzerinde yapılacağını söyler. Başlık (header) mesaj hakkındaki üst veridir. Gövde (body), varsa, taşınan içeriktir. Bu ayrım, dosyanın içeriği ile dosya hakkındaki bilgiyi ayırdığımız Bölüm 16'nın mesaj düzeyindeki akrabasıdır.1

GET /leaderboard?limit=10 HTTP/1.1
Host: api.example.test
Accept: application/json

İlk satırı soldan sağa oku: GET bir gösterimi okumak istediğimizi; /leaderboard sıralamayı; ?limit=10 en çok kaç kayıt istediğimizi; HTTP/1.1 bu okunabilir örneğin protokol sürümünü söyler. Host hedef sunucuyu belirtir. Accept, istemcinin yanıt için kabul ettiği veri biçimini bildirir; burada JSON istiyoruz. Başlıklarla gövde arasındaki sınır boş satırdır. Bu istekte gövde yoktur. HTTP/2 ve HTTP/3'ün ağdaki gösterimi bu düz metin resimle aynı değildir; burada mesajın anlamını öğrenmek için HTTP/1.1 gösterimini kullanıyoruz, paket dökümü ezberlemiyoruz.1312

YöntemTemel anlamÖrnek tasarım
GETKaynağın gösterimini getir; veri değiştirmek istemeGET /questions/1
POSTVeriyi hedef kaynağa işlemesi için gönderPOST /answers ile cevap kaydı oluştur
PUTHedefin gösterimini verilen içerikle bütünüyle değiştir; uygun durumda oluşturPUT /preferences/1 ile tercihlerin tamamını yaz
PATCHHedefe kısmi değişiklik tarif etPATCH /preferences/1 ile yalnız dili değiştir
DELETEHedef kaynağı kaldırDELETE /answers/17; yalnız API izin veriyorsa

Bu anlamlar düğmelerin adından çıkmaz; HTTP sözleşmesidir. Bir geliştirici yanlışlıkla GET /add-points yazarak okuma isteğine puan artırma işi yükleyebilir. Bilgisayar bunu ahlaken reddetmez, ama istemcilerin okuma hakkındaki beklentisini bozar. Sayfa yenileme, önceden getirme ya da yeniden deneme veri değiştirmeye başlar. Yöntem seçimi bu yüzden süs değil, başka programlara verilmiş sözdür.27

POST /answers HTTP/1.1
Host: api.example.test
Content-Type: application/json
Accept: application/json

{"question_id":1,"choice":2}

Bu kez POST sunucuya bir cevap gönderir. Content-Type, gönderdiğim gövde JSON der; Accept, yanıtı JSON kabul ediyorum der. Aynı kelimeyi taşımaları aynı işi yaptıkları anlamına gelmez. Gövdedeki question_id hangi soruyu, choice hangi şıkkı seçtiğimizi belirtir. Alan adlarını HTTP seçmedi; bizim API sözleşmemiz seçti. points göndermiyoruz: güven sınırı gereği puanı sunucu hesaplayacak.

Yol ile sorguyu da ayır: /questions/1 belirli soruyu adresler; /questions?lesson_id=3 soru koleksiyonunu filtreleyebilir. Sorgu parametresi de kullanıcı girdisidir; limit=on gelirse sunucu onu kendiliğinden sayıya dönüştürmek zorunda değildir. Bölüm 37'de sayıya çevirmeyi, aralık denetimini ve reddetmeyi açıkça yazacağız. İstemcinin TypeScript'te sayısal değişken kullanmış olması ağdan gelen metnin güvenilir olduğunu göstermez.

35.2 HTTP yanıtı: durum kodları

Yanıt (response), sunucunun isteğe verdiği mesajdır. Yanıtın durum kodu (status code), işin protokol düzeyindeki sonucunu anlatır. Başlıklar gövdenin biçimini ve başka davranışları tarif eder. Gövde bir kullanıcı listesi de olabilir, bir hata açıklaması da. Gövdede JSON bulunması isteğin başarılı olduğunu göstermez: hata da JSON ile yazılabilir.4

HTTP/1.1 201 Created
Content-Type: application/json

{"correct":true,"points_awarded":10,"total_points":50}

İlk satırda 201, isteğin başarıyla yeni kaynak oluşturduğunu söyler; bu örnekte cevap kaydı. Created insanın okuduğu açıklamadır, programın karar verirken baktığı parça kod olmalıdır. JSON gövdesi iş sonucunu anlatır: cevap doğru; bu kabulde 10 puan verilmiş; toplam 50 olmuş. Öğretici başlangıç puanı 40 ise hesap 40 + 10 = 50'dir. Bu sayılar ürünün değişmez kuralı değil, kitabın sınanabilir örnek verisidir.

KodNe anlatır?Uygulamamızdaki örnek
200 OKİstek başarılıLeaderboard listesi döndü
201 CreatedYeni kaynak oluşturulduCevap kaydı kabul edildi
400 Bad Requestİstekte işlenmesini engelleyen bir sorun varBozuk JSON veya geçersiz limit
401 UnauthorizedGeçerli kimlik doğrulama bilgisi gerekliOturum yok veya geçersiz
403 ForbiddenSunucu erişime izin vermiyorBu içeriği değiştirme yetkin yok
404 Not FoundHedef bulunamadı veya varlığı açıklanmıyorVerilen soru kimliği mevcut değil
500 Internal Server ErrorSunucu beklenmeyen iç sorunla karşılaştıİşi tamamlayamayan arka uç hatası

401'in İngilizce adı kafa karıştırır: burada temel mesele kimliğin doğrulanmasıdır. 403'te ise talep reddedilir; yeniden aynı kimliği söylemek tek başına çözüm değildir. Bir kaynak için yetki yoksa kimi sistemler varlığını gizlemek amacıyla 404 döndürür. Bu yüzden 404 görmek, kaynağın gerçekten hiçbir yerde bulunmadığını kanıtlamaz. Kimlik doğrulama ile yetkilendirmeyi Bölüm 41 ayıracak.4

Kodların ilk rakamı aileyi anlatır: 2xx başarı, 3xx yönlendirme, 4xx istemci isteğiyle ilgili hata, 5xx sunucu hatasıdır; 1xx ara bilgi içindir. Her ayrıntıyı şimdi ezberlemen gerekmiyor. Uygulamada 405 desteklenmeyen yöntem, 413 fazla büyük gövde, 415 desteklenmeyen içerik biçimi ve 422 sözdizimi anlaşılır ama içerik kuralları bakımından işlenemeyen istek için karşına çıkabilir. Bölüm 37'de 422'yi şık aralığı için kullanacağız. 500 ise “cevap yanlış” demek değildir: yanlış şık, doğru çalışan bir eğitim sisteminin normal sonucudur.4

Bölüm 33 ile bağlantı: hata neden Query'ye ulaşmıyor?

Bölüm 33'te if (!res.ok) throw new Error(...) görmüştün. Artık gerekçesi görünür: ağ üzerinden bir HTTP hata yanıtı almak ile hiç yanıt alamamak farklıdır. Sorgu fonksiyonu, başarısız durum kodunu kendi hata akışına çevirmelidir. Yoksa {"error":"soru bulunamadı"} nesnesi, kullanıcı listesi sanılabilir. Durum kodunu, gövdeyi ve ağ hatasını ayrı incele; bunlar üç ayrı kanıttır.

35.3 JSON: veri biçimi ve serileştirme

JSON (JavaScript Object Notation), programlar arasında yapılandırılmış veri taşımak için kullanılan metin biçimidir. Adında JavaScript bulunsa da JavaScript motoru gerektirmez. Go, Python ve başka diller aynı metni kendi değerlerine çevirebilir. Bu, iki tarafın aynı belleği paylaşmadan anlaşmasını sağlar: TypeScript nesnesinin bellek adresini değil, üzerinde anlaşılmış yazılı gösterimini göndeririz.5

{
  "user_id": 1,
  "name": "Kerem",
  "points": 40,
  "active": true,
  "badges": ["ilk-bolum", "tekrar"],
  "last_answer": null
}

Süslü parantezler nesneyi, yani ad–değer çiftlerini; köşeli parantezler sıralı diziyi gösterir. "name" ve "Kerem" karakter dizileridir; çift tırnak gerekir. 40 sayı, true Boole değeri, null açıkça boş değerdir. JSON'da altı temel değer türü vardır: nesne, dizi, karakter dizisi, sayı, Boole ve null. Bir JSON belgesi en üstte mutlaka nesne olmak zorunda değildir; bir dizi ya da tek bir değer de olabilir. Bizim sözleşmemizde leaderboard'un en üst düzeyi dizi olacak.5

undefined, fonksiyonlar, yorum satırları ve sondaki fazladan virgül JSON'un parçası değildir. JavaScript'te kabul edilen {name: 'Kerem'}, JSON değildir: ad tırnaksız, değer tek tırnaklı. {"points":"40"} geçerli JSON'dur ama sayı yerine metin taşır. Ayrıştırıcı açısından geçerli olmak, uygulamanın sözleşmesine uygun olmak değildir. Aynı biçimde {"question_id":-1,"choice":99} sözdizimi bakımından geçerli olabilir; var olmayan soru ve kabul edilmeyen şık sorununu iş kuralları çözer.5

Serileştirme (serialization), programdaki yapılandırılmış değeri saklanabilir veya aktarılabilir gösterime dönüştürmektir. Tersi, gösterimi yeniden program değerlerine çözmektir. JSON için bu yol metin üzerinden geçer. JavaScript'te JSON.stringify metin üretir; JSON.parse JSON metnini ayrıştırır. Go'da ilgili araçlar encoding/json paketindedir; Bölüm 37.2 aynı geçidi sunucu tarafında açacak.13

const answer = { question_id: 1, choice: 2 }
const text = JSON.stringify(answer)
const copy = JSON.parse(text)

İlk satır bellekte bir JavaScript nesnesi kurar. İkinci satır bu nesnenin JSON metnini üretir; text artık nesne değil karakter dizisidir. Üçüncü satır metinden bir değer kurar. Burada ağ isteği yapılmadı ve veri kaydedilmedi; yalnız gösterim değişti. Ayrı bir fetch çağrısı bu metni gövde olarak gönderebilir. JSON ile HTTP'yi aynı şey sanmak tam bu ayrımı kaybettirir: JSON'u dosyaya da yazabilir, HTTP ile JSON olmayan bir fotoğraf da taşıyabilirsin.

Bölüm 2.5'teki UTF-8'i burada yerine koy: JSON yapının metinsel kurallarını söyler; UTF-8 metnin byte olarak yazılma kuralıdır. "şık" metni ile onun byte uzunluğu aynı şey değildir. HTTP gövdesinin boyutunu sınırlamak bu yüzden karakter saymak değildir. Bölüm 37'nin 4096 byte sınırı, Türkçe bir metinde 4096 karakter sözü vermez. Sayısal hassasiyet de biçim ile alıcı dil arasında düşünülmelidir: JSON'da sayı yazılabilmesi, her dilin her büyüklükte tam sayıyı kayıpsız saklayacağı anlamına gelmez. Büyük kimlikleri metin taşıma gibi kararlar sözleşmede açıkça verilmelidir.513

35.4 REST: kaynak, uç nokta, URL ve idempotent işlemler

REST (Representational State Transfer) bir veri biçimi veya kurulacak kütüphane değildir; ağ üzerinden etkileşen bileşenler için mimari kısıtlar bütünüdür. Kaynak (resource), adreslenebilen kavramdır: bir kullanıcı, bir soru ya da haftalık sıralama. Gösterim (representation), kaynağın belli anda istemciye aktarılmış biçimidir. Veritabanı satırı, Go struct'ı ve JSON gövdesi aynı şey değildir; aynı kullanıcıyı farklı katlarda temsil edebilirler.6

Uç nokta (endpoint), API'de erişilen belirli giriş yeridir. Konuşurken genellikle yöntemle yolu birlikte söyleriz: GET /leaderboard. Aynı yoldaki POST başka bir sözleşme olabilir. Kaynak odaklı tasarımda /questions bir koleksiyon, /questions/1 onun belirli üyesi olarak okunur. /getQuestion gibi fiilleri yola yığmak yerine, yapılacak işi yöntem; üzerinde çalışılacak şeyi yol anlatır. Bu bir URL tasarım tercihidir; bütün API'ler aynı çoğul adları kullanmak zorunda değildir.

Fielding'in tezindeki REST yalnızca “HTTP üstünde JSON” değildir. İstemci–sunucu ayrımı, durumsuz etkileşim, önbellek kısıtları, tekbiçimli arayüz ve katmanlı sistem birlikte ele alınır; isteğe bağlı kod aktarımı da bulunur. Tekbiçimli arayüzün içinde kaynakların tanınması, gösterimlerle işlem, kendini açıklayan mesajlar ve uygulama durumunun bağlantılarla yönlendirilmesi vardır. Bu son fikir, istemcinin mümkün sonraki eylemleri yanıttaki bağlantılardan öğrenmesidir. Buradaki küçük API, bütün bu kısıtları eksiksiz gerçeklediğini iddia etmiyor; kaynak odaklı bir HTTP+JSON API'si kuruyoruz. Tez yalnız atıf ve merak kaynağıdır, başlangıçta baştan okunması gereken ödev değildir.6

İdempotent (idempotent), aynı isteğin tekrarlanmasının hedeflenen etkisinin bir kez yapılmasıyla aynı olmasıdır. “Tercih dilini Türkçe yap” tekrarlandığında dil yine Türkçedir. “Puana 10 ekle” tekrarlandığında ise her seferinde yeni artış hedeflenir. GET güvenlidir ve idempotenttir; PUT ile DELETE de idempotent anlam taşır. POST ve PATCH için böyle genel bir güvence yoktur. PATCH ile bir değeri sabite atamak idempotent tasarlanabilir; sayacı artırmak aynı özelliği taşımaz.27

İdempotent olmak aynı yanıtı vermek değildir. Bir kaynağı ilk DELETE kaldırır; ikinci DELETE, artık yok diye 404 döndürebilir. Hedeflenen son durum yine “kaynak yok”tur. Sunucunun her isteği kayda geçirmesi de aynı etki tanımını bozmaz; burada söz konusu olan istemcinin istediği etkidir. Ayrıca eşzamanlı değişiklikler ve koşullu istekler ayrı tasarım sorunlarıdır; “idempotent” sözcüğü bütün yarış durumlarının çözüldüğünü anlatmaz.7

Uygulamamızda: çift dokunuş değil, tekrar teslim sorunu

Kullanıcı doğru cevabı gönderir. Sunucu kaydeder ama yanıt ağda kaybolur. Kullanıcı başarısız sandığı işi yeniden gönderir. İki ayrı POST, sunucu bakımından iki ayrı teslimdir; düğmeyi devre dışı bırakmak bunu tek başına çözmez. Ürün kuralı “aynı başarıdan bir kez puan” ise sunucu tekrarları tanımalıdır. Bölüm 37 bunu tek süreçte küçük bir bellek kaydıyla gösterecek; Bölüm 39.3 kalıcı kayıt ve işlem tarafını açacak. POST'un kendi başına tek-seferlik teslim güvencesi yoktur. İstek kimliği, tekrar politikası ve kalıcı kısıt birlikte tasarlanır.

35.5 Alternatifler: GraphQL ve RPC

GraphQL (GraphQL query language), istemcinin ihtiyaç duyduğu alanları bir sorguda tarif etmesine imkân veren API yaklaşımıdır. Kaynak URL'lerini gezmek yerine bir veri şemasına uygun alanlar seçilir. Örneğin kullanıcı adı ile puanını ister, profilin diğer alanlarını istemezsin. Bu, sunucunun veritabanını doğrudan telefona açmak değildir; sunucu yine hangi alanın nasıl getirileceğini ve kimin okuyabileceğini belirler. “İstediğin alanı söylemek”, “istediğin bütün veriye yetkin var” anlamına gelmez.8

Uzak yordam çağrısı (RPC, Remote Procedure Call) ise etkileşimi bir kaynağa yöntem uygulamaktan çok, uzaktaki adlandırılmış işi çağırmak şeklinde kurar: SubmitAnswer gibi. gRPC bunun bir gerçeklemesidir; hizmetin metotlarını, girdi ve dönüş tiplerini tanımlar; istemci tarafında bunları çağırmaya yarayan kod üretilebilir. Varsayılan veri biçimi Protocol Buffers'tır. RPC yalnız gRPC demek değildir ve ağ üzerinden çağrı yapmak yerel fonksiyon çağrısı kadar sorunsuz olmaz: gecikme, iptal ve kısmi başarısızlık hâlâ vardır.9

Bu kitapta kaynak odaklı HTTP+JSON seçmemizin pedagojik gerekçesi şudur: yöntem, adres, başlık ve gövdeyi ayrı ayrı görebiliyoruz. GraphQL veya RPC kötü olduğu için değil; aynı soruna farklı arayüzler kurdukları için burada yalnız haritadaki yerlerini belirliyoruz. Bir agent GraphQL önerirse soracağın soru “daha modern mi?” değil, “hangi veri ihtiyacı veya istemci sözleşmesi bu ek dili gerekli kılıyor?” olmalı. Bu değerlendirme bizim tasarım çıkarımımızdır; evrensel hız sıralaması değildir.

35.6 CORS, çerezler ve oturum: ilk bakış

İstek doğru, sunucu yanıt vermiş, curl sonucu gösteriyor ama tarayıcı “CORS” diyor. Burada HTTP sunucusu ile tarayıcının güvenlik politikasını ayırmalısın. Köken (origin), şema, ana makine adı ve port birleşimidir. http://localhost:3000 ile http://localhost:8080 aynı makinede olsa da farklı kökendir. Kökenler arası kaynak paylaşımı (CORS, Cross-Origin Resource Sharing), tarayıcının başka kökendeki yanıtı betiğe açması için sunucunun izin bildirdiği başlık düzenidir.10

Bazı isteklerden önce tarayıcı Ön uçuş isteği (preflight request) gönderir. Yöntemi OPTIONS'tır; “şu kökenden şu yöntem ve başlıklarla asıl isteği gönderebilir miyim?” diye sorar. JSON içerik tipli kökenler arası POST buna tipik örnektir. Sunucu uygun Access-Control-Allow-Origin, yöntem ve başlık izinlerini bildirir. Yanıtta rastgele bir başlığa * yazmak bütün durumların çözümü değildir: kimlik bilgisi içeren paylaşımda açık köken ve uygun kimlik bilgisi izni gerekir.10

CORS bir kullanıcı kimliği doğrulama yöntemi değildir. Tarayıcı olmayan istemci bu politikayı uygulamak zorunda değildir; bir saldırgan kendi HTTP istemcisini yazabilir. CORS bütün isteklerin gönderilmesini de engellemez: ön uçuş gerektirmeyen istek sunucuya ulaşabilir ama yanıtı betiğe açılmaz. Bu yüzden CORS hatası gördüğünde “yazma kesin olmadı” varsayımı yapma. Çapraz site istek sahteciliği gibi saldırılara karşı tek başına CORS'a güvenilmez; ayrıntı Bölüm 41.4'te. Expo'nun web çıktısı tarayıcı politikasına tabidir; yerel mobil ağ istemcisini aynı tarayıcı modeliyle açıklamayız.

Çerez (cookie), tarayıcının saklayıp kapsamına uyan sonraki isteklere ekleyebildiği küçük veridir. Sunucu Set-Cookie yanıt başlığı gönderir; tarayıcı sonraki uygun istekte Cookie başlığı yollar. Oturum (session), ayrı istekleri kullanıcıyla ilişkili bir etkileşim bağlamında birleştiren düzendir. Sık kullanılan bir tasarımda çerez yalnız tahmin edilemez oturum kimliğini taşır; sunucu bu kimliği geçerli kullanıcıyla eşleştirir. Kullanıcının adını çereze yazmak, kimliği kanıtlamak değildir.11

Secure çerezin şifreli HTTPS isteklerinde taşınmasını sınırlar; HttpOnly betiklerin çereze erişmesini engeller; SameSite çapraz site gönderim davranışını sınırlar. Bunların hiçbiri tek başına “artık güvenli” mührü değildir. Çerezin kapsamı ve ömrü, oturumun sunucuda geçerliliği ve yazma isteklerinin korunması ayrıca tasarlanır. Bölüm 34'teki durumsuzluk ayrımını da inceltelim: HTTP durumsuz olabilirken uygulama çerezle oturum kurabilir; oturum verisini ayrı depoya taşımak sunucu kopyalarını kolaylaştırır ama otomatik olarak Fielding'in bütün REST kısıtlarının karşılandığını kanıtlamaz.116

Bu bölümde neler kuruldu

HTTP mesajın yöntemini, başlıklarını ve sonucunu tanımlar. JSON, gövdede taşınabilecek metinsel biçimdir; ayrıştırılabilmesi iş kuralına uygun olduğunu göstermez. REST kaynak ve gösterimlerle ilişkileri düzenleyen mimari üsluptur. İdempotentlik aynı yanıt değil, aynı hedeflenen etkidir. CORS tarayıcı politikasını, çerez veri taşımayı, oturum ise isteklerin bağlamını ilgilendirir. Sonraki bölümde bu mesajları işleyecek Go dilini tanıyacağız.

Terimler sözlükte, Bölüm 35 başlığı altında.

Birincil okuma

İlk okuma: kaynak 1, MDN Overview of HTTP içindeki HTTP messages ve HTTP flow. Derinleşme: kaynak 2, HTTP request methods; kaynak 5, JSON.org Introducing JSON.

Takıldığın yeri yapay zekâ öğretmenine sor: “Bana bir istek ve bir yanıt ver; yöntem, başlık, gövde ve durum kodunu ben işaretleyeyim.” Ardından aynı POST'un iki kez gelmesi senaryosunu tartış.

Bölüm sonu soruları

Kitaba bakmadan cevapla. Geri bildirim yalnız sonucu değil, gerekçeyi de gösterir.

1. Content-Type ile Accept arasındaki doğru ayrım nedir?
Content-Type mevcut içeriğin biçimini, Accept kabul edilen yanıt biçimlerini bildirir. Bkz. 35.1.
2. Geçerli kimlik bilgisi gereken bir isteğin temel hata kodu hangisidir?
401 kimlik doğrulama bilgisinin gerekli olduğunu bildirir; 403 erişimin reddidir. Bkz. 35.2.
3. Hangisi geçerli JSON içinde sayısal puan taşır?
JSON adları çift tırnaklıdır; tırnaksız değer burada sayıdır. Bkz. 35.3.
4. DELETE tekrarında farklı durum kodu gelmesi neyi gösterir?
İdempotentlik yanıt eşitliği değil, hedeflenen etki hakkındadır. Bkz. 35.4.
5. REST için hangi ifade daha doğrudur?
REST mimari üsluptur; JSON biçim, Go paketi gerçekleme aracıdır. Bkz. 35.4.
6. GraphQL istemciye hangi imkânı verir?
Alan seçimi şemaya uyar; güvenlik kararını sunucu vermeyi sürdürür. Bkz. 35.5.
7. CORS hangi sınırla doğrudan ilgilidir?
CORS tarayıcı ile köken ilişkisini düzenler; kullanıcı doğrulamaz. Bkz. 35.6.
8. Çerezli oturumda hangi ifade doğrudur?
Çerez yalnız veri taşır; geçerlilik ve kullanıcı eşlemesi sunucuda denetlenir. Bkz. 35.6.
9. Ağ yanıtı kaybolunca aynı POST neden yeniden puan verebilir? Düğmeyi kapatmak neden yeterli değildir?
Örnek cevabı göster

İlk istek sunucuda işlenmiş olabilir; istemci yanıtı görmediği için tekrar gönderir. Sunucu tekrar politikasını kalıcı kayıtla sağlamalıdır; düğme yalnız yerel etkileşimi sınırlar. Bkz. 35.4.

10. “curl çalışıyor ama tarayıcı çalışmıyor” gözlemini CORS, kimlik ve veri biçimi açısından nasıl ayırırsın?
Örnek cevabı göster

Önce tarayıcı konsolunda CORS başlıklarını ve varsa OPTIONS isteğini incelerim. Sonra kimlik bilgisini ve HTTP durumunu, en son gövdenin JSON sözleşmesini denetlerim. curl sonucu tarayıcıya izin verildiğini kanıtlamaz. Bkz. 35.6.

Kaynaklar

  1. MDN · Overview of HTTP: mesaj parçaları ve HTTP akışı.
  2. MDN · HTTP request methods: GET, POST, PUT, PATCH, DELETE ve yöntem anlamları.
  3. MDN · HTTP headers: Content-Type, Accept ve kimlik başlıkları.
  4. MDN · HTTP response status codes: başarı ve hata kodlarının anlamları.
  5. JSON.org · Introducing JSON: değerler, nesneler, diziler ve sayı gösterimi.
  6. Roy Fielding · REST architectural style, Bölüm 5: mimari kısıtlar ve kaynak/gösterim ayrımı; yalnız atıf.
  7. MDN · Idempotent: hedeflenen etki ile yanıt eşitliği ayrımı.
  8. GraphQL · Queries: istemcinin alan seçmesi ve sorgu yapısı.
  9. gRPC · Introduction to gRPC: uzak metot, hizmet sözleşmesi ve Protocol Buffers.
  10. MDN · Cross-Origin Resource Sharing (CORS): köken, ön uçuş ve kimlik bilgili istekler.
  11. MDN · Using HTTP cookies: Set-Cookie, Cookie, oturum ve güvenlik nitelikleri.
  12. MDN · HTTP/3: HTTP/3 taşımasının HTTP/1.1 düz metin gösteriminden ayrımı.
  13. MDN · JSON: Static methods; Lossless number serialization: JSON.stringify, JSON.parse ve sayı hassasiyeti.