PUT, hedef kaynağın durumunu istekte gönderdiğiniz temsille bütünüyle değiştirir; PATCH ise kaynağa uygulanacak değişiklikleri tarif eden bir yama belgesi (patch document) gönderir ve yalnızca bu değişikliklerin yapılmasını ister. Pratik sonucu şudur: PUT gövdesinde unuttuğunuz bir alan kaynaktan da düşer, PATCH gövdesinde yazmadığınız alanlar ise olduğu gibi kalır. PUT tanımı gereği idempotenttir (aynı isteği tekrarlamak aynı sonucu verir), PATCH ise tanımı gereği idempotent değildir ama kullandığınız yama biçimine göre idempotent davranabilir.

Bu yazıda iki metodun REST API tasarımında ne zaman seçileceğini, PATCH için en sık kullanılan iki JSON biçimini (JSON Merge Patch ve JSON Patch), idempotentlik farkının yeniden deneme davranışına etkisini ve hata durumlarında hangi durum kodunun döneceğini tek bir /kullanicilar örneği üzerinden ele alıyoruz. Metotların genel tanımı ve güvenli/idempotent tablosu için HTTP istek ve yanıt yapısı yazısına, serinin tamamı için REST API tasarımı öğrenme rehberi sayfasına bakabilirsiniz.

Kısa cevap: iki metodun niyeti farklı

Kısa cevap: iki metodun niyeti farklı: Gövdenin anlamı, Gönderilmeyen alan, İdempotent mi, Gövde biçimi

HTTP Semantics belgesi (RFC 9110) PUT için çok net bir niyet tanımlar: istemci, hedef URI'deki kaynağın yeni durumunun tam olarak gönderdiği temsil olmasını ister. Başarılı bir PUT'tan sonra aynı adrese yapılan GET'in, gönderilenle eşdeğer bir temsil döndürmesi beklenir. Yani PUT gövdesi bir "son hal" fotoğrafıdır; sunucu eski halle yeniyi karşılaştırmaz, eskisini atar ve yenisini koyar.

PATCH metodunu tanımlayan RFC 5789 ise gövdeyi bir talimat listesi olarak görür. Gönderilen belge, sunucudaki mevcut kaynağın nasıl değiştirileceğini anlatır ve bu belgenin biçimi bir medya tipiyle (media type) belirtilir. RFC 5789 bu farkı kendisi de açıkça yazar: PUT'ta gövde kaynağın değiştirilmiş bir sürümüdür, PATCH'te ise yeni sürümü üretmek için uygulanacak değişikliklerin tarifidir. Bu yüzden PATCH için tek bir varsayılan biçim yoktur; sunucunun hangi yama biçimlerini kabul ettiğini ilan etmesi gerekir.

ÖzellikPUTPATCH
Gövdenin anlamıKaynağın tam yeni haliUygulanacak değişikliklerin tarifi
Gönderilmeyen alanKaynaktan düşer veya varsayılana dönerOlduğu gibi kalır
İdempotent miEvet, tanımı gereğiTanımı gereği hayır, biçime göre olabilir
Gövde biçimiKaynağın normal temsili (ör. application/json)Yama medya tipi (ör. application/merge-patch+json)
Kaynak yoksa201 Created ile oluşturabilirYama biçimi izin veriyorsa oluşturabilir
Başarılı yanıt200 OK veya 204 No Content200 OK veya 204 No Content

PUT: kaynağın tamamını değiştirmek

PUT kullanırken istemcinin elinde kaynağın eksiksiz bir temsili olmalıdır. Aşağıdaki istekte telefon alanı bilinçli olarak null gönderiliyor ve sunucu kaynağı bu temsille değiştiriyor. Telefon alanını hiç yazmasaydınız sonuç yine aynı olurdu, çünkü PUT gövdesinde olmayan bilgi yeni durumda da yoktur.

http
PUT /kullanicilar/42 HTTP/1.1
Host: api.ornek.com
Content-Type: application/json

{"ad": "Ayşe Kaya", "eposta": "ayse@ornek.com", "telefon": null, "rol": "editor"}

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

{"id": 42, "ad": "Ayşe Kaya", "eposta": "ayse@ornek.com", "telefon": null, "rol": "editor"}

RFC 9110'a göre PUT mevcut bir temsili başarıyla değiştirdiğinde sunucu 200 OK ya da 204 No Content döner; hedefte henüz bir temsil yoksa ve PUT onu oluşturduysa 201 Created dönmek zorundadır. Burada önemli bir tasarım kararı saklıdır: PUT'un yeni kaynak oluşturabilmesi için istemcinin hedef URI'yi önceden bilmesi gerekir. RFC 9110, istemci adına uygun URI'yi sunucunun seçtiği durum değiştiren işlemlerin PUT yerine POST ile yapılmasını önerir. Kimliği veritabanının ürettiği bir /kullanicilar koleksiyonunda yeni kayıt POST ile açılır; PUT ise yalnızca var olan kaynağı değiştirir ve kaynak yoksa 404 Not Found döner. Kimliği istemcinin belirlediği kaynaklarda (ör. /ayarlar/tema gibi adı belli bir ayar) PUT ile oluşturma doğal bir seçimdir. Koleksiyon ve tekil kaynak uç noktalarının (endpoint) tamamı için CRUD endpoint tasarımı yazısına bakın.

PUT'un bir başka sonucu da sunucunun gelen temsili kaynağın kısıtlarıyla tutarlı olup olmadığını denetlemesidir. RFC 9110, temsil hedef kaynakla uyuşmuyorsa sunucunun ya onu uygun hale getirmesini ya da nedenini açıklayan bir hata dönmesini ister; önerilen kodlar 409 Conflict ve içerik tipine özgü kısıtlar için 415 Unsupported Media Type'dır. Ayrıca sunucunun PUT gövdesinde tanımadığı başlık alanlarını kaynağın parçası olarak saklamaması gerekir.

PATCH: yalnızca değişikliği göndermek

PATCH isteğinde gövdenin ne anlama geldiğini Content-Type başlığındaki yama medya tipi belirler. RFC 5789 birkaç kuralı zorunlu kılar. Birincisi atomikliktir: sunucu yama belgesindeki değişikliklerin tamamını birlikte uygulamalı, yarım kalmış bir hali hiçbir zaman göstermemelidir; belgenin tamamı uygulanamıyorsa hiçbir değişiklik yapılmamalıdır. İkincisi uygunluktur: sunucu gelen yama biçiminin o kaynak türü için anlamlı olduğundan emin olmalıdır. Üçüncüsü, PATCH hedef kaynağın dışında yan etkiler doğurabilir; bir yama başka kaynakların oluşmasına veya değişmesine yol açabilir.

JSON tabanlı bir API için RFC olarak yayımlanmış iki yama biçimi vardır: kaynağın kendisine benzeyen JSON Merge Patch ve işlem listesi olan JSON Patch. İkisi de PATCH metodu için tasarlanmıştır ama farklı ihtiyaçlara cevap verir.

JSON Merge Patch (RFC 7396)

Merge Patch belgesi, değiştirmek istediğiniz alanları hedef belgedeki yapıyla aynı şekilde yazdığınız bir JSON nesnesidir ve application/merge-patch+json medya tipiyle gönderilir. Kuralları kısadır: hedefte olmayan bir üye yamada varsa eklenir, varsa değeri değiştirilir, değeri null olan üye ise hedeften silinir. İç içe nesnelerde aynı kurallar özyinelemeli olarak uygulanır.

http
PATCH /kullanicilar/42 HTTP/1.1
Host: api.ornek.com
Content-Type: application/merge-patch+json

{"rol": "admin", "telefon": null}

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

{"id": 42, "ad": "Ayşe Kaya", "eposta": "ayse@ornek.com", "rol": "admin"}

RFC 7396 işleyişi kısa bir sözde kodla verir. Aşağıdaki Python fonksiyonu bu sözde kodun birebir karşılığıdır ve üç önemli davranışı gösterir: iç içe adres nesnesinde yalnızca ilce değişir, telefon silinir ve dizi olan etiketler kısmen değil bütünüyle değiştirilir.

python
import json

def merge_patch(hedef, yama):
    # RFC 7396 Bölüm 2'deki MergePatch sözde kodunun Python karşılığı
    if isinstance(yama, dict):
        if not isinstance(hedef, dict):
            hedef = {}
        sonuc = dict(hedef)
        for ad, deger in yama.items():
            if deger is None:
                sonuc.pop(ad, None)
            else:
                sonuc[ad] = merge_patch(sonuc.get(ad), deger)
        return sonuc
    return yama

kullanici = {
    "ad": "Ayşe Kaya",
    "telefon": "+90 555 000 00 00",
    "adres": {"il": "İzmir", "ilce": "Bornova"},
    "etiketler": ["yeni", "kurumsal"],
}
yama = {"telefon": None, "adres": {"ilce": "Karşıyaka"}, "etiketler": ["kurumsal"]}

bir = merge_patch(kullanici, yama)
print(json.dumps(bir, ensure_ascii=False))
# çıktı: {"ad": "Ayşe Kaya", "adres": {"il": "İzmir", "ilce": "Karşıyaka"}, "etiketler": ["kurumsal"]}

iki = merge_patch(bir, yama)
print(iki == bir)
# çıktı: True

print(merge_patch(kullanici, ["tamamen", "yeni"]))
# çıktı: ['tamamen', 'yeni']

Son satır, standardın açıkça belirttiği bir kenar durumudur: yama nesne değilse sonuç her zaman hedefin tamamen yamayla değiştirilmesidir. Merge Patch'in iki sınırı vardır. Diziler parça parça değiştirilemez; listeye tek bir öğe eklemek için bile dizinin tamamını göndermeniz gerekir. Ayrıca null silme anlamı taşıdığı için bir alanın değerini gerçekten null yapamazsınız. RFC 7396 bu nedenle biçimin, yapısında ağırlıklı olarak nesne kullanan ve açık null değerlere ihtiyaç duymayan belgeler için uygun olduğunu söyler.

JSON Patch (RFC 6902)

JSON Patch ise application/json-patch+json medya tipiyle gönderilen bir işlem dizisidir. Her nesnede tam olarak bir op ve bir path bulunur; op değeri add, remove, replace, move, copy veya test olabilir. path bir JSON Pointer ifadesidir ve dizinin sonuna eklemek için - karakteri kullanılır. İşlemler sırayla uygulanır, her işlemin sonucu bir sonrakinin hedefi olur.

http
PATCH /kullanicilar/42 HTTP/1.1
Host: api.ornek.com
Content-Type: application/json-patch+json
If-Match: "v7"

[
  {"op": "test", "path": "/rol", "value": "editor"},
  {"op": "replace", "path": "/rol", "value": "admin"},
  {"op": "remove", "path": "/telefon"},
  {"op": "add", "path": "/etiketler/-", "value": "vip"}
]

Buradaki test işlemi JSON Patch'i Merge Patch'ten ayıran en kullanışlı araçtır: rol hâlâ editor değilse değerlendirme durur ve RFC 5789'un atomiklik kuralı gereği belgedeki hiçbir değişiklik uygulanmaz. RFC 6902 de bir işlem başarısız olursa yama belgesinin bütününün başarılı sayılmayacağını belirtir. remove ve replace için hedef konumun var olması gerekir; add ise yeni üye ekleyebilir ama üst nesnenin var olmasını şart koşar.

KarşılaştırmaJSON Merge PatchJSON Patch
Medya tipiapplication/merge-patch+jsonapplication/json-patch+json
GövdeHedefe benzeyen JSON nesnesiİşlem nesnelerinden oluşan dizi
Alan silmeDeğeri null yapmakremove işlemi
Dizide tek öğe değiştirmeMümkün değil, dizi bütünüyle gönderiliradd, remove, replace ile indeksle
Değeri null yapmaMümkün değilreplace ile mümkün
Koşul denetimiYoktest işlemi
OkunabilirlikYüksek, kaynağa benzerDaha teknik, işlem odaklı

İdempotentlik farkı neden önemli

RFC 9110'a göre bir metodun idempotent olması, aynı isteğin birden çok kez gönderilmesinin sunucu üzerindeki amaçlanan etkisinin tek bir istekle aynı olması demektir. PUT bu sınıftadır: aynı tam temsili üç kez gönderirseniz kaynak üç kez de aynı hale gelir. RFC 5789 ise PATCH'in ne güvenli ne de idempotent olduğunu söyler; yine de bir PATCH isteğinin idempotent olacak şekilde düzenlenebileceğini ekler; bu, aynı kaynağa yakın zamanda gelen iki PATCH'in çakışmasından doğan kötü sonuçları önlemeye de yardım eder.

Farkı somutlaştırmak için iki biçime bakın. Yukarıdaki Python örneğinde aynı Merge Patch belgesini ikinci kez uygulamak sonucu değiştirmedi; değer atayan bir Merge Patch pratikte idempotent davranır. JSON Patch'teki {"op": "add", "path": "/etiketler/-", "value": "vip"} işlemi ise her uygulamada dizinin sonuna yeni bir öğe ekler:

json
{
  "ilk_hal": {"etiketler": ["kurumsal"]},
  "bir_kez_uygulandi": {"etiketler": ["kurumsal", "vip"]},
  "iki_kez_uygulandi": {"etiketler": ["kurumsal", "vip", "vip"]}
}

Bu farkın gerçek hayattaki karşılığı yeniden denemedir. RFC 9110, bağlantı yanıt okunmadan koparsa idempotent isteklerin otomatik olarak tekrarlanabileceğini, idempotent olmayan isteklerin ise istemcinin bunu güvenle bilebileceği bir yol olmadan otomatik tekrarlanmaması gerektiğini söyler. Ağ hatası sonrası PUT'u tekrar göndermek güvenlidir; dizi sonuna ekleyen bir PATCH'i tekrar göndermek ise veriyi çoğaltabilir. Böyle işlemleri güvenle tekrarlamak için Idempotency-Key başlığı gibi bir mekanizmaya veya koşullu isteklere ihtiyaç duyarsınız.

FastAPI ile PUT ve Merge Patch uygulaması

Aşağıdaki örnek, iki metodu Python'un FastAPI çatısıyla yan yana kurar. Veritabanı yerine bellek içi bir sözlük kullanılır. PUT uç noktası tam bir Pydantic modeli bekler; PATCH uç noktası ise ham gövdeyi okur, Content-Type değerini denetler, yamayı mevcut kayda uygular ve ortaya çıkan sonucu yine tam modelle doğrular. Bu son adım önemlidir: tek tek alanlar geçerli olsa bile yamanın uygulanmış hali geçersiz bir kaynak üretebilir.

python
import json
from fastapi import FastAPI, HTTPException, Request
from fastapi.testclient import TestClient
from pydantic import BaseModel, ValidationError

def merge_patch(hedef, yama):
    if isinstance(yama, dict):
        sonuc = dict(hedef) if isinstance(hedef, dict) else {}
        for ad, deger in yama.items():
            if deger is None:
                sonuc.pop(ad, None)
            else:
                sonuc[ad] = merge_patch(sonuc.get(ad), deger)
        return sonuc
    return yama

class Kullanici(BaseModel):
    ad: str
    eposta: str
    telefon: str | None = None
    rol: str

app = FastAPI()
# Örnek için bellek içi sözlük; gerçek uygulamada veritabanı kullanılır.
db = {42: {"ad": "Ayşe Kaya", "eposta": "ayse@ornek.com", "telefon": "+90 555 000 00 00", "rol": "editor"}}

@app.put("/kullanicilar/{kid}")
def degistir(kid: int, govde: Kullanici):
    if kid not in db:
        # Bu API'de kimliği sunucu üretir, PUT ile yeni kayıt açılmaz.
        raise HTTPException(status_code=404, detail="Kullanıcı bulunamadı")
    db[kid] = govde.model_dump()          # gönderilmeyen alan varsayılan değerine döner
    return {"id": kid, **db[kid]}

@app.patch("/kullanicilar/{kid}")
async def yamala(kid: int, istek: Request):
    if istek.headers.get("content-type") != "application/merge-patch+json":
        raise HTTPException(status_code=415, detail="Desteklenmeyen yama biçimi",
                            headers={"Accept-Patch": "application/merge-patch+json"})
    if kid not in db:
        raise HTTPException(status_code=404, detail="Kullanıcı bulunamadı")
    try:
        yama = json.loads(await istek.body())
    except json.JSONDecodeError:
        raise HTTPException(status_code=400, detail="Yama belgesi geçerli JSON değil")
    try:
        yeni = Kullanici(**merge_patch(db[kid], yama))   # sonucu tam modelle doğrula
    except (ValidationError, TypeError):
        raise HTTPException(status_code=422, detail="Yama sonrası kaynak geçersiz olur")
    db[kid] = yeni.model_dump()
    return {"id": kid, **db[kid]}

c = TestClient(app)
MP = {"Content-Type": "application/merge-patch+json"}

r = c.put("/kullanicilar/42", json={"ad": "Ayşe Demir"})
print(r.status_code, [e["loc"] for e in r.json()["detail"]])
# çıktı: 422 [['body', 'eposta'], ['body', 'rol']]

r = c.put("/kullanicilar/42", json={"ad": "Ayşe Demir", "eposta": "ayse@ornek.com", "rol": "editor"})
print(r.status_code, r.json())
# çıktı: 200 {'id': 42, 'ad': 'Ayşe Demir', 'eposta': 'ayse@ornek.com', 'telefon': None, 'rol': 'editor'}

r = c.patch("/kullanicilar/42", content='{"rol": "admin"}', headers=MP)
print(r.status_code, r.json())
# çıktı: 200 {'id': 42, 'ad': 'Ayşe Demir', 'eposta': 'ayse@ornek.com', 'telefon': None, 'rol': 'admin'}

r = c.patch("/kullanicilar/42", json={"rol": "admin"})
print(r.status_code, r.headers["accept-patch"], r.json())
# çıktı: 415 application/merge-patch+json {'detail': 'Desteklenmeyen yama biçimi'}

r = c.patch("/kullanicilar/42", content='{"ad": null}', headers=MP)
print(r.status_code, r.json())
# çıktı: 422 {'detail': 'Yama sonrası kaynak geçersiz olur'}

r = c.patch("/kullanicilar/42", content='{"rol": ', headers=MP)
print(r.status_code, r.json())
# çıktı: 400 {'detail': 'Yama belgesi geçerli JSON değil'}

Çıktıları sırayla okuyalım. Yalnızca ad içeren PUT, FastAPI'nin otomatik doğrulamasında takılır ve eksik iki alanın konumu 422 yanıtında listelenir; böylece kısmi PUT sessizce veri silmek yerine reddedilmiş olur. Telefonu içermeyen ama zorunlu alanları içeren ikinci PUT başarılıdır ve telefon None olur: kaynak gönderilen temsille değişti. PATCH ise yalnızca rolü değiştirir, diğer alanlara dokunmaz.

Dördüncü istek application/json tipiyle geldiği için 415 alır ve yanıttaki Accept-Patch başlığı istemciye hangi biçimi kullanması gerektiğini söyler. Beşinci istek sözdizimi olarak geçerli bir yamadır ama zorunlu ad alanını sildiği için kaynağı geçersiz bırakırdı; bu yüzden 422 döner ve atomiklik kuralına uygun olarak kayıt değişmez. Son istek bozuk JSON gönderdiği için 400 alır. Bu örnekte hatalar FastAPI'nin varsayılan {"detail": ...} biçiminde dönüyor; üretimde bunları tek bir biçimde toplamak için Problem Details (RFC 9457) yazısına bakın.

PATCH hata durumları ve durum kodları

PATCH hata durumları ve durum kodları: Bozuk yama belgesi, Desteklenmeyen yama biçimi, İşlenemeyen istek, Kaynak yok

RFC 5789, PATCH isteklerinin başarısız olabileceği bilinen durumları ve bunlar için uygun kodları sıralar. Bu liste, bir PATCH uç noktası tasarlarken hangi hatayı ayrı ele almanız gerektiğini gösteren iyi bir kontrol listesidir:

DurumKodAçıklama
Bozuk yama belgesi400 Bad RequestBelge seçilen biçime göre düzgün yazılmamış
Desteklenmeyen yama biçimi415 Unsupported Media TypeYanıtta Accept-Patch ile desteklenen biçimler bildirilir
İşlenemeyen istek422 Unprocessable ContentBelge geçerli ama uygulanınca kaynak geçersiz olur
Kaynak yok404 Not FoundYama var olmayan kaynağa uygulanamıyor
Çakışan durum409 ConflictYamanın varsaydığı yapı kaynakta yok
Çakışan değişiklik (ön koşullu)412 Precondition FailedIf-Match gibi ön koşul tutmadı
Çakışan değişiklik (ön koşulsuz)409 ConflictSunucu çakışmayı kendisi fark etti

RFC 5789 bu kodu hâlâ eski adıyla "422 Unprocessable Entity" olarak anar; RFC 9110 aynı kodun adını "422 Unprocessable Content" olarak güncelledi. Desteklenmeyen biçim yanıtı Problem Details gövdesiyle şöyle görünebilir:

http
HTTP/1.1 415 Unsupported Media Type
Accept-Patch: application/merge-patch+json, application/json-patch+json
Content-Type: application/problem+json

{"type": "about:blank", "title": "Unsupported Media Type", "status": 415, "detail": "Bu kaynak için desteklenen yama biçimleri Accept-Patch başlığında listelenmiştir."}

Sunucu PATCH desteğini önceden de duyurabilir. RFC 5789'a göre OPTIONS yanıtındaki Allow başlığına PATCH eklenir ve Accept-Patch başlığı kabul edilen biçimleri listeler. Herhangi bir yanıtta Accept-Patch bulunması, o kaynakta PATCH'e izin verildiğinin dolaylı bir işaretidir.

http
OPTIONS /kullanicilar/42 HTTP/1.1
Host: api.ornek.com

HTTP/1.1 200 OK
Allow: GET, PUT, PATCH, DELETE, OPTIONS
Accept-Patch: application/merge-patch+json

Eşzamanlı güncellemeler: If-Match ile koruma

İki istemci aynı kaynağı aynı anda değiştirmeye çalıştığında PATCH, PUT'tan daha riskli olabilir. RFC 5789 bunun nedenini açıklar: bazı yama biçimleri bilinen bir başlangıç noktasına göre çalışır ve kaynak arada değiştiyse onu bozabilir. Örneğin dizinin üçüncü öğesini silen bir JSON Patch, başka biri araya öğe eklediyse yanlış öğeyi siler. Bu tür biçimleri kullanan istemcilerin koşullu istek göndermesi beklenir; tipik yöntem son okunan sürümün güçlü ETag değerini If-Match başlığında göndermektir. Kaynak o arada değiştiyse sunucu 412 Precondition Failed döner. Değer atayan bir Merge Patch bu açıdan daha az kırılgandır ama son yazanın kazanması sorunu her iki metotta da vardır. ETag üretimi ve koşullu isteklerin ayrıntısı için Cache-Control, ETag ve koşullu istekler yazısına bakın.

Hangisini ne zaman kullanmalı

Hangisini ne zaman kullanmalı: İstemci kaynağın tamamını zaten tutuyor ve düzenleyip geri gönderiyorsa (ör. bir ayar formunun tamamı)..., JSON Merge Patch, JSON Patch, POST
  • PUT: İstemci kaynağın tamamını zaten tutuyor ve düzenleyip geri gönderiyorsa (ör. bir ayar formunun tamamı). Tekrar denemenin kendiliğinden güvenli olması istendiğinde.
  • JSON Merge Patch: Birkaç alanı değiştiren basit güncellemeler, nesne ağırlıklı ve açık null değeri olmayan kaynaklar. Okunması ve elle yazılması en kolay biçimdir.
  • JSON Patch: Dizilerde tek öğe ekleme veya silme, değeri gerçekten null yapma, "şu değer hâlâ buysa değiştir" gibi koşullu değişiklikler.
  • POST: RFC 5789, işlem hedef kaynağı öngörülebilir biçimde değiştirmiyorsa PUT veya PATCH yerine POST'un düşünülmesini söyler. "Siparişi iptal et" gibi bir iş akışı tetikleyen işlemler bu gruba girer. Toplu güncellemeler için toplu işlem (batch) endpoint yazısına bakın.

RFC 5789 boyutla ilgili pratik bir not da düşer: yama belgesi kaynağın kendisinden büyük olacaksa PUT kullanmak daha mantıklı olabilir. Bir API'de iki metodu birlikte sunmak yaygın bir tercihtir; önemli olan her uç noktanın davranışını belgelemek ve PATCH için kabul edilen medya tiplerini açıkça yazmaktır.

Sık yapılan hatalar

  • PATCH'i sessizce PUT gibi işlemek: Gelen gövdeyi doğrudan kaydın yerine yazmak, gönderilmeyen alanları siler. PATCH'te mevcut kaydı okuyup yamayı onun üzerine uygulamak gerekir.
  • Yama sonrası sonucu doğrulamamak: Her alan tek başına geçerli olsa bile birleşmiş kaynak geçersiz olabilir. Doğrulamayı yamanın uygulanmış haline yapın.
  • Kısmen uygulamak: Beş değişiklikten üçünü yazıp dördüncüde hata vermek RFC 5789'un atomiklik kuralına aykırıdır. Ya hepsi ya hiçbiri.
  • Medya tipini önemsememek: Merge Patch ve JSON Patch aynı uç noktaya gelebilir ve anlamları tamamen farklıdır. Content-Type değerini denetleyin, tanımadığınız biçime 415 dönün.
  • Null anlamını belirsiz bırakmak: Merge Patch'te null silmek demektir. "Alanı boşalt" ile "alanı sil" arasındaki farkı belgelemezseniz istemciler farklı yorumlar.
  • PATCH'i kör yeniden denemek: Ağ hatasında PATCH'i otomatik tekrarlayan bir istemci, dizi sonuna ekleme gibi işlemleri çoğaltabilir.

Sık Sorulan Sorular

PATCH gövdesinde düz application/json gönderebilir miyim?

Teknik olarak sunucunuz bunu kabul edecek şekilde yazılabilir, ancak bu durumda gövdenin nasıl yorumlanacağı yalnızca sizin belgenize bağlı kalır. RFC 5789 yama belgesinin bir medya tipiyle tanımlanmasını öngördüğü için application/merge-patch+json veya application/json-patch+json kullanmak, istemcinin ve sunucunun aynı kuralları uyguladığını garanti eder.

PUT ile kaynak oluşturmak doğru mu?

RFC 9110 buna izin verir; kaynak yoksa ve PUT onu oluşturduysa sunucu 201 Created dönmelidir. Bunun için istemcinin URI'yi bilmesi gerekir. Kimliği sunucunun ürettiği koleksiyonlarda oluşturma için POST kullanılır.

PATCH yanıtında gövde dönmeli miyim?

Zorunlu değil. RFC 5789'daki örnek yanıt gövdesiz 204 No Content kullanır ve başka başarı kodlarının da kullanılabileceğini belirtir. Güncel kaynağı 200 OK ile döndürmek, istemcinin ikinci bir GET yapmasını gereksiz kılar; hangisini seçtiyseniz tüm uç noktalarda aynı davranın.

Merge Patch ile bir diziye tek öğe nasıl eklenir?

Eklenemez; Merge Patch dizileri bütün olarak değiştirir. Dizinin yeni halinin tamamını gönderirsiniz veya bu işlem için JSON Patch'in add işlemini /etiketler/- yoluyla kullanırsınız.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: REST API tasarımı öğrenme rehberi · CRUD endpoint tasarımı · Idempotency-Key kullanımı · Toplu işlem endpoint · Problem Details hata yanıtı · HTTP metotları · ETag ve koşullu istekler