Soru Bir REST kaynağı bulunamadığı zaman 404'e dönmek doğru mu?


Aşağıdaki gibi basit bir Jersey REST kaynağım olduğunu varsayalım:

@Path("/foos")
public class MyRestlet
        extends BaseRestlet
{

    @GET
    @Path("/{fooId}")
    @Produces(MediaType.APPLICATION_XML)
    public Response getFoo(@PathParam("fooId") final String fooId)
            throws IOException, ParseException
    {
        final Foo foo = fooService.getFoo(fooId);

        if (foo != null)
        {
            return Response.status(Response.Status.OK).entity(foo).build();
        }
        else
        {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
    }

}

Yukarıdaki koda dayanarak, bir NOT_FOUND durum (404) ya da geri dönmeliyim 204veya başka bir daha uygun kod?

Şimdiden çok teşekkürler!


25
2017-11-10 14:05


Menşei




Cevaplar:


Bu durumda 404 yanıtı, API kullanıcılarının tüketmesi oldukça tipik ve kolaydır.

Bir problem, bir müşterinin bulunmayan bir varlıktan dolayı 404'e sahip olup olmadığının veya URI'daki yapısal bir problemden kaynaklanmasının zor olmasıdır. Örneğinde, /foos/5 ID = 5 olan foo bulunmadığından, 404 döndürülebilir. Ancak, /food/1 foo ile olsa bile 404 dönecekti id=1 var çünkü foos yanlış yazılmışsa). Başka bir deyişle, 404 ya kötü bir şekilde yapılandırılmış bir URI ya da var olmayan bir kaynağa referans anlamına gelir.

Başka bir sorun, birden fazla kaynağa başvuran bir URI'nız olduğunda ortaya çıkar. Basit bir 404 yanıtı ile, istemci, başvurulan kaynaklardan hangisinin bulunmadığını bilmez.

Bu problemlerin her ikisi de, arayan kişinin tam olarak neyin bulunamadığını bilmesini sağlamak için yanıt gövdesindeki ek bilgileri geri getirerek kısmen hafifletilebilir.


34
2017-11-10 14:17



Bunu eklemek istiyorum. /food/1 404 döndürüyor çünkü bu url mevcut değil, bu bir istemci hatasıdır (yanlış URL'ye girdi) ve bu nedenle sorun değil - Tim Castelijns
@TimCastelijns Müşterinin hatası olduğunu kabul ediyorum. Ancak, müşteri müşterinizse, o zaman sorun olur (telefonu açar ve birini ararlar). Müşterilerin API'yı çok fazla hayal kırıklığı yaşamadan kullanmasına yardımcı olabilirsek, hepimiz kazanırız. - Rob
Müşteriye doğru API dokümantasyonu sağladıysanız, kesinlikle onların hatası ;-) - Tim Castelijns


Evet, bulunamayan bir kaynak için 404'ü geri çevirmek oldukça yaygındır. Bir web sayfası gibi, bulunamadığı zaman, bir 404 elde edersiniz. Bu sadece REST değil, bir HTTP standardıdır.

Her kaynağın bir URL konumu olmalıdır. URL'lerin statik olması gerekmez, bunlar olabilir şablonlu. Bu nedenle, gerçek istenen URL'nin bir kaynağa sahip olmaması mümkün. Kaynağı aramak için URL'yi şablondan ayırmak sunucunun görevidir. Kaynak yoksa, o zaman "Bulunamadı"

İşte HTTP 1.1 özelliği

404 Bulunamadı

Sunucu, İstek URI'sı ile eşleşen hiçbir şey bulamadı. Durumun geçici mi yoksa kalıcı mı olduğuna dair bir gösterge verilmez. 410 (Gone) durum kodu, sunucu, bazı dahili olarak yapılandırılabilen bir mekanizma aracılığıyla, eski bir kaynağın kalıcı olarak kullanılamayacağını ve yönlendirme adresinin olmadığını bilmesi durumunda kullanılmalıdır. Bu durum kodu, sunucu isteğin neden reddedildiğini tam olarak açıklamak istemediğinde veya başka bir yanıt alınmadığında yaygın olarak kullanılır.


İşte 204 için

204 İçerik Yok

Sunucu, talebi yerine getirdi, ancak bir varlık-gövdesini iade etmeye gerek duymaz ve güncellenmiş geri dönüşüme dönmek isteyebilir. MAYIS, eğer mevcut ise, eğer var ise, talep edilen varyant ile ilişkilendirilmelidir.

İstemci bir kullanıcı aracısıysa, belge görünümünün isteğin gönderilmesine neden olandan değiştirmemesi GEREKMEKTEDİR. Bu yanıt, öncelikle kullanıcı aracısının etkin belge görünümünde herhangi bir değişikliğe neden olmadan eylemlerin girişine izin vermeyi amaçlamaktadır, ancak kullanıcı aracısının aktif görünümünde bulunan belgeye yeni veya güncelleştirilmiş bir raporlama yapılması GEREKİR.

204 cevabı, bir mesaj-gövdesi İÇERMEMELİDİR ve bu nedenle her zaman başlık alanlarından sonraki ilk boş satır ile sonlandırılmalıdır.

Normalde 204, bir temsil güncellendiğinde veya oluşturulduğunda ve bir yanıt gövdesi geri göndermeye gerek olmadığında kullanılır. Bir POST durumunda, yeni oluşturulan kaynağın yalnızca Konumunu geri gönderebilirsiniz. Gibi bir şey

@POST
@Path("/something")
@Consumes(...)
public Response createBuzz(Domain domain, @Context UriInfo uriInfo) {
    int domainId = // create domain and get created id
    UriBuilder builder = uriInfo.getAbsolutePathBuilder();
    builder.path(Integer.toString(domainId));  // concatenate the id.
    return Response.created(builder.build()).build();
}

created(URI) yanıtı yeni oluşturulan URI ile geri gönderecek Location başlığı.


İlk kısım ekleniyor. Bir istemciden gelen her isteğin, bir kaynaka erişme isteğidir, ister yalnızca GET için olsun, isterse de PUT ile güncelleştirin. Ve bir kaynak sunucuda herhangi bir şey olabilir. Kaynak yoksa, müşteriye o kaynağı bulamadığımızı söylemek genel bir cevap olacaktır.

Örneğinizi genişletmek için. Diyelimki FooService DB'yi etkinleştirir. Veritabanındaki her satır bir kaynak olarak kabul edilebilir. Ve bu satırların (kaynakların) her birinin, foo/db/1 Birincil anahtar 1 ile bir satırın yerini belirleyebilir. Kimlik bulunamazsa, o zaman kaynak olduğu "Bulunamadı"


17
2017-11-10 14:25



Cevabınız için teşekkürler! Oldukça geniş olduğu için harika. Her iki cevap da çok yardımcı oldu, ama maalesef sadece bir tane kabul edebiliyorum ... :( - carlspring
400'e ne dersin? - Belun
@Belun Neden 400? - Paul Samsotha
url bozuk => istek bozuk (400) - Belun
@Belun Mantıklı değil. Bir URL, kaynağın yerini gösterir. URL için kaynak bulunamazsa, uygun durum 404 "Bulunamadı" - Paul Samsotha


bir 4XX hata kodu, istemci tarafındaki hata anlamına gelir.
Resim veya html sayfası olarak statik kaynak isteğinde bulunduğunuzda, 404 tepki mantıklı:

HTTP 404 Bulunamadı istemcisi hata yanıt kodu,   Sunucu istenen kaynağı bulamıyor. 404’e giden bağlantılar   sayfa genellikle bozuk veya ölü bağlantılar olarak adlandırılır ve bağlantıya tabi olabilir   çürür.

Müşterilere bazı REST yöntemleri sunduğunuzdan, HTTP yöntemlerine güvenirsiniz, ancak REST hizmetlerini basit kaynaklar olarak düşünmemelisiniz.
İstemciler için, REST yöntemindeki bir hata yanıtı genellikle diğer işlemlerin hatalarına yakın olarak ele alınır.

Örneğin, REST çağrıları sırasında veya başka bir yerde hataları yakalamak için istemciler kullanabilir catchError() arasında RxJS.

Hata işlemeyi bir fonksiyona devretmek için bu şekilde bir kod yazabiliriz (örnek kod için TipScript / Açısal 2).

return this.http
  .get<Foo>("/api/foos")
  .pipe(
      catchError(this.handleError)
  )
  .map(foo => {...})

Sorun şu ki, herhangi bir HTTP hatası (5XX veya 4XXX) catchError() geri aramak.
İstemciler için yanıltıcı REST API yanıtlarını gerçekten yapabilir.

Programlama diliyle paralel bir şekilde yaparsak, istisna akışı olarak 5XX / 4XX'i düşünebiliriz.
Genel olarak, yalnızca bir veri bulunamadığı için bir istisna alamıyoruz. bir veri bulunamadı ve bu verilerin bulunabileceği gibi atıyoruz.
REST API için aynı mantığı takip etmeliyiz.

Varlık Mayıs ayı bulunamadı, geri dönüyor OK iki durumda da gayet iyi:

@GET
@Path("/{fooId}")
@Produces(MediaType.APPLICATION_XML)
public Response getFoo(@PathParam("fooId") final String fooId)
        throws IOException, ParseException {
    final Foo foo = fooService.getFoo(fooId);

    if (foo != null){
        return Response.status(Response.Status.OK).entity(foo).build();
    }

    return Response.status(Response.Status.OK).build();

}

Müşteri sonuca göre sonuca ulaşabilir veya mevcut olabilir.
Geri dönmeyi düşünmüyorum 204 herhangi bir yararlı değer getirir.
HTTP 204 belgeleme şunu belirtiyor:

İstemcinin mevcut sayfasından gitmesine gerek yok.

Ancak bir REST kaynağı ve daha özel olarak bir GET yöntemi talep etmek, müşterinin bir iş akışını sonlandırmakla ilgili olduğu anlamına gelmez (POST / PUT yöntemleri ile daha mantıklı).

Belge ayrıca şunları ekler:

Ortak kullanım durumu, bir PUT isteğinin sonucu olarak 204'ü iade etmektir.   Sayfanın mevcut içeriğini değiştirmeden bir kaynağı güncelleme   kullanıcıya gösterilir.

Bu durumda gerçekten değiliz.

REST API (201, 202, 401, vb.) İçin geri dönüş kodları ile birlikte klasik tarama matkabı için bazı özel HTTP kodları, ancak bu her zaman böyle değildir. Bu nedenle, orijinal kodları bükmekten ziyade, daha genel kodları kullanarak bunları basit tutmayı tercih ederim: 200, 400.


1
2018-03-18 18:18



@Downvoter, düşüncenizi paylaşabilir misiniz? Faydalı olabilir. - davidxxx