REST API - mengapa menggunakan PUT DELETE POST GET?

155

Jadi, saya melihat-lihat beberapa artikel tentang cara membuat REST API. Dan beberapa dari mereka menyarankan menggunakan semua jenis permintaan HTTP: suka PUT DELETE POST GET. Kami akan membuat misalnya index.php dan menulis API dengan cara ini:

$method = $_SERVER['REQUEST_METHOD'];
$request = split("/", substr(@$_SERVER['PATH_INFO'], 1));

switch ($method) {
  case 'PUT':
    ....some put action.... 
    break;
  case 'POST':
    ....some post action.... 
    break;
  case 'GET':
    ....some get action.... 
    break;
  case 'DELETE':
    ....some delete action.... 
    break;
}

OK, memang - saya belum tahu banyak tentang layanan web (belum). Tapi, bukankah akan lebih mudah untuk hanya menerima objek JSON melalui reguler POSTatau GET(yang akan berisi nama metode dan semua parameter) dan kemudian merespons dalam JSON juga. Kita dapat dengan mudah membuat serial / deserialize melalui PHP json_encode()dan json_decode()dan melakukan apa pun yang kita inginkan dengan data itu tanpa harus berurusan dengan metode permintaan HTTP yang berbeda.

Apakah saya melewatkan sesuatu?

PEMBARUAN 1:

Ok - setelah menggali berbagai API dan belajar banyak tentang XML-RPC , JSON-RPC , SOAP , REST Saya sampai pada kesimpulan bahwa jenis API ini masuk akal. Sebenarnya pertukaran stack cukup banyak menggunakan pendekatan ini di situs mereka dan saya pikir orang-orang ini tahu apa yang mereka lakukan Stack Exchange API .

Stann
sumber
4
Mengapa memaksakan payload JSON? Bagaimana jika tidak ada JSON, dan ini GET lama?
Mike DeSimone
1
Iya. w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
Ignacio Vazquez-Abrams

Jawaban:

200

Gagasan RE Presentational S tate T ransfer bukan tentang mengakses data dengan cara sesederhana mungkin.

Anda menyarankan menggunakan permintaan pos untuk mengakses JSON, yang merupakan cara yang sah untuk mengakses / memanipulasi data.

REST adalah metodologi untuk akses data yang bermakna . Ketika Anda melihat permintaan di REST, itu harus segera menilai apa yang terjadi dengan data.

Sebagai contoh:

GET: /cars/make/chevrolet

kemungkinan akan mengembalikan daftar mobil chevy. Api REST yang baik bahkan mungkin memasukkan beberapa opsi keluaran di querystring seperti ?output=jsonatau ?output=htmlyang akan memungkinkan accessor untuk memutuskan format informasi yang harus dikodekan.

Setelah sedikit berpikir tentang cara memasukkan data yang masuk ke dalam REST API, saya menyimpulkan bahwa cara terbaik untuk menentukan tipe data secara eksplisit adalah melalui ekstensi file yang sudah ada seperti .js,.json , .html, atau .xml. Ekstensi file yang hilang akan default ke format apa pun yang default (seperti JSON); ekstensi file yang tidak didukung dapat mengembalikan 501 Not Implementedkode status .

Contoh lain:

POST: /cars/
{ make:chevrolet, model:malibu, colors:[red, green, blue, grey] }

kemungkinan akan membuat malibu chevy baru di db dengan warna terkait. Saya katakan kemungkinan karena api REST tidak perlu berhubungan langsung dengan struktur database. Ini hanya antarmuka masking sehingga data yang sebenarnya dilindungi (anggap saja seperti accessors dan mutators untuk struktur database).

Sekarang kita perlu beralih ke masalah idempotensi . Biasanya REST mengimplementasikan CRUD melalui HTTP. HTTP menggunakan GET, PUT, POSTdan DELETEuntuk permintaan.

Implementasi REST yang sangat sederhana dapat menggunakan pemetaan CRUD berikut:

Create -> Post
Read   -> Get
Update -> Put
Delete -> Delete

Ada masalah dengan implementasi ini: Posting didefinisikan sebagai metode non-idempoten. Ini berarti bahwa panggilan selanjutnya dari metode Post yang sama akan menghasilkan status server yang berbeda . Dapatkan, Pasang, dan Hapus, idempoten; yang berarti bahwa memanggil mereka beberapa kali akan menghasilkan keadaan server yang identik.

Ini berarti permintaan seperti:

Delete: /cars/oldest

sebenarnya bisa diimplementasikan sebagai:

Post: /cars/oldest?action=delete

Sedangkan

Delete: /cars/id/123456

akan menghasilkan status server yang sama jika Anda memanggilnya sekali, atau jika Anda memanggilnya 1000 kali.

Cara yang lebih baik untuk menangani penghapusan oldestitem adalah dengan meminta:

Get: /cars/oldest

dan gunakan IDdari data yang dihasilkan untuk membuat deletepermintaan:

Delete: /cars/id/[oldest id]

Masalah dengan metode ini adalah jika /carsitem lain ditambahkan antara saat /oldestdiminta dan ketika deletedikeluarkan.

zzzzBov
sumber
3
@Andre merupakan kombinasi dari sejumlah alasan: Mengikuti pedoman HTTP berarti bahwa Anda (kemungkinan) akan memiliki lebih sedikit masalah kompatibilitas ke belakang ketika terjadi perubahan; menggunakan formulir html via POST akan memperingatkan pengguna untuk beberapa pengiriman data yang sama (ini untuk mencegah transaksi non-idempoten); mengikuti praktik terbaik yang terdefinisi dengan baik adalah, well.. praktik terbaik. Istirahat tidak didefinisikan dengan implementasi tertentu dalam pikiran, yang memungkinkan Anda untuk menggunakannya sesuai keinginan Anda. Saya sarankan mengambil keuntungan dari semua kode kesalahan HTTP dan metode permintaan, tetapi Anda diizinkan melakukannya
sesuka
4
Jadi masalah dengan jawaban ini (itu adalah jawaban yang layak, tetapi tidak lengkap) adalah bahwa itu tidak menjawab pertanyaan utama yang dia tanyakan: Mengapa Anda akan menggunakan kata kerja HTTP dan URI daripada data JSON khusus (mungkin semacam Sintaks doa API berbasis JSON). Anda dapat membuat sintaks JSON khusus sehingga "segera ... apparant apa yang terjadi dengan data". Yang tidak bisa Anda lakukan adalah dengan mudah menggunakan fasilitas bawaan dan lapisan jaringan di atas HTTP seperti Anda bisa menggunakan API yang mengikuti semua konvensi REST. Bukan berarti jawaban saya sempurna, tentu saja;)
Merlyn Morgan-Graham
4
@Andre: Contoh yang digunakan entri wiki adalah otentikasi, caching, dan negosiasi jenis konten. Sekarang saya lebih memikirkannya, Anda mungkin dapat menggunakan ini dengan antarmuka gaya RPC, tetapi godaan akan sering untuk menerapkan sistem Anda sendiri dari awal, atau menyusun integrasi ke sistem yang ada. Dengan REST Anda dapat menggunakan integrasi bawaan, dan mengadministrasikannya di server web. Ini berarti kopling yang lebih longgar, yang berarti Anda harus menerapkan lebih sedikit, dan berarti aplikasi Anda jauh lebih fleksibel untuk mengubah opsi di masa depan dengan kode yang lebih rendah dan dampak pengujian.
Merlyn Morgan-Graham
10
Alih-alih HAPUS: / mobil / tertua, bagaimana dengan GET: / mobil / tertua diikuti oleh HAPUS? Dengan begitu, Anda memiliki dua perintah idempoten yang terpisah.
Neil
3
+1; Saya setuju ini adalah jawaban yang bagus (saya akan membahasnya lagi untuk kesenangan dan keuntungan). POST: /cars/oldestmenjadi pengganti DELETE tidak masuk akal. Sesuatu seperti - POST: /cars/oldest/deletemungkin, kurasa aku lebih suka solusi Neil. Satu-satunya keuntungan yang diberikan oleh delete langsung daripada solusi get-id-delete-id adalah atomicity. Saya ingin pembenaran bisnis yang jelas dengan skenario yang tidak dibuat-buat sebelum saya menerapkan hal seperti itu. Anda tidak perlu mendukung semua kata kerja pada semua objek / url.
Merlyn Morgan-Graham
39

Ini adalah pertanyaan keamanan dan pemeliharaan.

metode yang aman

Jika memungkinkan, Anda harus menggunakan metode 'aman' (searah) seperti GET dan HEAD untuk membatasi potensi kerentanan.

metode idempoten

Kapan pun memungkinkan, Anda harus menggunakan metode 'idempoten' seperti GET, HEAD, PUT dan DELETE, yang tidak dapat memiliki efek samping dan karena itu lebih rentan kesalahan / mudah dikendalikan.

Sumber

markus
sumber
1
Maaf, tetapi bagaimana metode PUT dan DELETE idempoten? Mereka mempengaruhi keadaan server dan datanya!
Mahmoud Al-Qudsi
27
@ Komputer: Melakukan PUT yang sama atau HAPUS yang sama menghasilkan kondisi akhir yang sama. Itulah yang dimaksud dengan "idempoten".
Ignacio Vazquez-Abrams
4
Untuk klarifikasi lebih lanjut: operasi F idempoten, jika aplikasi tunggal dan beberapa aplikasi konsekuen keduanya menghasilkan hasil yang sama. Lebih tepatnya F adalah idempoten jika dan hanya jika F (x) = F (F (x)). Misalnya, Hapus adalah idempoten, karena ketika Anda menghapus item satu kali, atau menghapusnya beberapa kali, hasilnya sama: item tersebut dihapus sekali saja dengan aplikasi hapus pertama dan tidak ada yang terjadi dalam aplikasi hapus kedua atau ketiga.
qartal
1
Namun dalam hal penciptaan, ketika Anda membuat catatan baru dengan perintah buat, dan mengeluarkan perintah yang sama lagi, dua catatan (mungkin) dibuat (meskipun keduanya mencerminkan informasi yang sama).
qartal
qartal - definisi fungsional Anda untuk idempoten harus 'F (X) = F (X) F (X)'. Cara yang bagus untuk mengucapkannya.
Gerard ONeill
26

Singkatnya, REST menekankan kata benda di atas kata kerja. Ketika API Anda menjadi lebih kompleks, Anda menambahkan lebih banyak hal, daripada lebih banyak perintah.

Neil
sumber
2
Saya mengalami sedikit kesulitan untuk menyelesaikan masalah ini. Posting ini ( lornajane.net/posts/2013/... ) bahwa kata kerjanya harus berasal dari permintaan HTTP sehingga URI hanya akan berisi kata benda yang telah dibersihkan sedikit demi sedikit bagi saya
icc97
9

Anda bertanya :

bukankah akan lebih mudah untuk hanya menerima objek JSON melalui $ _POST normal dan kemudian merespons dalam JSON juga

Dari Wikipedia di REST :

Aplikasi RESTful memaksimalkan penggunaan antarmuka yang sudah ada, didefinisikan dengan baik dan kemampuan built-in lainnya yang disediakan oleh protokol jaringan yang dipilih, dan meminimalkan penambahan fitur khusus aplikasi baru di atasnya.

Dari apa (kecil) yang pernah saya lihat, saya percaya ini biasanya dicapai dengan memaksimalkan penggunaan kata kerja HTTP yang ada, dan merancang skema URL untuk layanan Anda yang sekuat dan jelas mungkin.

Protokol data khusus (meskipun dibangun di atas yang standar, seperti SOAP atau JSON) tidak disarankan, dan harus diminimalkan agar sesuai dengan ideologi REST.

SOAP RPC melalui HTTP, di sisi lain, mendorong setiap perancang aplikasi untuk mendefinisikan kosakata kata benda dan kata kerja yang baru dan sewenang-wenang (misalnya getUsers (), savePurchaseOrder (...)), biasanya dilapiskan ke kata kerja 'POST' HTTP. Ini mengabaikan banyak kemampuan HTTP yang ada seperti otentikasi, caching, dan negosiasi jenis konten, dan dapat membuat perancang aplikasi menciptakan kembali banyak fitur ini di dalam kosa kata baru.

Objek aktual yang Anda kerjakan dapat dalam format apa pun. Idenya adalah untuk menggunakan kembali HTTP sebanyak mungkin untuk mengekspos operasi Anda yang ingin dilakukan pengguna pada sumber daya tersebut (kueri, manajemen negara / mutasi, penghapusan).

Anda bertanya :

Apakah saya melewatkan sesuatu?

Ada banyak lagi yang perlu diketahui tentang REST dan sintaksis URI / HTTP itu sendiri. Sebagai contoh, beberapa kata kerja idempoten, yang lain tidak. Saya tidak melihat apa-apa tentang ini dalam pertanyaan Anda, jadi saya tidak repot-repot mencoba menyelami itu. Jawaban lain dan Wikipedia sama-sama memiliki banyak informasi bagus.

Juga, ada banyak hal untuk dipelajari tentang berbagai teknologi jaringan yang dibangun di atas HTTP yang dapat Anda manfaatkan jika Anda menggunakan API yang benar-benar tenang. Saya akan mulai dengan otentikasi.

Merlyn Morgan-Graham
sumber
8

Dalam hal menggunakan ekstensi untuk menentukan tipe data. Saya perhatikan bahwa API MailChimp melakukannya, tapi saya rasa ini bukan ide yang baik.

GET /zzz/cars.json/1

GET /zzz/cars.xml/1

Suara saya seperti ide yang bagus, tapi saya pikir pendekatan "lebih tua" lebih baik - menggunakan header HTTP

GET /xxx/cars/1
Accept: application/json

Header HTTP juga jauh lebih baik untuk komunikasi tipe data silang (jika seseorang membutuhkannya)

POST /zzz/cars
Content-Type: application/xml     <--- indicates we sent XML to server
Accept: application/json          <--- indicates we want get data back in JSON format  
Pawel Cioch
sumber
4

Apakah saya melewatkan sesuatu?

Iya. ;-)

Fenomena ini ada karena kendala antarmuka yang seragam . REST suka menggunakan standar yang sudah ada alih-alih menciptakan kembali roda. Standar HTTP telah terbukti sangat terukur (web berfungsi untuk sementara waktu). Kenapa kita harus memperbaiki sesuatu yang tidak rusak ?!

Catatan: Kendala antarmuka seragam adalah penting jika Anda ingin memisahkan klien dari layanan. Ini mirip dengan mendefinisikan antarmuka untuk kelas untuk memisahkan mereka dari satu sama lain. Ofc. di sini antarmuka yang seragam terdiri dari standar seperti HTTP , tipe MIME , URI , RDF , vocab data tertaut , hydra vocab , dll ...

inf3rno
sumber
2

Semantik yang baik penting dalam pemrograman.

Memanfaatkan lebih banyak metode selain GET / POST akan membantu karena akan meningkatkan keterbacaan kode Anda dan membuatnya lebih mudah untuk dipelihara.

Mengapa?

Karena Anda tahu GET akan mengambil data dari api Anda. Anda tahu POST akan menambahkan data baru ke sistem Anda. Anda tahu PUT akan membuat pembaruan. HAPUS akan menghapus baris dll, dll,

Saya biasanya menyusun Layanan Web RESTFUL saya sehingga saya memiliki fungsi panggil balik bernama hal yang sama dengan metode.

Saya menggunakan PHP, jadi saya menggunakan function_exists (saya pikir itu namanya). Jika fungsi tidak ada, saya melempar 405 (METODE TIDAK DIIZINKAN).

HumbleWebDev
sumber
2

Bill Venners: Dalam posting blog Anda yang berjudul "Mengapa REST Gagal," Anda mengatakan bahwa kami membutuhkan keempat kata kerja HTTP — GET, POST, PUT, dan DELETE — dan menyesalkan bahwa vendor browser hanya GET dan POST. "Mengapa kita membutuhkan keempatnya? kata kerja? Mengapa GET dan POST tidak cukup?

Elliotte Rusty Harold: Ada empat metode dasar dalam HTTP: GET, POST, PUT, dan DELETE. GET digunakan sebagian besar waktu. Ini digunakan untuk apa pun yang aman, yang tidak menimbulkan efek samping. GET dapat di-bookmark, di-cache, ditautkan, dilewatkan melalui server proxy. Ini adalah operasi yang sangat kuat, operasi yang sangat berguna.

Sebaliknya POST mungkin adalah operasi yang paling kuat. Itu bisa melakukan apa saja. Tidak ada batasan untuk apa yang bisa terjadi, dan akibatnya, Anda harus sangat berhati-hati dengannya. Anda tidak membookmarknya. Anda tidak menyimpannya. Anda tidak mengambilnya sebelumnya. Anda tidak melakukan apa pun dengan POST tanpa meminta pengguna. Apakah Anda ingin melakukan ini? Jika pengguna menekan tombol, Anda dapat POST beberapa konten. Tetapi Anda tidak akan melihat semua tombol pada halaman, dan mulai menekannya secara acak. Sebaliknya, browser mungkin melihat semua tautan pada halaman dan mengambilnya sebelumnya, atau mengambilnya terlebih dahulu, yang menurut mereka paling mungkin diikuti selanjutnya. Dan pada kenyataannya beberapa browser dan ekstensi Firefox dan berbagai alat lain telah mencoba melakukan itu pada satu titik atau yang lain.

PUT dan DELETE berada di antara GET dan POST. Perbedaan antara PUT atau DELETE dan POST adalah bahwa PUT dan DELETE adalah * idempoten, sedangkan POST tidak. PUT dan DELETE dapat diulang jika perlu. Katakanlah Anda mencoba mengunggah halaman baru ke situs. Katakanlah Anda ingin membuat halaman baru di http://www.example.com/foo.html, jadi Anda mengetik konten Anda dan Anda Taruh di URL itu. Server membuat halaman itu di URL yang Anda berikan. Sekarang, anggaplah karena suatu alasan koneksi jaringan Anda turun. Anda tidak yakin, apakah permintaannya berhasil atau tidak? Mungkin jaringannya lambat. Mungkin ada masalah server proxy. Jadi tidak apa-apa untuk mencobanya lagi, atau lagi — sebanyak yang Anda suka. Karena MENEMPATKAN dokumen yang sama ke URL yang sama sepuluh kali tidak akan ada bedanya dengan meletakkannya sekali. Hal yang sama berlaku untuk DELETE. Anda dapat HAPUS sesuatu sepuluh kali, dan itu sama dengan menghapusnya sekali.

Sebaliknya, POST, dapat menyebabkan sesuatu yang berbeda terjadi setiap kali. Bayangkan Anda keluar dari toko online dengan menekan tombol beli. Jika Anda mengirim permintaan POST itu lagi, Anda bisa membeli semuanya di keranjang Anda untuk kedua kalinya. Jika Anda mengirimnya lagi, Anda telah membelinya untuk ketiga kalinya. Itu sebabnya browser harus sangat berhati-hati dalam mengulangi operasi POST tanpa persetujuan pengguna eksplisit, karena POST dapat menyebabkan dua hal terjadi jika Anda melakukannya dua kali, tiga hal jika Anda melakukannya tiga kali. Dengan PUT dan DELETE, ada perbedaan besar antara nol permintaan dan satu, tetapi tidak ada perbedaan antara satu permintaan dan sepuluh permintaan.

Silakan kunjungi url untuk lebih jelasnya. http://www.artima.com/lejava/articles/why_put_and_delete.html

Memperbarui:

Metode idempoten HTTP idempoten adalah metode HTTP yang dapat dipanggil berkali-kali tanpa hasil yang berbeda. Tidak masalah jika metode ini dipanggil hanya sekali, atau sepuluh kali lipat. Hasilnya harus sama. Sekali lagi, ini hanya berlaku untuk hasilnya, bukan sumber daya itu sendiri. Ini masih dapat dimanipulasi (seperti cap waktu pembaruan, asalkan informasi ini tidak dibagikan dalam representasi sumber daya (saat ini).

Perhatikan contoh-contoh berikut:

a = 4;

a ++;

Contoh pertama adalah idempoten: tidak peduli berapa kali kita menjalankan pernyataan ini, a akan selalu 4. Contoh kedua bukan idempoten. Menjalankan ini 10 kali akan menghasilkan hasil yang berbeda seperti ketika menjalankan 5 kali. Karena kedua contoh mengubah nilai a, keduanya adalah metode yang tidak aman.

Bimal Das
sumber
1
Tentang contoh halaman baru, bukankah POST harus digunakan dengan cara itu, sementara PUT untuk pembaruan? Membuat halaman baru adalah proses yang menghasilkan hasil baru setiap kali, sementara hasil edit yang sama dapat diulangi berapapun kali, lakukan hasil yang sama setiap kali. Tapi ungkapan dan penjelasannya bagus.
Spyryto
0

Pada dasarnya REST adalah ( wiki ):

  1. Arsitektur client-server
  2. Kewarganegaraan
  3. Cacheability
  4. Sistem berlapis
  5. Kode sesuai permintaan (opsional)
  6. Antarmuka yang seragam

REST bukan protokol, itu prinsip. Uris dan metode berbeda - seseorang yang disebut praktik terbaik.

MAX
sumber