Method HTTP
GET, POST, PUT, PATCH, dan DELETE, serta mana yang aman untuk diulang.
Method adalah kata pertama di setiap request. Ia memberi tahu server apa yang ingin Anda lakukan pada resource di URL itu. URL yang sama, /api/Books/1masuk untuk melihat, mengembalikan sebuah buku dengan GET, mengubahnya dengan PUT atau PATCH, dan menghapusnya dengan DELETE. Sebagian besar API memakai lima method untuk hampir semua hal, dan sesekali muncul beberapa lagi.
Di method-lah perbedaan antara browser dan alat pengujian mulai terasa. Bilah alamat hanya mengirim GET. Untuk sisanya Anda butuh curl, Postman, atau tombol Kirim seperti yang ada di halaman ini. Contoh yang mengubah data bersama memakai curl, supaya tombol Kirim di halaman ini tidak mengubah data yang sedang dilihat pembaca lain. Pelajaran 6, Mengirim request dengan curl dan Postman, menyiapkan kedua alat itu dengan benar. Jika Anda belum punya curl, baca saja contoh curl di sini dan jalankan setelah pelajaran itu.
Lima method sehari-hari
| Method | Fungsi | Status sukses yang umum |
|---|---|---|
GET | Membaca resource atau daftar. Tidak mengirim body. | 200 |
POST | Membuat resource baru, atau memicu sebuah aksi. | 201, kadang 200 atau 202 |
PUT | Mengganti resource dengan body yang Anda kirim. | 200 atau 204 |
PATCH | Mengubah sebagian field sebuah resource. | 200 atau 204 |
DELETE | Menghapus resource. | 200 atau 204 |
Endpoint Methods di API ini masing-masing menerima satu kata kerja dan mendeskripsikan apa yang diterimanya. Kirim sebuah GET:
/api/methods/get?x=1Dan sebuah POST dengan body:
/api/methods/post{"hello":"world"}Endpoint ini tidak menyimpan apa pun. Untuk melihat apa yang dilakukan method pada data sungguhan, Anda butuh sebuah resource, dan sisa pelajaran ini memakai Books.
POST membuat
Buat sebuah buku:
curl -i -X POST https://api.testingapis.com/api/Books \
-H "Content-Type: application/json" \
-d '{"title":"The Pragmatic Programmer","author":"David Thomas",
"isbn":"9780135957059","genre":"programming","publishedYear":2019,
"pages":352,"language":"English","price":42.5,"rating":4.6,
"available":true,"tags":["career"]}'HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8
{
"message": "Book created successfully",
"data": {
"id": 29,
"title": "The Pragmatic Programmer",
"author": "David Thomas",
"isbn": "9780135957059",
"genre": "programming",
"publishedYear": 2019,
"pages": 352,
"language": "English",
"price": 42.5,
"rating": 4.6,
"available": true,
"tags": ["career"]
}
}Server menjawab 201 Created, memberi ID 29, dan mengembalikan data baru itu. Anda akan mendapat ID yang berbeda, karena orang lain juga membuat buku. Itulah hal pertama yang diuji pada POST mana pun: server yang memilih ID-nya, dan tes Anda harus membacanya dari response alih-alih menebaknya.
Banyak API juga mengirim header Location pada 201 berisi URL resource baru, misalnya Location: /api/Books/29masuk untuk melihat. API ini tidak. Standarnya tidak mewajibkan, tetapi jika dokumentasi menjanjikannya, itu bug.
Sekarang jalankan POST yang sama untuk kedua kalinya. Anda mendapat buku kedua dengan ID baru, identik kecuali nomor itu. POST tidak aman untuk diulang: setiap panggilan membuat sesuatu yang baru. Ingat ini untuk tabel di bawah.
PUT mengganti, PATCH mengubah
Kedua method memperbarui data, dan orang terus-menerus mencampuradukkannya. Perbedaannya terlihat pada field yang Anda lewatkan.
PATCH
Ubah hanya harga buku 29:
curl -X PATCH https://api.testingapis.com/api/Books/29 \
-H "Content-Type: application/json" \
-d '{"price":39.99}'{
"message": "Book patched successfully",
"changed": ["price"],
"ignored": [],
"data": {
"id": 29,
"title": "The Pragmatic Programmer",
"author": "David Thomas",
"isbn": "9780135957059",
"genre": "programming",
"publishedYear": 2019,
"pages": 352,
"language": "English",
"price": 39.99,
"rating": 4.6,
"available": true,
"tags": ["career"]
}
}Hanya harganya yang berubah. Semua yang tidak Anda sebut tetap bernilai sama. API ini juga memberi tahu field mana yang diubahnya, sesuatu yang jarang dan berguna untuk pengujian.
PUT
Sekarang kirim PUT dengan hanya tiga field:
curl -X PUT https://api.testingapis.com/api/Books/29 \
-H "Content-Type: application/json" \
-d '{"title":"The Pragmatic Programmer","author":"David Thomas","price":39.99}'{
"message": "Book updated successfully",
"data": {
"id": 29,
"title": "The Pragmatic Programmer",
"author": "David Thomas",
"isbn": "",
"genre": "",
"publishedYear": 0,
"pages": 0,
"language": "",
"price": 39.99,
"rating": 0,
"available": false,
"tags": []
}
}ISBN, genre, tahun, jumlah halaman, bahasa, rating, dan tag hilang. PUT berarti "ini versi baru yang lengkap dari resource ini". Field apa pun yang tidak Anda kirim diganti dengan nilai kosong atau nol. API melakukan persis seperti definisi PUT, dan tetap saja menghapus sebagian besar data karena klien mengirim body yang tidak lengkap.
Ini salah satu bug nyata yang paling umum di aplikasi. Seorang developer memakai PUT untuk memperbarui satu field, hanya mengirim field itu, dan semua field lain di data itu terhapus diam-diam. Saat menguji fitur pembaruan, kirim body yang tidak lengkap lalu GET datanya untuk melihat apa yang tersisa.
Beberapa API menanganinya secara berbeda. Mereka memperlakukan PUT dengan field yang hilang seperti PATCH, atau menolaknya dengan 400 karena field wajib tidak ada. Opsi terakhir bisa dibilang paling aman. Apa yang Anda uji tergantung dokumentasinya, tetapi Anda selalu mengujinya.
DELETE menghapus
Hapus buku 29, lalu coba hapus lagi:
$ curl -X DELETE https://api.testingapis.com/api/Books/29
{"message":"Book deleted successfully"} (200 OK)
$ curl -X DELETE https://api.testingapis.com/api/Books/29
{"status":404,"error":"Not Found","message":"Book with ID 29 does not exist."} (404 Not Found)Panggilan pertama mengembalikan 200 dengan pesan. Yang kedua mengembalikan 404, karena tidak ada lagi yang bisa dihapus. Setelah menghapus, periksa juga bahwa GET untuk ID yang sama mengembalikan 404. Beberapa sistem hanya menandai data sebagai terhapus dan terus mengembalikannya, dan itu bug jika dokumentasi mengatakan sebaliknya.
Method yang aman dan idempoten
Dua sifat dari standar HTTP menentukan bagaimana klien dan tes boleh memperlakukan setiap method.
Method yang aman tidak mengubah apa pun di server. Anda bisa memanggilnya sesering yang Anda mau. Method yang idempoten bisa mengubah sesuatu, tetapi memanggilnya dua kali punya efek yang sama di server dengan memanggilnya sekali.
| Method | Aman | Idempoten |
|---|---|---|
GET | Ya | Ya |
HEAD | Ya | Ya |
OPTIONS | Ya | Ya |
PUT | Tidak | Ya |
DELETE | Tidak | Ya |
POST | Tidak | Tidak |
PATCH | Tidak | Tidak dijamin |
PUT idempoten karena mengirim data lengkap yang sama dua kali meninggalkan data yang sama. DELETE idempoten meskipun panggilan kedua mendapat 404: response-nya berbeda, tetapi keadaan server (buku 29 tidak ada) sama saja. Idempotensi menyangkut efeknya, bukan response-nya. POST tidak idempoten, seperti yang Anda lihat saat POST kedua membuat buku kedua. PATCH bisa ke mana saja. Mengatur harga menjadi 39.99 itu idempoten; patch yang berbunyi "tambah 1 ke jumlah stok" tidak.
Ini penting karena jaringan bisa gagal. Jika sebuah request timeout, klien tidak tahu apakah server menerimanya. Mengulang GET atau PUT tidak berbahaya. Mengulang POST bisa menagih kartu dua kali. Browser, proxy, dan library HTTP memakai aturan ini saat memutuskan apakah akan mengulang sendiri, dan Timeout, retry, dan rate limit menunjukkan cara API membuat POST aman diulang dengan idempotency key.
Bagi penguji, aturan ini memberi kasus uji secara gratis. Panggil GET dan periksa bahwa tidak ada yang berubah. Panggil PUT dua kali dan periksa bahwa panggilan kedua tidak membuat atau menggandakan apa pun. GET yang mengubah data (seperti /api/deleteUser?id=5masuk untuk melihat, yang memang ada di beberapa codebase) adalah bug desain, karena crawler, pratinjau tautan, dan prefetch browser semuanya mengirim request GET tanpa bertanya.
HEAD dan OPTIONS
HEAD adalah GET tanpa body. Server mengirim status dan header yang sama seperti untuk GET, lalu berhenti di situ. Klien memakainya untuk memeriksa apakah sesuatu ada atau seberapa besar sebuah file tanpa mengunduhnya.
HTTP/1.1 200 OK
x-message: HEAD request received. Responses to HEAD carry headers only.
x-method: HEADOPTIONS menanyakan apa yang diizinkan di sebuah URL. Browser mengirimnya otomatis sebelum beberapa request lintas origin (sebuah "preflight"), itulah sebabnya ia muncul di log jaringan meskipun tidak ada kode yang memanggilnya. Anda jarang mengujinya langsung kecuali Anda menangani pengaturan CORS.
/api/methods/optionsMemakai method yang salah
/api/methods/get hanya menerima GET. Kirimi ia POST dengan curl -i -X POST https://api.testingapis.com/api/methods/get:
HTTP/1.1 405 Method Not Allowed
Content-Length: 0
allow: GET405 Method Not Allowed berarti URL-nya ada tetapi tidak mendukung method itu. Header allow mendaftar method yang didukungnya. POST ke satu buku, yang tidak masuk akal karena buku dibuat di /api/Booksmasuk untuk melihat, mendapat perlakuan yang sama:
HTTP/1.1 405 Method Not Allowed
Content-Length: 0
allow: DELETE, GET, HEAD, PATCH, PUTMengirim setiap method ke setiap endpoint adalah tes murah yang menemukan masalah nyata. Anda mencari method yang seharusnya ditolak tetapi tidak (DELETE yang berfungsi di endpoint yang seharusnya hanya-baca), dan 500 atau 404 di tempat yang seharusnya 405. Perhatikan bahwa API ini mengembalikan 405 dengan body kosong, sementara error lainnya berupa JSON. Klien yang mengharapkan body error JSON di setiap 4xx akan tersandung di sini.
Latihan
Kerjakan ini dengan curl (atau kembali ke sini setelah pelajaran curl).
- Buat buku dengan POST. Catat ID-nya.
- PATCH judulnya. GET buku itu dan pastikan hanya judulnya yang berubah.
- PUT buku itu dengan body yang berisi semua field kecuali
tags. Apa yang terjadi pada tag-nya? - Kirim PUT yang sama lagi. Apakah ada yang berubah pada kali kedua?
- DELETE buku itu, GET, lalu DELETE lagi. Catat ketiga kode status.
- Kirim DELETE ke
/api/Booksmasuk untuk melihat (tanpa ID). Sebelum menjalankannya, tebak kode statusnya. Lalu periksa headerallow.