Haruskah saya mengembalikan respons 204 atau 404 ketika sumber daya tidak ditemukan?

15

Saya mengembangkan layanan RESTful sederhana untuk turnamen dan jadwal. Ketika sebuah turnamen dibuat melalui permintaan POST yang berisi badan JSON, turnamen tersebut dimasukkan ke dalam BiMap, dinyatakan sebagai berikut dalam implementasi DAO:

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

Ketika sebuah turnamen dibuat, id string yang terkait dikembalikan sehingga pengguna dapat memiliki referensi di masa depan dari turnamen itu. Ia dapat memperoleh informasi kembali dari turnamen baru dengan melakukan permintaan berikut:

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

Tetapi bagaimana jika tidak ada turnamen dengan id seperti itu ditemukan? Sejauh ini, saya mengembalikan respons 204. Nah, Jersey melakukannya untuk saya ketika kembali nulldari salah satu metodenya. Ini adalah metode yang sesuai dengan rute di atas:

@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;
}

Pertanyaan saya adalah: apakah 204: No Contentboleh mengembalikan jawaban, atau haruskah itu 404balasan, karena sumber daya tidak ditemukan?

Jika saya harus mengubahnya ke 404, pertanyaan yang jelas: Saya harus mengubah metode tanda tangan kan? Karena sekarang turnamen (tipe Tournament) mungkin tidak dikembalikan, metodenya akan terlihat berbeda. Saya harus menggunakan Responsetipe sebagai jenis kembali bukan?

dabadaba
sumber

Jawaban:

32

HTTP 204berarti bahwa sesuatu itu ditemukan, tapi itu kosong. Misalnya, bayangkan Anda menyajikan file log melalui HTTP, dengan permintaan seperti http://example.com/logs/[date-goes-here] . Pada 18 Mei 2015:

Jika Anda memberikan nullkerangka kerja sebagai respons terhadap permintaan, itu mengasumsikan bahwa Anda menemukan entri, dan entri ini kosong HTTP 204. Sebagai gantinya, Anda harus throw new NotFoundException();menunjukkan kepada kerangka kerja bahwa entri tidak ada, sehingga akan menghasilkan a HTTP 404.

Jika saya harus mengubahnya ke 404, pertanyaan yang jelas: Saya harus mengubah metode tanda tangan kan?

Tidak, tidak. Itu hal yang baik tentang throw new NotFoundException();. Ini akan berfungsi apa pun jenis pengembalian aktual metode Anda.

Arseni Mourzenko
sumber
5
Perhatikan RFC 2616 . 204 tanggapan hanya sesuai dengan spesifikasi jika Anda menghilangkan seluruh isi pesan. Sampai batas tertentu, inti dari tanggapan 204 adalah mengatakan, "tidak, itu bukan kebetulan bahwa saya tidak mengembalikan konten." Untuk memperluas contoh MainMa: Jika alat pencarian log meludahkan file teks (misalnya, pembungkus tipis di sekitar file log yang hanya memuntahkan file log apa adanya), 204 akan sesuai untuk file log kosong. Jika responsnya adalah objek JSON kosong (misalnya, {content: ''}), respons 204 akan tidak pantas.
Brian
" karena, yah, sulit untuk mencatat masa depan. " - Bit ini tergantung pada tanggal arbitrer; mengapa tidak menjadikannya sesuatu yang tidak mengharuskan pembaca untuk berpura-pura tidak hari ini? Mungkin menggunakan 2015-02-29akan lebih baik, karena itu kencan yang tidak ada sama sekali?
Dana Gugatan Monica
1

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

Jika http://localhost:8080/eventscheduler/tidak ada sebagai titik akhir, Anda harus mengembalikan 404. Anda mencoba mengakses sumber daya ( /eventscheduler/) yang tidak ada. Ini akan menunjukkan kepada klien bahwa server ada localhost:8080, tetapi tidak ada di eventschedulertitik akhir.

Jika http://localhost:8080/eventscheduler/ada sebagai titik akhir tetapi sumber daya yang diperlukan tidak tersedia, kesalahan 5xx tepat. Contoh yang baik dari ini adalah jika database sedang offline, di mana Anda bisa mengembalikan 503. Tentu saja, Anda mungkin hanya ingin mengembalikan kesalahan 500 generik daripada contoh khusus.

Jika http://localhost:8080/eventscheduler/ada tetapi hal yang diwakili oleh c15268ce-474a-49bd-a623-b0b865386f39tidak ada, saya akan mengembalikan 200 dengan badan yang menunjukkan rincian. Titik akhir ada, permintaan yang dibuat benar-benar valid dan dapat diproses, tetapi tidak ada kecocokan.

Jika permintaan klien Anda ke titik akhir tidak valid, Anda akan melihat kesalahan 4xx lainnya. Anda dapat menunjukkan bahwa klien tidak berwenang untuk mengakses titik akhir atau item yang diminta dengan 401 atau 403 atau dapat menggunakan 400 untuk menunjukkan bahwa permintaan tersebut tidak valid. Dengan semua ini, informasi tambahan dapat diberikan di badan respons.

Thomas Owens
sumber
Tidak perlu membedakan antara titik akhir dan sumber daya. Jika URI tidak cocok dengan sumber daya apa pun, untuk alasan apa pun, server harus mengembalikan 404.
bdsl
Periksa kode respons di situs ini untuk contoh situs yang melakukan hal yang benar. Ini situs web, bukan API, tetapi spesifikasi http yang sama berlaku. softwareengineering.stackexchange.com/questions/266183385
bdsl
@ sddsl saya dapat memberitahu Anda bahwa itu benar-benar salah. Misalnya, saya berinteraksi dengan layanan pengguna yang dapat mengembalikan profil pengguna. Katakanlah titik akhir ini adalah /userdan digunakan seperti /[email protected]. Sebagai konsumen API, saya ingin tahu apakah /userkarena alasan tertentu tidak ada di server (mungkin ditambahkan di v2 API dan server ada di v1 atau diubah namanya di v3) atau jika pengguna dengan email [email protected]tidak ada. Yang pertama adalah 404, yang kedua adalah 200 dengan tubuh yang menunjukkan tidak ada pengguna dengan alamat email itu.
Thomas Owens
@ bbdsl Bagus, tetapi itu tidak berarti itu benar atau terbaik. Saya juga tidak berpikir bahwa Anda dapat membandingkan situs web yang dirancang untuk interaksi manusia melalui browser web versus API yang dirancang untuk digunakan dalam sistem perangkat lunak.
Thomas Owens
1
Masalah ini dibahas lebih lanjut di youtube.com/watch?v=nSKp2StlS6s
bdsl