Pertanyaan HTTP GET dengan badan permintaan


Saya sedang mengembangkan jejaring RESTEN baru untuk aplikasi kami.

Ketika melakukan GET pada entitas tertentu, klien dapat meminta konten dari entitas. Jika mereka ingin menambahkan beberapa parameter (misalnya mengurutkan daftar) mereka dapat menambahkan parameter ini dalam string kueri.

Sebagai alternatif, saya ingin orang-orang dapat menentukan parameter-parameter ini dalam tubuh permintaan. HTTP / 1.1 tampaknya tidak secara eksplisit melarang ini. Ini akan memungkinkan mereka untuk menentukan informasi lebih lanjut, mungkin membuatnya lebih mudah untuk menentukan permintaan xml kompleks.

Pertanyaan saya:

  • Apakah ini ide yang bagus?
  • Apakah klien HTTP akan mengalami masalah dengan menggunakan badan permintaan dalam permintaan GET?

http://tools.ietf.org/html/rfc2616


1410
2018-06-10 20:47


asal


Jawaban:


Komentar Roy Fielding tentang memasukkan tubuh dengan permintaan GET.

Iya nih. Dengan kata lain, pesan permintaan HTTP apa pun dibolehkan memuat   badan pesan, dan dengan demikian harus menguraikan pesan dengan memikirkan hal itu.   Semantik server untuk GET, bagaimanapun, dibatasi sedemikian rupa sehingga sebuah badan,   jika ada, tidak memiliki makna semantik untuk permintaan tersebut. Persyaratan   pada parsing terpisah dari persyaratan pada semantik metode.

Jadi, ya, Anda dapat mengirim sebuah tubuh dengan GET, dan tidak, itu tidak pernah berguna   untuk melakukannya.

Ini adalah bagian dari desain berlapis HTTP / 1.1 yang akan menjadi   bersihkan kembali setelah spesifikasi dipartisi (pekerjaan sedang berlangsung).

.... Roy

Ya, Anda dapat mengirim badan permintaan dengan GET tetapi seharusnya tidak memiliki arti. Jika Anda memberi arti dengan menguraikannya di server dan mengubah tanggapan Anda berdasarkan isinya, maka Anda mengabaikan rekomendasi ini spek HTTP / 1.1, bagian 4.3:

[...] jika metode permintaan      tidak termasuk semantik yang ditentukan untuk badan entitas, lalu      Badan Pesan HARUS diabaikan saat menangani permintaan.

Dan deskripsi metode GET di spek HTTP / 1.1, bagian 9.3:

Metode GET berarti mengambil informasi apa pun ([...]) diidentifikasi oleh Request-URI.

yang menyatakan bahwa permintaan-tubuh bukan bagian dari identifikasi sumber daya dalam permintaan GET, hanya permintaan URI.


1200
2018-06-11 20:27



Sementara kamu bisa lakukan itu, sejauh itu tidak secara eksplisit dilarang oleh spesifikasi HTTP, saya akan menyarankan untuk menghindarinya hanya karena orang tidak mengharapkan hal-hal bekerja seperti itu. Ada banyak fase dalam rantai permintaan HTTP dan sementara mereka "kebanyakan" sesuai dengan spesifikasi HTTP, satu-satunya hal yang Anda yakini adalah bahwa mereka akan berperilaku seperti yang biasa digunakan oleh peramban web. (Saya memikirkan hal-hal seperti proksi transparan, akselerator, toolkit A / V, dll.)

Inilah semangat di balik itu Prinsip Ketahanan kira-kira "jadilah liberal dalam apa yang Anda terima, dan konservatif dalam apa yang Anda kirim", Anda tidak ingin mendorong batas-batas spesifikasi tanpa alasan yang baik.

Namun, jika Anda memiliki alasan yang kuat, lakukanlah.


234
2018-06-10 20:53



Anda mungkin akan mengalami masalah jika Anda pernah mencoba memanfaatkan caching. Proxy tidak akan melihat dalam tubuh GET untuk melihat apakah parameter berdampak pada respons.


116
2018-06-10 21:10



Bukan keduanya restclient maupun REST console mendukung ini tetapi curl tidak.

Itu Spesifikasi HTTP mengatakan di bagian 4.3

Sebuah badan pesan TIDAK HARUS dimasukkan dalam permintaan jika spesifikasi metode permintaan (bagian 5.1.1) tidak memungkinkan pengiriman badan-entitas dalam permintaan.

Bagian 5.1.1 mengalihkan kita ke bagian 9.x untuk berbagai metode. Tak satu pun dari mereka secara eksplisit melarang masuknya sebuah badan pesan. Namun...

Bagian 5.2 kata

Sumber daya yang tepat diidentifikasi oleh permintaan Internet ditentukan dengan memeriksa baik bidang URI Permintaan-URI dan Host.

dan Bagian 9.3 kata

Metode GET berarti mengambil informasi apa pun (dalam bentuk entitas) yang diidentifikasi oleh Request-URI.

Yang bersama-sama menunjukkan bahwa ketika memproses permintaan GET, server tidak wajib untuk memeriksa hal lain yang ada pada bidang header Request-URI dan Host.

Singkatnya, spesifikasi HTTP tidak mencegah Anda mengirim pesan-tubuh dengan GET tetapi ada ambiguitas yang cukup bahwa itu tidak akan mengejutkan saya jika tidak didukung oleh semua server.


60
2018-03-27 10:41



Elasticsearch menerima permintaan GET dengan tubuh. Bahkan tampaknya ini adalah cara yang lebih disukai: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/common-options.html#_request_body_in_query_string

Beberapa pustaka klien (seperti pengandar Ruby) dapat mencatat perintah menangis ke stdout dalam mode pengembangan dan menggunakan sintaks ini secara ekstensif.


36
2017-12-03 11:15



Apa yang Anda coba capai telah dilakukan untuk waktu yang lama dengan metode yang jauh lebih umum, dan yang tidak bergantung pada penggunaan payload dengan GET.

Anda dapat dengan mudah membangun mediatype pencarian spesifik Anda, atau jika Anda ingin lebih RESTful, gunakan sesuatu seperti OpenSearch, dan POST permintaan ke URI yang diinstruksikan server, katakan / cari. Server kemudian dapat menghasilkan hasil pencarian atau membangun URI akhir dan mengarahkan ulang menggunakan 303.

Ini memiliki keuntungan dengan mengikuti metode PRG tradisional, membantu perantara cache membuat cache hasil, dll.

Yang mengatakan, URI dikodekan pula untuk apa pun yang bukan ASCII, dan begitu juga aplikasi / x-www-form-urlencoded dan multipart / form-data. Saya akan merekomendasikan menggunakan ini daripada membuat format json kustom lain jika niat Anda adalah untuk mendukung skenario ReSTful.


25
2018-06-10 22:47



Server mana yang akan mengabaikannya? - fijiaaron 30 Agustus '12 jam 21:27

Google misalnya melakukan lebih buruk daripada mengabaikannya, itu akan menganggapnya sebagai kesalahan!

Cobalah sendiri dengan netcat sederhana:

$ netcat www.google.com 80
GET / HTTP/1.1
Host: www.google.com
Content-length: 6

1234

(Isi 1234 diikuti oleh CR-LF, sehingga totalnya adalah 6 byte)

dan Anda akan mendapatkan:

HTTP/1.1 400 Bad Request
Server: GFE/2.0
(....)
Error 400 (Bad Request)
400. That’s an error.
Your client has issued a malformed or illegal request. That’s all we know.

Anda juga mendapatkan 400 Bad Request dari Bing, Apple, dll ... yang dilayani oleh AkamaiGhost.

Jadi saya tidak menyarankan menggunakan permintaan GET dengan entitas tubuh.


23
2018-06-29 21:26



Anda dapat mengirim GET dengan badan atau mengirim POST dan menyerahkan religiusitas RESTish (tidak terlalu buruk, 5 tahun yang lalu hanya ada satu anggota dari keyakinan itu - komentarnya terkait di atas).

Juga bukan keputusan yang bagus, tetapi mengirim tubuh GET dapat mencegah masalah untuk beberapa klien - dan beberapa server.

Melakukan POST mungkin memiliki kendala dengan beberapa kerangka RESTish.

Julian Reschke menyarankan di atas menggunakan header HTTP non-standar seperti "SEARCH" yang bisa menjadi solusi elegan, kecuali bahwa itu bahkan cenderung didukung.

Mungkin paling produktif untuk mendaftarkan klien yang dapat dan tidak dapat melakukan masing-masing di atas.

Klien yang tidak dapat mengirim GET dengan badan (yang saya tahu):

  • XmlHTTPRequest Fiddler

Klien yang dapat mengirim GET dengan badan:

  • kebanyakan browser

Server & pustaka yang dapat mengambil badan dari GET:

  • Apache
  • PHP

Server (dan proksi) yang menghapus sebuah badan dari GET:

  • ?

21
2017-08-30 21:41



Dari RFC 2616, bagian 4.3, "Badan Pesan":

Sebuah server HARUS membaca dan meneruskan pesan-tubuh pada setiap permintaan; jika   metode permintaan tidak termasuk semantik yang ditentukan untuk entitas-tubuh,   maka isi pesan HARUS diabaikan ketika menangani permintaan.

Artinya, server harus selalu membaca body permintaan apa pun yang diberikan dari jaringan (periksa Content-Length atau baca tubuh yang terbebani, dll). Juga, proksi harus meneruskan setiap badan permintaan yang mereka terima. Kemudian, jika RFC mendefinisikan semantik untuk tubuh untuk metode yang diberikan, server benar-benar dapat menggunakan tubuh permintaan dalam menghasilkan respons. Namun, jika RFC tidak mendefinisikan semantik untuk tubuh, maka server harus mengabaikannya.

Ini sejalan dengan kutipan dari Fielding di atas.

Bagian 9.3, "GET", menjelaskan semantik metode GET, dan tidak menyebutkan badan permintaan. Oleh karena itu, server harus mengabaikan setiap badan permintaan yang diterimanya pada permintaan GET.


16
2018-03-06 21:44



Saya mengajukan pertanyaan ini ke IETF HTTP WG. Komentar dari Roy Fielding (penulis dokumen http / 1.1 pada 1998) adalah itu

"... sebuah implementasi akan rusak untuk melakukan apa pun selain mengurai dan membuang tubuh itu jika diterima"

RFC 7213 (HTTPbis) menyatakan

"Payload dalam pesan permintaan GET tidak memiliki semantik yang ditentukan;"

Tampaknya jelas sekarang bahwa maksudnya adalah makna semantik pada tubuh permintaan GET dilarang, yang berarti bahwa tubuh permintaan tidak dapat digunakan untuk mempengaruhi hasilnya.

Ada proksi di luar sana yang akan melakukannya pastinya pecahkan permintaan Anda dengan berbagai cara jika Anda menyertakan sebuah badan di GET.

Jadi secara ringkas, jangan lakukan itu.


12
2017-07-28 01:06



Jika Anda benar-benar ingin mengirim tubuh JSON / XML yang dapat di-cache ke aplikasi web, satu-satunya tempat yang masuk akal untuk menempatkan data Anda adalah string kueri yang dienkode dengan RFC4648: Base 64 Encoding dengan URL dan Alphename Safe Alphabet. Tentu saja Anda hanya dapat urlencode JSON dan menempatkannya dalam nilai parameter param, tetapi Base64 memberikan hasil yang lebih kecil. Perlu diingat bahwa ada batasan ukuran URL, lihat Berapa panjang maksimum URL di berbagai browser? .

Anda mungkin berpikir bahwa padding Base64 = karakter mungkin buruk untuk nilai param URL, namun tampaknya tidak - lihat diskusi ini: http://mail.python.org/pipermail/python-bugs-list/2007-February/037195.html . Namun Anda tidak perlu memasukkan data yang di-enkode tanpa nama param karena string yang di-enkode dengan padding akan diartikan sebagai kunci param dengan nilai kosong. Saya akan menggunakan sesuatu seperti ?_b64=<encodeddata>.


7
2018-02-18 13:43