Bir kaynak bulunamadığında 204 veya 404 yanıtı döndürmeli miyim?


15

Turnuvalar ve programlar için basit bir RESTful hizmeti geliştiriyorum. JSON gövdesi içeren bir POST isteği ile bir turnuva oluşturulduğunda, turnuva BiMapbir DAO uygulamasında aşağıdaki gibi ilan edilen bir a'ya eklenir :

private BiMap<String, Tournament> tournaments = Maps.synchronizedBiMap(HashBiMap.create());

Bir turnuva oluşturulduğunda, kullanıcının bu turnuvanın ileride referansını alabilmesi için ilişkili dize kimliği döndürülür . Aşağıdaki talebi yerine getirerek yeni turnuvadan bilgi alabilir:

GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39

Peki böyle bir kimliğe sahip turnuva bulunmazsa ne olur? Şimdiye kadar 204 yanıtı geri gönderiyorum. Jersey, nullyöntemlerinden birinden dönerken bunu benim için yapıyor . Bu, yukarıdaki rotaya karşılık gelen yöntemdir:

@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Tournament getTournament(@PathParam("id") String id) {
    Optional<Tournament> optTournament = tournamentDao.getTournament(id);
    if (optTournament.isPresent())
        return optTournament.get();
    return null;
}

Sorum şu: Bir 204: No Contentyanıt döndürmek uygun 404mu yoksa kaynak bulunamadığı için bunun bir yanıt olması mı gerekiyor?

Bunu 404, açık bir soru olarak değiştirirsem: Yöntem imzasını doğru değiştirmeli miyim? Şimdi (tür Tournament) bir turnuva iade edilmeyebileceğinden, yöntem farklı görünmelidir. Bunun Responseyerine türü dönüş türü olarak mı kullanmalıyım?

Yanıtlar:


32

HTTP 204bir şey bulundu demek , ama boş. Örneğin, günlük dosyalarını http://example.com/logs/[date-goes-burat] gibi isteklerle HTTP üzerinden sunduğunuzu düşünün . 18 Mayıs 2015'te:

  • http://example.com/logs/2015-05-19 dönecekti HTTP 404, yani günlük yok, çünkü geleceği günlüğe kaydetmek zor.

  • http://example.com/logs/2015-05-18 , ya HTTP 200yanıtın içeriğindeki günlük girişleriyle ya HTTP 204da günlük dosyası oluşturulduysa, ancak bunun için henüz kaydedilmiş bir günlük yoksa dönecektir. tarihi.

Eğer sağlarsanız nullbir isteğe yanıt olarak çerçeveye, bu bir girdi bulduğunu varsayar ve bu girişin dolayısıyla boş HTTP 204. Bunun yerine, throw new NotFoundException();girişin mevcut olmadığını, böylece bir a oluşturacağını belirtmeniz gerekir HTTP 404.

Eğer 404, açık bir soru olarak değiştirmeliyim: Yöntem imzasını doğru değiştirmeli miyim?

Hayır. Bu güzel bir şey throw new NotFoundException();. Yönteminizin gerçek dönüş türü ne olursa olsun çalışır.


5
RFC 2616'ya özellikle dikkat edin . 204 yanıtlar yalnızca ileti gövdesini tamamen atlıyorsanız spesifikasyonlarla uyumludur. Bir dereceye kadar, 204 yanıtının anlamı, "hayır, içerik döndürmem bir kaza değildir" demek. MainMa'nın örneğini genişletmek için: Bir günlük arama aracı metin dosyalarını tükürürse (örneğin, günlük dosyalarını olduğu gibi dağıtan günlük dosyalarının etrafındaki ince bir sarıcı), boş bir günlük dosyası için 204 uygun olur. Yanıt boş bir JSON nesnesi (ör. {content: ''}) Olsaydı, 204 yanıtı uygunsuz olurdu.
Brian

" Çünkü, geleceği kaydetmek zordur. " - Bu bit keyfi bir tarihe bağlıdır; neden okuyucunun bugün olmadığı gibi davranmasını gerektirmeyen bir şey yapmıyorsunuz? Belki de kullanmak 2015-02-29daha iyi olurdu, çünkü hiç var olmayan bir tarih?
Monica'nın Davası


1

Talebiniz GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39.

Bir http://localhost:8080/eventscheduler/bitiş noktası yoksa, bir 404 döndürmelisiniz. Varolmayan bir kaynağa ( /eventscheduler/) erişmeye çalışıyorsunuz . Bu, istemciye bir sunucunun var olduğunu gösterir localhost:8080, ancak eventscheduleruç noktada hiçbir şey yoktur .

Eğer http://localhost:8080/eventscheduler/bir son nokta olarak var ancak gerekli kaynaklar kullanılamaz, bir 5xx hata uygundur. Buna iyi bir örnek, 503'ü döndürebileceğiniz bir veritabanı çevrimdışıysa, elbette, belirli bir örnek yerine genel bir 500 hatası döndürmek isteyebilirsiniz.

Varsa http://localhost:8080/eventscheduler/ancak temsil edilen şey c15268ce-474a-49bd-a623-b0b865386f39mevcut değilse, ayrıntıları gösteren bir gövdeye sahip bir 200 döndürürüm. Son nokta var, yapılan istek tamamen geçerli ve işlenebilir, ancak eşleşme yoktu.

Müşterinizin uç noktaya talebi geçerli değilse, diğer 4xx hatalarına bakarsınız. İstemcinin 401 veya 403 ile istenen uç noktaya veya öğelere erişme yetkisi olmadığını veya isteğin geçersiz olduğunu belirtmek için 400'ü kullanabilirsiniz. Bunlardan herhangi biri ile, yanıt gövdesinde ek bilgi sağlanabilir.


Uç nokta ile kaynak arasında ayrım yapmaya gerek yoktur. URI herhangi bir kaynakla eşleşmezse, ne olursa olsun, sunucu
404'ü

Doğru şeyi yapan bir site örneği için bu sitedeki yanıt kodunu kontrol edin. Bu bir web sitesi, bir API değil, aynı http özelliği de geçerli. softwareengineering.stackexchange.com/questions/266183385
BDSL

@bdsl Bunun yanlış olduğunu söyleyebilirim. Örneğin, kullanıcı profili döndürebilen bir kullanıcı hizmetiyle etkileşime giriyorum. Diyelim ki bu uç nokta şöyle /userve kullanılıyor /user?email=test@example.com. Bir API tüketicisi olarak, /userherhangi bir nedenle sunucuda bulunup bulunmadığını (API'nin v2'sine eklenmiş ve sunucu v1'de mi yoksa v3'te yeniden adlandırılmışsa) veya e-postaya sahip kullanıcı olup olmadığını bilmek istiyorum test@example.commevcut değil. Birincisi 404, ikincisi 200 ve bu e-posta adresine sahip bir kullanıcıyı gösteren bir gövdeye sahip.
Thomas Owens

@bdsl Bu güzel, ama bu doğru ya da en iyi olduğu anlamına gelmiyor. Ayrıca, bir web sisteminde insan etkileşimi için tasarlanmış bir web sitesini bir yazılım sisteminde kullanılmak üzere tasarlanmış bir API ile karşılaştırabileceğinizi de düşünmüyorum.
Thomas Owens

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.