Buat permintaan dengan POST, yang merespons kode 200 atau 201 dan konten

125

Misalkan saya menulis layanan REST yang bertujuan untuk menambahkan item data baru ke sistem.

Saya berencana untuk POST ke

http://myhost/serviceX/someResources

Misalkan berhasil, kode respons apa yang harus saya gunakan? Dan konten apa yang mungkin saya kembalikan.

Saya melihat definisi kode respons HTTP dan melihat kemungkinan berikut:

200: Mengembalikan entitas yang mendeskripsikan atau berisi hasil dari tindakan;

201: yang artinya DIBUAT. Artinya * Permintaan telah dipenuhi dan menghasilkan sumber daya baru yang dibuat. Sumber daya yang baru dibuat dapat direferensikan oleh URI yang dikembalikan dalam entitas respons, dengan URI paling spesifik untuk sumber daya yang diberikan oleh bidang header Lokasi. Respons HARUS menyertakan entitas yang berisi daftar karakteristik sumber daya dan lokasi tempat pengguna atau agen pengguna dapat memilih salah satu yang paling sesuai. Format entitas ditentukan oleh jenis media yang diberikan di bidang header Jenis Konten. *

Yang terakhir terdengar lebih sesuai dengan spesifikasi Http, tapi saya sama sekali tidak jelas apa

Respons HARUS menyertakan entitas yang berisi daftar karakteristik sumber daya dan lokasi (s)

cara.

Rekomendasi? Interpretasi?

djna
sumber

Jawaban:

78

Idenya adalah bahwa respons tubuh memberi Anda halaman yang menghubungkan Anda ke hal tersebut:

201 Dibuat

Kode status 201 (Dibuat) menunjukkan bahwa permintaan telah dipenuhi dan menghasilkan satu atau lebih sumber daya baru yang dibuat. Sumber daya utama yang dibuat oleh permintaan diidentifikasi oleh bidang header Lokasi dalam respons atau, jika tidak ada bidang Lokasi yang diterima, oleh URI permintaan yang efektif.

Ini berarti bahwa Anda akan mencakup Locationdalam respon sundulan yang memberikan URL dari mana Anda dapat menemukan yang baru dibuat hal :

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597

Tubuh respon

Mereka kemudian melanjutkan dengan menyebutkan apa yang harus Anda sertakan dalam badan tanggapan :

Payload respons 201 biasanya mendeskripsikan dan menautkan ke resource yang dibuat.

Untuk manusia yang menggunakan browser, Anda memberi mereka sesuatu yang dapat mereka lihat, dan klik, untuk mendapatkan sumber daya yang baru mereka buat:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: text/html

Your answer has been saved! 
Click <A href="https://stackoverflow.com/a/36373586/12597">here</A> to view it.

Jika laman tersebut hanya akan digunakan oleh robot, masuk akal untuk memiliki respons yang dapat dibaca oleh komputer:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/xml

<createdResources>
   <questionID>1860645</questionID>
   <answerID>36373586</answerID>
   <primary>/a/36373586/12597</primary>
   <additional>
      <resource>http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586</resource>
      <resource>http://stackoverflow.com/a/1962757/12597</resource>
   </additional>
</createdResource>

Atau, jika Anda lebih suka:

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/36373586/12597
Content-Type: application/json

{ 
   "questionID": 1860645, 
   "answerID": 36373586,
   "primary": "/a/36373586/12597",
   "additional": [
      "http://stackoverflow.com/questions/1860645/create-request-with-post-which-response-codes-200-or-201-and-content/36373586#36373586",
      "http://stackoverflow.com/a/36373586/12597"
   ]
}

Tanggapan sepenuhnya terserah Anda; itu sesuka Anda.

Ramah cache

Akhirnya ada pengoptimalan bahwa saya dapat melakukan pra-cache sumber daya yang dibuat (karena saya sudah memiliki konten; saya baru saja mengunggahnya). Server dapat mengembalikan tanggal atau ETag yang dapat saya simpan dengan konten yang baru saya unggah:

Lihat Bagian 7.2 untuk diskusi tentang arti dan tujuan bidang header validator, seperti ETag dan Last-Modified, dalam respons 201.

HTTP/1.1 201 Created
Date: Sat, 02 Apr 2016 12:22:40 GMT
Location: http://stackoverflow.com/a/23704283/12597
Content-Type: text/html
ETag: JF2CA53BOMQGU5LTOQQGC3RAMV4GC3LQNRSS4
Last-Modified: Sat, 02 Apr 2016 12:22:39 GMT 

Your answer has been saved! 
Click <A href="https://stackoverflow.com/a/36373586/12597">here</A> to view it.

Dan ETags adalah nilai yang murni sewenang-wenang. Membuatnya berbeda ketika sumber daya berubah (dan cache perlu diperbarui) adalah yang terpenting. ETag biasanya berupa hash (misalnya SHA2). Tapi itu bisa berupa database rowversion, atau nomor revisi yang bertambah. Apa pun yang akan berubah saat hal itu berubah.

Ian Boyd
sumber
Sejauh ini tanggapan Anda tampaknya paling masuk akal. Saya sedikit cemas tentang ontologi responsnya, tetapi selain itu, sepertinya interpretasi spesifikasi yang paling matang. Saya ingin tahu apakah ada cara "responsif" ringan untuk menangani keluaran manusia / mesin. tetapi kebanyakan saya tertarik dengan saran "menyimpan masukan Anda sendiri". Sebagian besar aplikasi web yang saya tahu tidak akan membuat sumber daya versi 1: 1. Bahkan jika itu adalah sesuatu yang sepele seperti menormalkan kapitalisasi sebuah string. Bukankah agak cerdik untuk memperlakukan versi yang Anda kirimkan sebagai versi yang dibuat oleh etag?
Anthony
1
@Anthony, caching: bisa jadi semacam aplikasi penyimpanan file 1: 1. Bandingkan misalnya WebDAV PUT & POST. File-file besar untuk ditangani.
kxr
@Anthony Terserah Anda jika Anda ingin mengembalikan ETag kembali ke klien. Jika konten yang baru saja diunggah klien bukan yang Anda simpan, jangan mengembalikan ETag. Itu adalah fleksibilitas dan pilihan Anda.
Ian Boyd
Mengapa tanggapan Anda tidak memiliki Panjang Konten?
Vinnie Falco
1
@VinnieFalco Ini adalah jawaban tentang kode respons 201. Panjang Konten telah dipilih untuk tujuan ekspositori.
Ian Boyd
91

Menurut saya, REST API atompub adalah contoh bagus dari layanan yang tenang. Lihat cuplikan di bawah dari spesifikasi atompub:

POST /edit/ HTTP/1.1
Host: example.org
User-Agent: Thingio/1.0
Authorization: Basic ZGFmZnk6c2VjZXJldA==
Content-Type: application/atom+xml;type=entry
Content-Length: nnn
Slug: First Post

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <title>Atom-Powered Robots Run Amok</title>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2003-12-13T18:30:02Z</updated>
  <author><name>John Doe</name></author>
  <content>Some text.</content>
</entry>

Server memberi sinyal kreasi yang berhasil dengan kode status 201. Responsnya mencakup header Lokasi yang menunjukkan URI Entri Anggota dari Entri Atom, dan representasi Entri tersebut di dalam isi respons.

HTTP/1.1 201 Created
Date: Fri, 7 Oct 2005 17:17:11 GMT
Content-Length: nnn
Content-Type: application/atom+xml;type=entry;charset="utf-8"
Location: http://example.org/edit/first-post.atom
ETag: "c180de84f991g8"  

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <title>Atom-Powered Robots Run Amok</title>
  <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
  <updated>2003-12-13T18:30:02Z</updated>
  <author><name>John Doe</name></author>
  <content>Some text.</content>
  <link rel="edit"
      href="http://example.org/edit/first-post.atom"/>
</entry>

Entri yang dibuat dan dikembalikan oleh Koleksi mungkin tidak cocok dengan Entri yang DIPOSTING oleh klien. Server MUNGKIN mengubah nilai berbagai elemen dalam Entri, seperti nilai atom: id, atom: diperbarui, dan atom: penulis, dan BISA memilih untuk menghapus atau menambahkan elemen dan atribut lain, atau mengubah konten elemen dan nilai atribut.

Chandra Patni
sumber
9
Mengembalikan sumber daya yang dibuat mungkin sedikit banyak, jika sumber daya dalam besaran gigabyte ...
Tor Valamo
10
Sepakat! Itulah pengoptimalan kebutuhan-- tetapi Anda tidak ingin melakukannya secara prematur. Penting untuk mendesain dalam roh Tenang dan membuat pengecualian hanya jika diperlukan.
Chandra Patni
3
@ChandraPatni, Atom sudah mati . Butuh contoh yang lebih baik.
Pacerier
16
Atom mungkin sudah mati, tapi semangat contohnya masih tepat.
Asimema
2
Penafsiran asli saya terhadap respons 201 lebih seperti "hei, Anda ingin membuat sumber daya, tetapi berdasarkan konteks, Anda tidak tertarik dengan hasil akhirnya, atau memiliki akses tulis tetapi tidak memiliki akses baca ke sumber daya ini. Di kedua kasus, semua yang Anda butuhkan sebelum kembali ke koleksi utama adalah URL dari sumber daya yang dibuat. Sebagai bukti itu dibuat. " Apa pun di luar itu tampaknya seperti 200 respons, pada dasarnya. Kecuali jika RFC memikirkan hal lain.
Anthony
50

Dalam beberapa kata:

  • 200 ketika sebuah objek dibuat dan dikembalikan
  • 201 ketika sebuah objek dibuat tetapi hanya referensinya yang dikembalikan (seperti ID atau tautan)
Stéphane Bruckert
sumber
Sumber untuk ini?
sudo soul
3
Ini yang saya pahami dari w3.org/Protocols/rfc2616/rfc2616-sec10.html dan httpstatuses.com/201
Stéphane Bruckert
3
Setelah membaca tools.ietf.org/html/rfc7231#section-6.3.1 , saya setuju dengan pemahaman ini - Saya kira saya bertanya lebih lanjut bagaimana Anda sampai di sana. Tapi sekarang dalam pemahaman saya ... 200 = sumber daya dibuat dan dikembalikan | 201 = sumber daya dibuat dan referensi dikembalikan | 204 = sumber daya dibuat dan tidak ada muatan yang dikembalikan
sudo soul
34

Lihat HTTP: Definisi Metode: POST .

Tindakan yang dilakukan oleh metode POST mungkin tidak menghasilkan sumber daya yang dapat diidentifikasi oleh URI. Dalam kasus ini, baik 200 (OK) atau 204 (Tanpa Konten) adalah status respons yang sesuai, bergantung pada apakah respons menyertakan entitas yang menjelaskan hasil atau tidak.

Jika sumber daya telah dibuat di server asal, respons HARUS 201 (Dibuat) dan berisi entitas yang menjelaskan status permintaan dan merujuk ke sumber daya baru, dan header Lokasi (lihat bagian 14.30).

ma11hew28
sumber
18

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19

Ini hanya nilai kunci yang dipisahkan oleh titik dua.

ETag: "xyzzy"

Ini bisa berupa semua jenis data teks - Saya biasanya menyertakan string JSON dengan pengenal item yang dibuat. Kemudahan pengujian saja membuatnya menjadi bermanfaat.

ETag: "{ id: 1234, uri: 'http://domain.com/comments/1234', type: 'comment' }"

Dalam contoh ini, pengidentifikasi, uri, dan jenis item yang dibuat adalah "karakteristik dan lokasi sumber daya".

tempire
sumber
3
Anda mengatakan bahwa ETag sesuai dengan entitas yang berisi daftar karakteristik sumber daya dan lokasi . Saya dapat melihat bahwa saran Anda bagus, sangat setuju dengan pendapat Anda tentang pengujian. Namun saya tidak melihat bagaimana ini cocok dengan "daftar karakteristik sumber daya dan lokasi".
djna
"Daftar karakteristik sumber daya dan lokasi" akan menjadi konten dari struktur data apa pun yang disediakan. Implementasi yang lebih ketat adalah agar struktur JSON menyertakan uri sumber daya dan mungkin jenis sumber daya yang dibuat. Saya akan menyesuaikan jawabannya seperti itu.
tempire
7
Tentukan masalah, sehingga orang dapat belajar. Jika tidak, komentar itu hanya melambaikan tangan.
tempire
@SimonGibbs Masalah apa?
MEMark
2
Meskipun benar sesuai spesifikasi, ini merekomendasikan opsi implementasi yang sangat tidak biasa. Juga tidak benar-benar menjawab pertanyaan di bagian atas halaman (atau melakukannya dengan mencampurkan kata ETag dan entitas). Jawaban dengan 43 suara mungkin lebih baik.
Simon Gibbs
1

Outputnya sebenarnya tergantung pada jenis konten yang diminta. Namun, setidaknya Anda harus meletakkan sumber daya yang telah dibuat di Lokasi. Sama seperti pola Pasca-Pengalihan-Dapatkan.

Dalam kasus saya, saya membiarkannya kosong sampai diminta sebaliknya. Karena itulah perilaku JAX-RS saat menggunakan Response.created ().

Namun, perhatikan bahwa browser dan kerangka kerja seperti Angular tidak mengikuti 201 secara otomatis. Saya telah mencatat perilaku tersebut di http://www.trajano.net/2013/05/201-created-with-angular-resource/

Archimedes Trajano
sumber
-2

Jawaban lain yang saya miliki untuk ini adalah dengan mengambil pendekatan pragmatis dan mempertahankan kontrak REST API Anda sederhana. Dalam kasus saya, saya telah merefaktor REST API saya untuk membuat semuanya lebih dapat diuji tanpa menggunakan JavaScript atau XHR, hanya formulir dan tautan HTML sederhana.

Jadi untuk lebih spesifik tentang pertanyaan Anda di atas, saya hanya akan menggunakan kode pengembalian 200dan pesan yang dikembalikan berisi pesan JSON yang dapat dipahami aplikasi Anda. Bergantung pada kebutuhan Anda, ini mungkin memerlukan ID dari objek yang baru dibuat sehingga aplikasi web bisa mendapatkan data dalam panggilan lain.

Satu catatan, dalam kontrak API refactored saya, tanggapan POST tidak boleh berisi data yang dapat disimpan dalam cache karena POST tidak benar-benar dapat disimpan dalam cache, jadi batasi ke ID yang dapat diminta dan disimpan dalam cache menggunakan permintaan GET.

Archimedes Trajano
sumber