Panggil metode sisi server pada sumber daya dengan tenang

142

Perlu diingat saya memiliki pemahaman yang belum sempurna tentang REST. Katakanlah saya punya URL ini:

http://api.animals.com/v1/dogs/1/

Dan sekarang, saya ingin membuat server membuat kulit anjing. Hanya server yang tahu cara melakukan ini. Katakanlah saya ingin menjalankannya pada pekerjaan CRON yang membuat anjing menggonggong setiap 10 menit selama sisa keabadian. Seperti apa panggilan itu? Saya agak ingin melakukan ini:

Permintaan URL:

ACTION http://api.animals.com/v1/dogs/1/

Di badan permintaan:

{"action":"bark"}

Sebelum Anda marah kepada saya karena membuat metode HTTP saya sendiri, bantu saya dan berikan saya ide yang lebih baik tentang bagaimana saya harus memanggil metode sisi server dengan cara yang tenang. :)

EDIT UNTUK KLARIFIKASI

Beberapa klarifikasi lebih lanjut tentang apa metode "kulit" tidak. Berikut adalah beberapa opsi yang dapat menghasilkan panggilan API terstruktur berbeda:

  1. kulit hanya mengirim email ke dog.email dan tidak mencatat apa pun.
  2. kulit mengirim email ke dog.email dan pertambahan dog.barkCount oleh 1.
  3. kulit membuat catatan "kulit" baru dengan rekaman kulit.timestamp ketika kulit itu terjadi. Ini juga menambah dog.barkCount dengan 1.
  4. kulit kayu menjalankan perintah sistem untuk menarik kode anjing versi terbaru dari Github. Kemudian mengirim pesan teks ke dog.owner mengatakan kepada mereka bahwa kode anjing baru sedang dalam produksi.
Kirk Ouimet
sumber
14
Menariknya, menambahkan karunia tampaknya telah menarik jawaban yang lebih buruk daripada yang Anda miliki sebelumnya ;-) Ketika mengevaluasi jawaban ingat bahwa: 1) Spesifikasi untuk kata kerja HTTP menghalangi pilihan selain POST. 2) REST tidak ada hubungannya dengan struktur URL - itu adalah daftar generik dari kendala (stateless, cacheable, layered, antarmuka yang seragam, dll) daripada memberi manfaat (skalabilitas, keandalan, visibilitas, dll). 3) Praktek saat ini (seperti menggunakan POST dalam spesifikasi RPC) mengalahkan pembuat definisi yang membuat aturan API mereka sendiri. 4) REST membutuhkan antarmuka yang seragam (mengikuti spesifikasi HTTP).
Raymond Hettinger
@Kirk apa pendapat Anda tentang jawaban baru? Adakah sesuatu yang masih ingin Anda ketahui tetapi tidak dialamatkan pada mereka? Saya akan sangat senang mengedit jawaban saya lagi jika itu bisa lebih membantu.
Jordan
@RaymondHettinger PATCHbisa tepat. Saya menjelaskan mengapa menjelang akhir jawaban saya .
Jordan
PATCH hanya akan sesuai untuk menambah dog.barkCount per satu. POST adalah metode untuk mengirim email, membuat catatan kulit baru, menjalankan perintah untuk mengunduh dari Github, atau memicu pesan teks. @ Jonord, pembacaan Anda tentang PATCH RFC adalah imajinatif tetapi agak bertentangan dengan maksudnya sebagai varian PUT untuk modifikasi sumber daya parsial. Saya tidak berpikir Anda membantu OP dengan membuat bacaan yang tidak konvensional dari spesifikasi HTTP daripada mengakui praktik standar menggunakan POST untuk panggilan prosedur jarak jauh.
Raymond Hettinger
@RaymondHettinger yang praktiknya secara de facto membakukan POST? Semua antarmuka RPC standar yang pernah saya lihat mengidentifikasi sumber daya berdasarkan entitas (bukan RESTful), vs URI, jadi jawaban yang valid yang memprioritaskan konvensi RPC akan tetap tidak konvensional, yang menurut saya menyangkal nilai RPC konvensional: yang satu adalah imajinatif atau tidak konsisten . Anda tidak akan pernah salah dengan POST karena POST menangkap semuanya untuk pemrosesan data, tetapi ada metode yang lebih spesifik. REST berarti menamai sumber daya dan menjelaskan perubahan di negara mereka, bukan menyebutkan prosedur yang mengubah negara. PATCH dan POST keduanya menjelaskan perubahan status.
Jordan

Jawaban:

280

Mengapa bertujuan untuk desain yang tenang?

Prinsip RESTful membawa fitur yang membuat situs web mudah (bagi pengguna manusia acak untuk "berselancar") ke desain API layanan web , sehingga mudah digunakan oleh programmer. REST tidak baik karena REST, itu bagus karena itu bagus. Dan itu bagus terutama karena itu sederhana .

Kesederhanaan HTTP biasa (tanpa amplop SOAP dan POSTlayanan kelebihan-URI tunggal ), yang oleh sebagian orang disebut "kekurangan fitur" , sebenarnya merupakan kekuatan terbesarnya . Langsung dari kesalahan, HTTP meminta Anda untuk memiliki addressability dan statelessness : dua keputusan desain dasar yang menjaga HTTP scalable hingga situs mega saat ini (dan layanan mega).

Tapi REST bukan bulletet perak: Kadang-kadang gaya RPC ("Remote Procedure Call" - seperti SOAP) mungkin sesuai , dan kadang-kadang kebutuhan lain didahulukan dari kebaikan Web. Ini baik Yang tidak kita sukai adalah kompleksitas yang tidak perlu . Terlalu sering programmer atau perusahaan membawa Layanan bergaya RPC untuk pekerjaan yang dapat ditangani oleh HTTP tua biasa. Efeknya adalah HTTP direduksi menjadi protokol transport untuk muatan XML yang sangat besar yang menjelaskan apa yang sebenarnya terjadi (bukan metode URI atau HTTP yang memberikan petunjuk tentang hal itu). Layanan yang dihasilkan terlalu rumit, tidak mungkin untuk di-debug, dan tidak akan berfungsi kecuali klien Anda memiliki pengaturan persis seperti yang diinginkan pengembang.

Cara yang sama kode Java / C # tidak bisa berorientasi objek, hanya menggunakan HTTP tidak membuat desain TENANG. Seseorang mungkin terjebak dalam ketergesaan berpikir tentang layanan mereka dalam hal tindakan dan metode jarak jauh yang harus dipanggil. Tidak heran ini sebagian besar akan berakhir dalam layanan RPC-Style (atau REST-RPC-hybrid). Langkah pertama adalah berpikir secara berbeda. Desain yang tenang dapat dicapai dengan banyak cara, salah satunya adalah dengan memikirkan aplikasi Anda dalam hal sumber daya, bukan tindakan:

💡 Alih-alih berpikir dalam hal tindakan yang dapat dilakukan ("lakukan pencarian tempat di peta") ...

... coba pikirkan dalam hal hasil dari tindakan tersebut ("daftar tempat di peta yang cocok dengan kriteria pencarian").

Saya akan ambil contoh di bawah ini. (Aspek kunci lain dari REST adalah penggunaan HATEOAS - Saya tidak menyikatnya di sini, tapi saya membicarakannya dengan cepat di pos lain .)


Masalah desain pertama

Mari kita lihat desain yang diusulkan:

ACTION http://api.animals.com/v1/dogs/1/

Pertama, kita seharusnya tidak mempertimbangkan membuat kata kerja HTTP baru ( ACTION). Secara umum, ini tidak diinginkan karena beberapa alasan:

  • (1) Hanya diberikan layanan URI, bagaimana programmer "acak" tahu ACTIONkata kerjanya?
  • (2) jika programmer tahu itu ada, bagaimana dia tahu semantiknya? Apa arti kata kerja itu?
  • (3) properti apa (keamanan, idempoten) yang harus dimiliki seseorang yang memiliki kata kerja itu?
  • (4) bagaimana jika programmer memiliki klien yang sangat sederhana yang hanya menangani kata kerja HTTP standar?
  • (5) ...

Sekarang mari kita pertimbangkanPOST untuk menggunakan (saya akan membahas mengapa di bawah ini, ambil saja kata-kata saya sekarang):

POST /v1/dogs/1/ HTTP/1.1
Host: api.animals.com

{"action":"bark"}

Ini mungkin OK ... tetapi hanya jika :

  • {"action":"bark"}adalah sebuah dokumen; dan
  • /v1/dogs/1/adalah "pengolah dokumen" (seperti pabrik) URI. "Pemroses dokumen" adalah URI yang Anda "singkirkan" dan "lupakan" - prosesor dapat mengarahkan Anda ke sumber yang baru dibuat setelah "melempar". Misalnya URI untuk memposting pesan di layanan perantara pesan, yang, setelah posting akan mengarahkan Anda ke URI yang menunjukkan status pemrosesan pesan.

Saya tidak tahu banyak tentang sistem Anda, tetapi saya sudah bertaruh keduanya tidak benar:

  • {"action":"bark"} bukan dokumen , itu sebenarnya metode yang Anda coba untuk menyelinap masuk ke layanan; dan
  • yang /v1/dogs/1/URI merupakan "anjing" sumber daya (mungkin anjing dengan id==1) dan tidak prosesor dokumen.

Jadi yang kita tahu sekarang adalah bahwa desain di atas tidak begitu tenang, tapi apa sebenarnya itu? Apa yang sangat buruk tentang itu? Pada dasarnya, itu buruk karena itu adalah URI yang kompleks dengan makna yang kompleks. Anda tidak dapat menyimpulkan apa pun darinya. Bagaimana seorang programmer mengetahui seekor anjing memiliki barkaksi yang dapat secara diam-diam dimasukkan POSTke dalamnya?


Merancang panggilan API pertanyaan Anda

Jadi mari kita memotong ke pengejaran dan mencoba untuk merancang gonggongan itu dengan tenang dengan memikirkan sumber daya . Izinkan saya mengutip buku Restful Web Services :

Sebuah POSTpermintaan merupakan upaya untuk menciptakan sumber daya baru dari yang sudah ada. Sumber daya yang ada dapat menjadi induk dari yang baru dalam arti struktur data, cara akar pohon adalah induk dari semua simpul daunnya. Atau sumber daya yang ada dapat berupa sumber daya "pabrik" khusus yang tujuannya hanya untuk menghasilkan sumber daya lain. Representasi yang dikirim bersama dengan POSTpermintaan menggambarkan keadaan awal sumber daya baru. Seperti PUT, POSTpermintaan tidak perlu menyertakan representasi sama sekali.

Dengan mengikuti uraian di atas, kita dapat melihat bahwa barkdapat dimodelkan sebagai sub-sumber daya daridog (karena a barkterkandung dalam seekor anjing, yaitu, kulit kayu "kulit kayu" oleh seekor anjing).

Dari alasan itu kita sudah mendapat:

  • Metodenya adalah POST
  • Sumber dayanya adalah /barks, sub- sumber daya anjing:, /v1/dogs/1/barksmewakili bark"pabrik". URI itu unik untuk setiap anjing (karena di bawah /v1/dogs/{id}).

Sekarang setiap kasus daftar Anda memiliki perilaku tertentu.

1. kulit hanya mengirim email ke dog.emaildan tidak merekam apa pun.

Pertama, apakah menggonggong (mengirim email) tugas yang sinkron atau tidak sinkron? Kedua, apakah barkpermintaan memerlukan dokumen apa pun (email, mungkin) atau kosong?


1.1 kulit mengirim email ke dog.emaildan tidak merekam apa-apa (sebagai tugas sinkron)

Kasus ini sederhana. Panggilan ke barkssumber daya pabrik menghasilkan kulit kayu (e-mail terkirim) segera dan responsnya (jika OK atau tidak) segera diberikan:

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

(entity-body is empty - or, if you require a **document**, place it here)

200 OK

Saat merekam (perubahan) tidak ada, 200 OKsudah cukup. Ini menunjukkan bahwa semuanya berjalan seperti yang diharapkan.


1.2 kulit mengirim email ke dog.emaildan tidak merekam apa-apa (sebagai tugas tidak sinkron)

Dalam hal ini, klien harus memiliki cara untuk melacak barktugas. The barktugas kemudian harus menjadi sumber daya dengan itu sendiri URI .:

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

{document body, if needed;
NOTE: when possible, the response SHOULD contain a short hypertext note with a hyperlink
to the newly created resource (bark) URI, the same returned in the Location header
(also notice that, for the 202 status code, the Location header meaning is not
standardized, thus the importance of a hipertext/hyperlink response)}

202 Accepted
Location: http://api.animals.com/v1/dogs/1/barks/a65h44

Dengan cara ini, masing bark- masing dapat dilacak. Klien kemudian dapat mengeluarkan a GETke barkURI untuk mengetahui keadaan saat ini. Mungkin bahkan menggunakan DELETEuntuk membatalkannya.


2. kulit kayu mengirim email ke dog.emaildan kemudian bertambah dog.barkCount1

Yang ini bisa lebih sulit, jika Anda ingin memberi tahu klien bahwa dogsumber daya diubah:

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

{document body, if needed; when possible, containing a hipertext/hyperlink with the address
in the Location header -- says the standard}

303 See Other
Location: http://api.animals.com/v1/dogs/1

Dalam hal ini, locationmaksud header adalah memberi tahu klien bahwa ia harus melihatnya dog. Dari HTTP RFC tentang303 :

Metode ini ada terutama untuk memungkinkan output dari POSTskrip-aktif untuk mengarahkan agen pengguna ke sumber daya yang dipilih.

Jika tugas tidak sinkron, barksubresource diperlukan seperti 1.2situasinya dan 303harus dikembalikan pada GET .../barks/Ysaat tugas selesai.


3. kulit membuat catatan " bark" baru dengan bark.timestampmerekam ketika kulit terjadi. Ini juga bertambah dog.barkCount1.

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

(document body, if needed)

201 Created
Location: http://api.animals.com/v1/dogs/1/barks/a65h44

Di sini, barkitu dibuat karena permintaan, jadi statusnya 201 Createdditerapkan.

Jika pembuatannya tidak sinkron, maka 202 Accepteddiperlukan ( seperti yang dikatakan HTTP RFC ).

Stempel waktu yang disimpan adalah bagian dari barksumber daya dan dapat diambil dengan GETitu. Anjing yang diperbarui dapat "didokumentasikan" di GET dogs/X/barks/Ydalamnya juga.


4. kulit kayu menjalankan perintah sistem untuk menarik kode anjing versi terbaru dari Github. Kemudian mengirim pesan teks untuk dog.ownermemberi tahu mereka bahwa kode anjing baru dalam produksi.

Kata-kata yang satu ini rumit, tetapi cukup banyak tugas asinkron yang sederhana:

POST /v1/dogs/1/barks HTTP/1.1
Host: api.animals.com
Authorization: Basic mAUhhuE08u724bh249a2xaP=

(document body, if needed)

202 Accepted
Location: http://api.animals.com/v1/dogs/1/barks/a65h44

Klien kemudian akan mengeluarkan GETs untuk /v1/dogs/1/barks/a65h44mengetahui keadaan saat ini (jika kode itu ditarik, itu e-mail dikirim ke pemilik dan semacamnya). Setiap kali anjing berubah, a 303dapat diterapkan.


Membungkus

Mengutip Roy Fielding :

Satu-satunya hal yang dituntut oleh REST dari metode adalah bahwa mereka didefinisikan secara seragam untuk semua sumber daya (yaitu, sehingga perantara tidak harus mengetahui jenis sumber daya untuk memahami makna permintaan).

Dalam contoh di atas, POSTdirancang secara seragam. Itu akan membuat anjing " bark". Itu tidak aman (artinya kulit kayu memiliki efek pada sumber daya), atau idempoten (setiap permintaan menghasilkan yang baru bark), yang cocok dengan POSTkata kerja dengan baik.

Seorang programmer akan tahu: a POSTto barksyields a bark. Kode status respons (juga dengan entitas-badan dan header bila perlu) melakukan pekerjaan menjelaskan apa yang berubah dan bagaimana klien dapat dan harus melanjutkan.

Catatan: Sumber utama yang digunakan adalah: " Restful Web Services " buku, HTTP RFC dan blog Roy Fielding .




Edit:

Pertanyaan dan dengan demikian jawabannya telah sedikit berubah sejak pertama kali dibuat. Pertanyaan awal ditanyakan tentang desain URI seperti:

ACTION http://api.animals.com/v1/dogs/1/?action=bark

Di bawah ini adalah penjelasan mengapa itu bukan pilihan yang baik:

Bagaimana klien memberi tahu server APA YANG HARUS DILAKUKAN dengan data adalah informasi metode .

  • Layanan web yang tenang menyampaikan informasi metode dalam metode HTTP.
  • Layanan RPC-Style dan SOAP yang khas menyimpannya di entitas-badan dan header HTTP.

BAGIAN yang dari data [klien ingin server] untuk beroperasi adalah informasi pelingkupan .

  • Layanan tenang menggunakan URI. Layanan SOAP / RPC-Style sekali lagi menggunakan entitas-tubuh dan header HTTP.

Sebagai contoh, ambil Google URI http://www.google.com/search?q=DOG. Di sana, informasi metode adalah GETdan informasi pelingkupannya /search?q=DOG.

Singkat cerita:

  • Dalam arsitektur RESTful , informasi metode masuk ke metode HTTP.
  • Dalam Arsitektur Berorientasi Sumber Daya , informasi pelingkupan masuk ke URI.

Dan aturan praktisnya:

Jika metode HTTP tidak cocok dengan informasi metode, layanan ini tidak tenang. Jika informasi pelingkupan tidak dalam URI, layanan tidak berorientasi sumber daya.

Anda dapat meletakkan "kulit" "tindakan" di URL (atau di badan-entitas) dan gunakan POST. Tidak masalah di sana, ini berfungsi, dan mungkin cara paling sederhana untuk melakukannya, tetapi ini tidak tenang .

Untuk menjaga layanan Anda tetap tenang, Anda mungkin harus mengambil langkah mundur dan memikirkan apa yang benar-benar ingin Anda lakukan di sini (efek apa yang akan terjadi pada sumber daya).

Saya tidak dapat berbicara tentang kebutuhan bisnis spesifik Anda, tetapi izinkan saya memberi Anda sebuah contoh: Pertimbangkan layanan pemesanan yang tenang di mana pesanan berada di URI seperti example.com/order/123.

Sekarang katakanlah kita ingin membatalkan pesanan, bagaimana kita akan melakukannya? Orang mungkin tergoda untuk berpikir bahwa itu adalah "pembatalan" "tindakan" dan mendesainnya sebagai POST example.com/order/123?do=cancel.

Itu tidak tenang, seperti yang kita bicarakan di atas. Sebagai gantinya, kami mungkin PUTrepresentasi baru dari orderdengan canceledelemen yang dikirim ke true:

PUT /order/123 HTTP/1.1
Content-Type: application/xml

<order id="123">
    <customer id="89987">...</customer>
    <canceled>true</canceled>
    ...
</order>

Dan itu saja. Jika pesanan tidak dapat dibatalkan, kode status tertentu dapat dikembalikan. (Desain sub-sumber daya, seperti POST /order/123/canceleddengan entitas-badan truemungkin, untuk kesederhanaan, juga tersedia.)

Dalam skenario spesifik Anda, Anda dapat mencoba sesuatu yang serupa. Dengan begitu, saat anjing menggonggong, misalnya, GETat /v1/dogs/1/dapat memasukkan informasi itu (misalnya <barking>true</barking>) . Atau ... jika itu terlalu rumit, kendurkan persyaratan RESTful Anda dan ikuti POST.

Memperbarui:

Saya tidak ingin membuat jawaban terlalu besar, tetapi perlu beberapa saat untuk membiasakan mengekspos algoritma ( aksi ) sebagai satu set sumber daya. Alih-alih berpikir dalam hal tindakan ( "melakukan pencarian tempat di peta" ), orang perlu berpikir dalam hal hasil dari tindakan itu ( "daftar tempat di peta yang cocok dengan kriteria pencarian" ).

Anda mungkin menemukan diri Anda kembali ke langkah ini jika Anda menemukan bahwa desain Anda tidak sesuai dengan antarmuka seragam HTTP.

Variabel kueri adalah pelingkupan informasi , tetapi tidak menunjukkan sumber daya baru ( /post?lang=enjelas sumber daya yang sama dengan /post?lang=jp, hanya representasi yang berbeda). Sebaliknya, mereka digunakan untuk menyampaikan status klien (seperti ?page=10, sehingga status tidak disimpan di server; ?lang=enjuga merupakan contoh di sini) atau memasukkan parameter ke sumber daya algoritmik ( /search?q=dogs, /dogs?code=1). Sekali lagi, bukan sumber daya yang berbeda.

Properti (metode) kata kerja HTTP:

Poin jelas lainnya yang ditampilkan ?action=somethingdalam URI adalah tidak TETAP, adalah properti dari kata kerja HTTP:

  • GETdan HEADaman (dan idempoten);
  • PUTdan DELETEhanya idempoten;
  • POST bukan keduanya.

Keamanan : Permintaan GETatau HEADpermintaan adalah permintaan untuk membaca beberapa data, bukan permintaan untuk mengubah status server apa pun. Klien dapat membuat GETatau HEADmeminta 10 kali dan itu sama dengan membuatnya sekali, atau tidak pernah membuatnya sama sekali .

Idempoten : Operasi idempoten di salah satu yang memiliki efek yang sama apakah Anda menerapkannya sekali atau lebih dari sekali (dalam matematika, mengalikan dengan nol adalah idempoten). Jika Anda DELETEsumber daya sekali, menghapus lagi akan memiliki efek yang sama (sumber daya GONEsudah ada).

POSTtidak aman atau idempoten. Membuat dua POSTpermintaan yang identik dengan sumber daya 'pabrik' mungkin akan menghasilkan dua sumber daya bawahan yang mengandung informasi yang sama. Dengan kelebihan beban (metode dalam URI atau entitas-tubuh) POST, semua taruhan dimatikan.

Kedua properti ini penting untuk keberhasilan protokol HTTP (melalui jaringan yang tidak dapat diandalkan!): Berapa kali Anda memperbarui ( GET) halaman tanpa menunggu sampai sepenuhnya dimuat?

Membuat tindakan dan menempatkannya di URL dengan jelas melanggar kontrak metode HTTP. Sekali lagi, teknologi memungkinkan Anda, Anda bisa melakukannya, tetapi itu bukan desain yang tenang.

acdcjunior
sumber
Saya setuju dengan gagasan bahwa memanggil tindakan di server, yang ditunjuk sebagai tindakan di URL, tidak tenang. POSTdirancang untuk "menyediakan blok data ... untuk proses penanganan data" . Tampaknya banyak orang membedakan sumber daya dari tindakan, tetapi benar-benar tindakan hanyalah jenis sumber daya.
Jacob Stevens
1
@ JacobStevens OP mengubah pertanyaan sedikit jadi saya harus memperbarui jawaban saya untuk membuatnya lebih langsung (periksa pertanyaan asli , mungkin Anda akan melihat apa yang saya maksud). Saya setuju dengan POST"menyediakan blok data ... untuk proses penanganan data", tetapi perbedaannya adalah, blok data , bukan blok data dan prosedur (tindakan, metode, perintah) untuk menjadi dieksekusi pada saat itu. Itu POSToverloading, dan POSToverloading adalah desain RPC-Style, bukan RESTful.
acdcjunior
Saya menduga logika tindakan / metode akan ditempatkan di server, jika tidak, apa tujuan panggilan itu? Jika Anda menjelaskan, saya setuju, itu tidak akan menjadi desain yang bagus. Tetapi metode atau subrutin yang melakukan tindakan akan ditentukan oleh URI (yang merupakan alasan lain mengapa sumber daya tindakan yang ditunjuk sebagai kata kerja di akhir URL berguna dan tenang, meskipun banyak yang menyarankan untuk tidak melakukannya).
Jacob Stevens
6
Jawabannya kami perbarui. Agak lama karena diperlukan penjelasan yang menyeluruh ("Ingat saya memiliki pemahaman yang belum sempurna tentang REST."). Itu semacam perjuangan untuk membuatnya sejelas mungkin. Semoga bermanfaat dalam beberapa cara.
acdcjunior
2
Penjelasan hebat, saya memilih tetapi header Lokasi tidak boleh digunakan dalam 202 Respons yang diterima. Tampaknya menjadi interpretasi yang salah yang dilakukan banyak orang dari RFC. Periksa stackoverflow.com/questions/26199228/…
Delmo
6

Saya menjawab sebelumnya , tetapi jawaban ini bertentangan dengan jawaban lama saya dan mengikuti strategi yang jauh berbeda untuk mencapai solusi. Ini menunjukkan bagaimana permintaan HTTP dibangun dari konsep yang mendefinisikan REST dan HTTP. Ini juga menggunakan PATCHbukan POSTatau PUT.

Ia melewati batasan REST, lalu komponen HTTP, lalu solusi yang memungkinkan.

BERISTIRAHAT

REST adalah serangkaian kendala yang dimaksudkan untuk diterapkan pada sistem hypermedia terdistribusi untuk membuatnya scalable. Bahkan untuk membuatnya masuk akal dalam konteks mengendalikan suatu tindakan dari jarak jauh, Anda harus berpikir untuk mengendalikan suatu tindakan dari jarak jauh sebagai bagian dari sistem hypermedia terdistribusi - bagian dari sistem untuk menemukan, melihat, dan mengubah informasi yang saling berhubungan. Jika itu lebih banyak masalah daripada nilainya, maka mungkin tidak baik untuk mencoba membuatnya Tenang. Jika Anda hanya menginginkan "panel kontrol" ketik GUI pada klien yang dapat memicu tindakan pada server melalui port 80, maka Anda mungkin menginginkan antarmuka RPC sederhana seperti JSON-RPC melalui permintaan / tanggapan HTTP atau WebSocket.

Tetapi REST adalah cara berpikir yang menarik dan contoh dalam pertanyaan tersebut adalah mudah untuk dimodelkan dengan antarmuka RESTful, jadi mari kita hadapi tantangan untuk bersenang-senang dan untuk pendidikan.

REST didefinisikan oleh empat batasan antarmuka:

identifikasi sumber daya; manipulasi sumber daya melalui representasi; pesan deskriptif diri; dan, hypermedia sebagai mesin status aplikasi.

Anda bertanya bagaimana Anda bisa mendefinisikan antarmuka, memenuhi batasan-batasan ini, di mana satu komputer memberitahu komputer lain untuk membuat kulit anjing. Khususnya, Anda ingin antarmuka Anda menjadi HTTP, dan Anda tidak ingin membuang fitur yang membuat HTTP RESTful saat digunakan sebagaimana dimaksud.

Mari kita mulai dengan kendala pertama: identifikasi sumber daya .

Setiap informasi yang dapat dinamai dapat berupa sumber daya: dokumen atau gambar, layanan temporal (mis. "Cuaca hari ini di Los Angeles"), kumpulan sumber daya lain, objek non-virtual (misalnya seseorang), dan sebagainya .

Jadi seekor anjing adalah sumber daya. Itu perlu diidentifikasi.

Lebih tepatnya, sumber daya R adalah fungsi keanggotaan temporal yang bervariasi M R ( t ), yang untuk waktu t peta untuk satu set entitas, atau nilai-nilai yang setara. Nilai-nilai dalam himpunan mungkin representasi sumber daya dan / atau pengidentifikasi sumber daya .

Anda membuat model seekor anjing dengan mengambil satu set pengidentifikasi dan representasi dan mengatakan mereka semua terkait satu sama lain pada waktu tertentu. Untuk sekarang, mari gunakan pengidentifikasi "anjing # 1". Itu membawa kita ke kendala kedua dan ketiga: representasi sumber daya dan deskripsi diri .

Komponen REST melakukan tindakan pada sumber daya dengan menggunakan representasi untuk menangkap kondisi sumber daya saat ini atau yang dimaksudkan dan mentransfer representasi antara komponen. Representasi adalah urutan byte, ditambah representasi metadata untuk menggambarkan byte tersebut.

Berikut ini adalah urutan byte yang menangkap keadaan anjing yang dimaksud, yaitu representasi yang kami ingin dikaitkan dengan pengidentifikasi "anjing # 1" (perhatikan bahwa itu hanya mewakili bagian dari keadaan karena tidak memperhatikan nama anjing, kesehatan , atau bahkan menggonggong masa lalu):

Itu telah menggonggong setiap 10 menit sejak waktu perubahan negara ini diberlakukan, dan akan berlanjut tanpa batas waktu.

Seharusnya melekat pada metadata yang menggambarkannya. Metadata ini mungkin berguna:

Ini adalah pernyataan bahasa Inggris. Ini menggambarkan bagian dari keadaan yang dimaksud. Jika diterima beberapa kali, hanya biarkan yang pertama memiliki efek.

Akhirnya, mari kita lihat batasan keempat: HATEOAS .

REST ... memandang aplikasi sebagai struktur informasi yang kohesif dan mengontrol alternatif yang melaluinya pengguna dapat melakukan tugas yang diinginkan. Misalnya, mencari kata dalam kamus online adalah salah satu aplikasi, seperti tur melalui museum virtual, atau meninjau satu set catatan kelas untuk belajar untuk ujian. ... Keadaan kontrol berikutnya dari sebuah aplikasi berada dalam representasi sumber daya yang diminta pertama, sehingga memperoleh bahwa representasi pertama adalah prioritas. ... Oleh karena itu aplikasi model merupakan mesin yang bergerak dari satu keadaan ke keadaan berikutnya dengan memeriksa dan memilih dari antara transisi keadaan alternatif dalam rangkaian representasi saat ini.

Dalam antarmuka yang tenang, klien menerima representasi sumber daya untuk mengetahui bagaimana ia harus menerima atau mengirim representasi. Harus ada representasi di suatu tempat dalam aplikasi yang darinya klien dapat mengetahui cara menerima atau mengirim semua representasi yang seharusnya dapat diterima atau dikirim, bahkan jika ia mengikuti rantai representasi untuk sampai pada informasi itu. Ini tampaknya cukup sederhana:

Klien meminta representasi sumber daya yang diidentifikasi sebagai beranda; sebagai tanggapan, ia mendapat representasi yang berisi pengidentifikasi setiap anjing yang mungkin diinginkan klien. Klien mengekstraksi pengidentifikasi darinya dan menanyakan layanan bagaimana ia dapat berinteraksi dengan anjing yang diidentifikasi, dan layanan mengatakan klien dapat mengirim pernyataan bahasa Inggris yang menggambarkan bagian dari kondisi anjing yang dimaksud. Kemudian klien mengirim pernyataan seperti itu dan menerima pesan sukses atau pesan kesalahan.

HTTP

HTTP menerapkan batasan REST sebagai berikut:

identifikasi sumber daya : URI

representasi sumber daya : entitas-badan

deskripsi-diri : metode atau kode status, tajuk, dan kemungkinan bagian-bagian dari entitas-badan (mis. URI dari skema XML)

HATEOAS : hyperlink

Anda telah memutuskan http://api.animals.com/v1/dogs/1sebagai URI. Mari kita asumsikan klien mendapatkan ini dari beberapa halaman di situs.

Mari kita gunakan entitas-badan ini (nilai nexttimestamp; nilai 0sarana 'saat permintaan ini diterima'):

{"barks": {"next": 0, "frequency": 10}}

Sekarang kita membutuhkan suatu metode. PATCH cocok dengan deskripsi "bagian dari negara yang dituju" yang kami putuskan:

Metode PATCH meminta agar serangkaian perubahan yang dijelaskan dalam entitas permintaan diterapkan ke sumber daya yang diidentifikasi oleh Request-URI.

Dan beberapa tajuk:

Untuk menunjukkan bahasa entitas-tubuh: Content-Type: application/json

Untuk memastikan itu hanya terjadi sekali: If-Unmodified-Since: <date/time this was first sent>

Dan kami memiliki permintaan:

PATCH /v1/dogs/1/ HTTP/1.1
Host: api.animals.com
Content-Type: application/json
If-Unmodified-Since: <date/time this was first sent>
[other headers]

{"barks": {"next": 0, "frequency": 10}}

Jika berhasil, klien harus menerima 204kode status sebagai respons, atau 205jika representasi /v1/dogs/1/telah berubah untuk mencerminkan jadwal menggonggong baru.

Pada kegagalan, seharusnya menerima 403dan membantu pesan mengapa.

Tidaklah penting untuk REST bagi layanan untuk merefleksikan jadwal kulit kayu dalam representasi sebagai tanggapan GET /v1/dogs/1/, tetapi akan lebih masuk akal jika perwakilan JSON menyertakan ini:

"barks": {
    "previous": [x_1, x_2, ..., x_n],
    "next": x_n,
    "frequency": 10
}

Perlakukan pekerjaan cron sebagai detail implementasi yang disembunyikan server dari antarmuka. Itulah keindahan antarmuka generik. Klien tidak harus tahu apa yang dilakukan server di balik layar; yang perlu diperhatikan adalah layanan memahami dan merespons perubahan status yang diminta.

Yordania
sumber
3

Kebanyakan orang menggunakan POST untuk tujuan ini. Sangat tepat untuk melakukan "operasi apa pun yang tidak aman atau tidak ramah ketika tidak ada metode HTTP lain yang sesuai".

API seperti XMLRPC menggunakan POST untuk memicu tindakan yang dapat menjalankan kode arbitrer. "Tindakan" termasuk dalam data POST:

POST /RPC2 HTTP/1.0
User-Agent: Frontier/5.1.2 (WinNT)
Host: betty.userland.com
Content-Type: text/xml
Content-length: 181

<?xml version="1.0"?>
<methodCall>
   <methodName>examples.getStateName</methodName>
   <params>
      <param>
         <value><i4>41</i4></value>
         </param>
      </params>
   </methodCall>

Contoh RPC diberikan untuk menunjukkan bahwa POST adalah pilihan konvensional kata kerja HTTP untuk metode sisi server. Inilah pemikiran Roy Fielding pada POST - ia cukup banyak mengatakan itu tenang untuk menggunakan metode HTTP seperti yang ditentukan.

Perhatikan bahwa RPC itu sendiri tidak terlalu tenang karena tidak berorientasi sumber daya. Tetapi jika Anda membutuhkan kewarganegaraan, caching, atau layering, tidak sulit untuk melakukan transformasi yang tepat. Lihat http://blog.perfectapi.com/2012/opinionated-rpc-apis-vs-restful-apis/ untuk contoh.

Raymond Hettinger
sumber
Saya pikir Anda akan URLencode params tidak memasukkannya ke dalam string kueri
tacos_tacos_tacos
@Kirk Ya, tetapi dengan satu modifikasi kecil, lepaskan garis miring terakhir: POST api.animals.com/v1/dogs1?action=bark
Raymond Hettinger
jika Anda mengikuti saran dalam jawaban ini, ingatlah bahwa API yang dihasilkan tidak akan tenang.
Nicholas Shanks
2
Ini bukan RESTful karena HTTP menetapkan URL sebagai pengidentifikasi sumber daya dan URL /RPC2tidak melakukan apa pun untuk mengidentifikasi sumber daya - ini mengidentifikasi teknologi server. Alih-alih, ini digunakan methodNameuntuk mencoba 'mengidentifikasi' sumber daya '- tetapi bahkan kemudian, itu tidak mendapat manfaat dari perbedaan kata benda / kata kerja; satu-satunya 'kata kerja' di sini adalah methodCall. Ini seperti 'do state-name-retrieval' dan bukannya 'take-state-name' - yang terakhir jauh lebih masuk akal.
Jordan
+1 untuk tautan; sangat informatif dan percobaan "berpendapatan RPC" adalah inventif.
Jordan
2

POSTadalah metode HTTP yang dirancang untuk

Menyediakan blok data ... untuk proses penanganan data

Metode sisi server yang menangani tindakan yang tidak dipetakan CRUD adalah apa yang dimaksudkan oleh Roy Fielding dengan REST, jadi Anda hebat di sana, dan itulah sebabnya POSTdibuat menjadi non-idempoten. POSTakan menangani sebagian besar pengiriman data ke metode sisi server untuk memproses informasi.

Yang mengatakan, dalam skenario menggonggong anjing Anda, jika Anda ingin menggonggong sisi server dilakukan setiap 10 menit, tetapi untuk beberapa alasan perlu pemicu berasal dari klien, PUTakan melayani tujuan lebih baik, karena idempotensinya. Ya, benar-benar berdasarkan skenario ini, tidak ada risiko yang jelas dari beberapa permintaan POST yang menyebabkan anjing Anda mengeong, tetapi toh itulah tujuan dari dua metode yang serupa. Jawaban saya untuk pertanyaan SO yang serupa mungkin bermanfaat bagi Anda.

Jacob Stevens
sumber
1
PUT vs. POST adalah semua tentang URL. Paragraf ketiga setelah 9,6 PUT mengatakan tujuan dari kedua metode ini adalah agar PUTURL merujuk pada apa yang harus diganti oleh konten klien dan POSTURL mengacu pada apa yang harus memproses konten klien seperti yang diinginkan.
Jordan
1

Jika kita menganggap Barking adalah sumber daya dalam / dependen / sub di mana konsumen dapat bertindak, maka kita dapat mengatakan:

POST http://api.animals.com/v1/dogs/1/bark

gonggongan anjing nomor 1

GET http://api.animals.com/v1/dogs/1/bark

mengembalikan cap waktu kulit terakhir

DELETE http://api.animals.com/v1/dogs/1/bark

tidak berlaku! jadi abaikan saja.

bolbol
sumber
Ini hanya tenang jika Anda mempertimbangkan /v1/dogs/1/barkuntuk menjadi sumber daya per se , dan POSTmenjadi deskripsi tentang bagaimana keadaan internal sumber daya itu harus berubah. Saya menemukan bahwa lebih masuk akal untuk mempertimbangkan /v1/dogs/1/sebagai sumber daya dan menunjukkan dalam entitas-badan bahwa ia harus menggonggong.
Jordan
mmm .. yah, ini sumber daya yang bisa Anda ubah kondisinya. Karena hasil dari mengubah keadaannya membuat suara, tidak membuatnya kurang sumber daya! Anda melihat Bark sebagai kata kerja (yang) itu sebabnya Anda tidak bisa menganggapnya sebagai sumber daya. Saya melihatnya sebagai sumber daya dependen yang negaranya dapat diubah dan karena negaranya boolean, saya tidak melihat alasan untuk menyebutkannya dalam entitas-badan. Itu hanya pendapat saya.
bolbol
1

Revisi sebelumnya atas beberapa jawaban menyarankan Anda menggunakan RPC. Anda tidak perlu untuk melihat ke RPC seperti ini sangat mungkin untuk melakukan apa yang Anda inginkan sementara mengikuti kendala REST.

Pertama, jangan letakkan parameter tindakan di URL. URL menentukan apa yang Anda terapkan tindakan, dan parameter permintaan adalah bagian dari URL. Itu harus dianggap sepenuhnya sebagai kata benda. http://api.animals.com/v1/dogs/1/?action=barkadalah sumber yang berbeda - kata benda yang berbeda - untuk http://api.animals.com/v1/dogs/1/. [nb Penanya telah menghapus ?action=barkURI dari pertanyaan.] Misalnya, bandingkan http://api.animals.com/v1/dogs/?id=1dengan http://api.animals.com/v1/dogs/?id=2. Sumber daya berbeda, hanya dibedakan oleh string kueri. Jadi tindakan permintaan Anda, kecuali jika itu berhubungan langsung dengan jenis metode yang ada tanpa badan (TRACE, OPTIONS, HEAD, GET, DELETE, dll) harus didefinisikan dalam badan permintaan.

Selanjutnya, putuskan apakah tindakan itu " idempoten ", artinya tindakan itu dapat diulang tanpa efek yang merugikan (lihat paragraf berikutnya untuk penjelasan lebih lanjut). Misalnya, menetapkan nilai ke true dapat diulang jika klien tidak yakin bahwa efek yang diinginkan terjadi. Mereka mengirim permintaan lagi dan nilainya tetap benar. Menambahkan 1 ke angka bukanlah idempoten. Jika klien mengirim perintah Add1, tidak yakin itu berhasil, dan mengirimkannya lagi, apakah server menambahkan satu atau dua? Setelah Anda menentukan itu, Anda berada dalam posisi yang lebih baik untuk memilih di antara PUTdan POSTuntuk metode Anda.

Idempoten berarti permintaan dapat diulang tanpa mengubah hasilnya. Efek ini tidak termasuk pencatatan dan aktivitas admin server lainnya. Menggunakan contoh pertama dan kedua Anda, mengirim dua email ke orang yang sama menghasilkan keadaan yang berbeda dari mengirim satu email (penerima memiliki dua di kotak masuk mereka, yang mereka anggap sebagai spam), jadi saya pasti akan menggunakan POST untuk itu . Jika barkCount dalam contoh 2 dimaksudkan untuk dilihat oleh pengguna API Anda atau memengaruhi sesuatu yang terlihat oleh klien, maka itu juga merupakan sesuatu yang akan membuat permintaan tersebut menjadi non-idempoten. Jika hanya untuk dilihat oleh Anda maka itu dianggap sebagai pendataan server dan harus diabaikan ketika menentukan idempotentcy.

Terakhir, tentukan apakah tindakan yang ingin Anda lakukan dapat diharapkan berhasil segera atau tidak. BarkDog adalah tindakan yang cepat selesai. RunMarathon tidak. Jika tindakan Anda lambat, pertimbangkan untuk mengembalikan a 202 Accepted, dengan URL di badan respons agar pengguna dapat polling untuk melihat apakah tindakan itu selesai. Atau, minta pengguna POST ke daftar URL suka /marathons-in-progress/dan kemudian ketika tindakan dilakukan, mengarahkan mereka dari URL ID sedang berlangsung ke /marathons-complete/URL.
Untuk kasus-kasus tertentu # 1 dan # 2, saya akan meminta server host antrian, dan klien memposting batch alamat untuk itu. Tindakannya bukan SendEmails, tetapi sesuatu seperti AddToDispatchQueue. Server kemudian dapat polling antrian untuk melihat apakah ada alamat email yang menunggu, dan mengirim email jika ada. Ini kemudian memperbarui antrian untuk menunjukkan bahwa tindakan yang tertunda sekarang telah dilakukan. Anda akan memiliki URI lain yang menunjukkan kepada klien keadaan antrian saat ini. Untuk menghindari pengiriman ganda email, server juga dapat menyimpan log yang telah dikirimi email ini, dan memeriksa setiap alamat yang menentangnya untuk memastikan tidak pernah mengirim dua ke alamat yang sama, bahkan jika Anda POST daftar yang sama dua kali untuk antrian.

Ketika memilih URI untuk apa pun, coba pikirkan itu sebagai hasilnya, bukan tindakan. Misalnya google.com/search?q=dogsmenunjukkan hasil pencarian untuk kata "anjing". Tidak perlu melakukan pencarian.

Kasus # 3 dan # 4 dari daftar Anda juga bukan tindakan idempoten. Anda menyarankan bahwa berbagai efek yang disarankan dapat memengaruhi desain API. Dalam keempat kasus saya akan menggunakan API yang sama, karena keempatnya mengubah "negara dunia."

Nicholas Shanks
sumber
Katakanlah tindakannya adalah mengaduk-aduk antrian email raksasa dan mengirim pesan ke sekelompok orang. Apakah itu idempoten? Apakah tindakan idempoten untuk PUT atau POST?
Kirk Ouimet
@kirk Saya telah memperluas jawaban saya.
Nicholas Shanks
0

Lihat jawaban baru saya - ini bertentangan dengan yang ini dan menjelaskan REST dan HTTP dengan lebih jelas dan akurat.

Berikut adalah rekomendasi yang kebetulan tenang tetapi tentu saja bukan satu-satunya pilihan. Untuk mulai menggonggong ketika layanan menerima permintaan:

POST /v1/dogs/1/bark-schedule HTTP/1.1
...
{"token": 12345, "next": 0, "frequency": 10}

token adalah nomor sewenang-wenang yang mencegah gonggongan redundan tidak peduli berapa kali permintaan ini dikirim.

nextmenunjukkan waktu kulit berikutnya; nilai 0sarana 'ASAP'.

Setiap kali Anda GET /v1/dogs/1/bark-schedule, Anda harus mendapatkan sesuatu seperti ini, di mana t adalah waktu dari kulit lalu dan u adalah t + 10 menit:

{"last": t, "next": u}

Saya sangat menyarankan Anda menggunakan URL yang sama untuk meminta kulit kayu yang Anda gunakan untuk mencari tahu tentang kondisi menggonggong anjing saat ini. Ini tidak penting untuk REST, tetapi menekankan tindakan memodifikasi jadwal.

Kode status yang sesuai mungkin 205 . Saya membayangkan klien yang melihat jadwal saat ini, POSTs ke URL yang sama untuk mengubahnya, dan diinstruksikan oleh layanan untuk memberikan jadwal tampilan kedua untuk membuktikan bahwa itu telah diubah.

Penjelasan

BERISTIRAHAT

Lupakan HTTP sejenak. Sangat penting untuk memahami bahwa sumber daya adalah fungsi yang membutuhkan waktu sebagai input dan mengembalikan set yang berisi pengidentifikasi dan representasi . Mari kita sederhanakan untuk: suatu sumber daya adalah seperangkat R pengidentifikasi dan representasi; R dapat berubah - anggota dapat ditambahkan, dihapus, atau dimodifikasi. (Meskipun itu buruk, desain stabil untuk menghapus atau mengubah pengenal.) Kita mengatakan sebuah identifier yang merupakan elemen dari R mengidentifikasi R , dan bahwa representasi yang merupakan elemen dari R mewakili R .

Katakanlah R adalah seekor anjing. Anda kebetulan mengidentifikasi R sebagai /v1/dogs/1. (Arti /v1/dogs/1adalah anggota R .) Itu hanya salah satu dari banyak cara yang bisa mengidentifikasi R . Anda juga dapat mengidentifikasi R sebagai /v1/dogs/1/x-raysdan sebagai /v1/rufus.

Bagaimana Anda mewakili R ? Mungkin dengan foto. Mungkin dengan satu set sinar-X. Atau mungkin dengan indikasi tanggal dan waktu ketika R terakhir menyalak. Tetapi ingat bahwa ini semua adalah representasi dari sumber yang sama . /v1/dogs/1/x-raysadalah pengidentifikasi dari sumber daya yang sama yang diwakili oleh jawaban untuk pertanyaan "kapan R kulit terakhir?"

HTTP

Representasi berganda dari sumber daya tidak terlalu berguna jika Anda tidak bisa merujuk ke yang Anda inginkan. Karena itulah HTTP berguna: memungkinkan Anda menghubungkan pengidentifikasi ke representasi . Artinya, ini adalah cara bagi layanan untuk menerima URL dan memutuskan perwakilan mana yang akan dilayani kepada klien.

Setidaknya, itulah yang GETdilakukannya. PUTpada dasarnya adalah kebalikan dari GET: Anda PUTrepresentasi r di URL jika Anda ingin agar GETpermintaan di masa depan untuk mengembalikan r , dengan beberapa terjemahan yang mungkin seperti JSON ke HTML.

POSTadalah cara yang lebih longgar untuk memodifikasi representasi. Bayangkan ada logika tampilan dan logika modifikasi yang merupakan rekan satu sama lain - keduanya sesuai dengan URL yang sama. Permintaan POST adalah permintaan untuk logika modifikasi untuk memproses informasi dan memodifikasi representasi apa pun (bukan hanya representasi yang terletak dengan URL yang sama) sesuai dengan keinginan layanan. Perhatikan paragraf ketiga setelah 9,6 PUT : Anda tidak mengganti barang di URL dengan konten baru; Anda meminta sesuatu di URL untuk memproses beberapa informasi dan merespons dengan cerdas dalam bentuk representasi informatif.

Dalam kasus kami, kami meminta logika modifikasi di /v1/dogs/1/bark-schedule(yang merupakan lawan logika tampilan yang memberi tahu kami kapan salak terakhir dan kapan salak berikutnya) untuk memproses informasi kami dan memodifikasi beberapa representasi yang sesuai. Menanggapi masa depan GET, logika tampilan yang sesuai dengan URL yang sama akan memberi tahu kami bahwa anjing itu sekarang menggonggong seperti yang kita inginkan.

Pikirkan pekerjaan cron sebagai detail implementasi. Penawaran HTTP dalam melihat dan memodifikasi representasi. Mulai sekarang, layanan akan memberi tahu klien kapan anjing menggonggong terakhir dan kapan akan menggonggong berikutnya. Dari perspektif layanan, itu jujur ​​karena masa-masa itu sesuai dengan pekerjaan cron masa lalu dan yang direncanakan.

Yordania
sumber
-1

REST adalah standar yang berorientasi sumber daya, ini bukan tindakan yang didorong seperti RPC.

Jika Anda ingin server Anda menggonggong , Anda harus melihat ke berbagai ide seperti JSON-RPC , atau ke komunikasi websockets.

Setiap mencoba untuk tetap tenang akan gagal dalam pendapat saya: Anda bisa mengeluarkan POSTdengan actionparameter, Anda tidak menciptakan sumber daya baru tetapi karena Anda mungkin memiliki efek samping, Anda lebih aman.

moonwave99
sumber
POSTdirancang untuk "menyediakan blok data ... untuk proses penanganan data" . Tampaknya banyak orang membedakan sumber daya dari tindakan, tetapi benar-benar tindakan hanyalah jenis sumber daya. Memanggil sumber aksi di server masih berupa antarmuka yang seragam, dapat disimpan dalam cache, modular, dan dapat diskalakan. Itu juga tanpa kewarganegaraan, tetapi itu bisa dilanggar jika klien dirancang untuk mengharapkan respons. Tetapi memanggil "void method" di server adalah apa yang dimaksud Roy Fielding dengan REST .
Jacob Stevens
Seperti yang saya jelaskan dalam jawaban saya , Anda dapat di REST secara implisit menyebabkan server melakukan tindakan dengan memintanya untuk mengatakan, mulai sekarang, "tindakan Anda selesai", sedangkan RPC didasarkan pada gagasan hanya meminta server untuk melakukan tindakan. Keduanya masuk akal, sama seperti pemrograman imperatif dan deklaratif keduanya masuk akal.
Jordan