REST - Pengorbanan antara negosiasi konten melalui header Terima versus ekstensi

40

Saya sedang bekerja melalui merancang API yang tenang. Kami tahu kami ingin mengembalikan JSON dan XML untuk sumber daya apa pun yang diberikan. Saya telah berpikir kami akan melakukan sesuatu seperti ini:

GET /api/something?param1=value1
Accept:  application/xml (or application/json)

Namun, seseorang dikeluarkan menggunakan ekstensi untuk ini, seperti:

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Apa untungnya dengan pendekatan ini? Apakah yang terbaik untuk mengandalkan tajuk terima saat ekstensi tidak ditentukan, tetapi menghormati ekstensi saat ditentukan? Apakah ada kelemahan dari pendekatan itu?

Brandon Linton
sumber
Server web apa yang Anda gunakan? dan bagaimana cara mem-parsing URL?
Dipan Mehta
1
Saya tidak tahu tentang sisi teknis (server). Yang sedang berkata, saya lebih suka pendekatan Anda, karena menggunakan standar http, yang membuatnya lebih mudah untuk dipahami (misalnya ketika orang lain seharusnya melakukan pemeliharaan di atasnya beberapa tahun ke depan). Anda bisa mengandalkan ekstensi ketika menerima tidak ditentukan, atau memiliki nilai yang tidak terduga, tetapi saya akan selalu pergi dengan cara standar terlebih dahulu.
Treb
@Dipan Saya meretas ini dengan MVC4 Web API (masih dalam versi beta). Ini menggunakan abstraksi routing ASP.NET, yang cukup bagus.
Brandon Linton
1
@ Treb Ya saya jauh lebih suka menggunakan nilai header terima. Saya bertanya-tanya apakah ada kekurangan untuk mendukung keduanya.
Brandon Linton

Jawaban:

38

Ini, "Namun, secara filosofis - pendekatan pertama adalah satu-satunya pendekatan.", Dan ini "Pendekatan resmi resmi yang tepat adalah dengan menggunakan Accept: header." secara luas dianggap sebagai kasus, tetapi juga sama sekali tidak benar .

Berikut cuplikan singkat dari Roy Fielding (yang mendefinisikan REST) ​​...

"Bagian 6.2.1 tidak mengatakan bahwa negosiasi konten harus digunakan setiap saat." mengutip

Percakapan khusus itu dalam konteks tajuk 'Bahasa Terima:', tetapi hal yang sama berlaku untuk tajuk 'Terima:', sebagaimana dijelaskan kemudian dalam tanggapannya ...

"Saya tidak tahu mengapa orang tidak dapat melihat tautan kedua dan ketiga di halaman atas

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

yang mengarah ke dua edisi PDF. "

Maksudnya tidak ada masalah dalam menggunakan titik akhir yang berbeda untuk representasi berbeda dari data sumber yang sama. (Dalam hal ini satu .html endpoint dan dua endpoint .pdf berbeda.)

Juga dalam diskusi serupa, kali ini mengenai manfaat menggunakan parameter kueri vs menggunakan ekstensi file untuk berbagai jenis media ...

"Itu sebabnya aku selalu lebih suka ekstensi. Pilihan tidak ada hubungannya dengan REST." mengutip

Sekali lagi, itu sedikit berbeda dengan ekstensi Terima vs nama file, tetapi sikap Fielding masih jelas.

Jawab - benar-benar tidak masalah. Pertukaran antara keduanya tidak terlalu signifikan dan keduanya merupakan gaya yang dapat diterima.

Tom Christie
sumber
3
Jawaban seimbang yang bagus. Saya pikir saya akan menambahkan kadang-kadang 'jelas' dari URI bahwa konten tertentu dimaksudkan. mis. ekstensi .html atau ekstensi .pdf di URI. Dan dalam hal ini benar-benar tidak perlu untuk mendukung negosiasi konten, dan memiliki konten yang tersirat dalam URI membuatnya lebih mudah bagi manusia untuk berbagi URI dan menggunakannya untuk menghubungkan ke berbagai hal dengan cara yang dapat segera mereka konsumsi. Dalam kasus lain seperti Anda ingin menghindari ekstensi di URI Anda, dan / atau Anda ingin mengekspos API web yang mendukung beberapa jenis konten secara sama, header terima dapat lebih cocok.
Tim Lovell-Smith
Jawaban yang diperbarui berisi tautan baru. Saya pikir kelompok yahoo mengubah struktur mereka.
Phil Sturgeon
Saya tidak setuju. Bahasa deskripsi sumber daya yang dikembalikan oleh server harus tidak relevan dengan logika bisnis yang dilakukan oleh titik akhir layanan. Memiliki beberapa URI untuk titik akhir layanan yang sama, hanya untuk mengakomodasi bahasa deskripsi sumber daya yang berbeda, sepertinya kesalahpahaman tentang bagaimana REST URI harus dibangun.
Dejay Clayton
10

Pendekatan resmi RESTful resmi yang tepat adalah dengan menggunakan Accept:header.

Namun, Anda harus berhati-hati untuk tidak menghentikan cacheability, yang merupakan salah satu persyaratan REST. Anda harus memiliki Vary: Acceptheader dan cache yang memahaminya. Di dunia ideal Anda akan memilikinya, tetapi dalam kehidupan nyata, keberanian Anda mungkin berbeda. Jadi solusi kedua tidak bersih, tetapi mungkin lebih praktis.

Juga, perhatikan bahwa beberapa browser yang sangat lama digunakan untuk mengabaikan header, sebagai gantinya bergantung pada ekstensi.

vartec
sumber
1
Faktanya tidak akurat. Lihat jawaban yang diterima.
Phil Sturgeon
9

Secara teknis itu tidak terlalu penting - server web Anda akan dapat melewati proses dengan tepat seperti yang terlihat. (Saya mengasumsikan ini tetapi tidak terlihat seperti showstopper).

Namun, secara filosofis - pendekatan pertama adalah satu-satunya pendekatan. Di REST, URL sebenarnya hanya menunjuk ke URI - yang hanya sumber daya. Pikirkan sejenak sumber daya ini sama dengan objek dalam pemrograman berorientasi objek. Anda berbicara dengan sumber ini hanya melalui 4 metode (alias GET / POST / PUT / DELETE -atau jika ada yang memungkinkan), tetapi metode itu tidak menjadi deskripsi objek. Cara yang sama, aspek nilai kembali bukan URI. Objeknya masih sesuatu dan bukan sesuatu.xml atau sesuatu.json

Misalkan jika Anda tidak ingin menggunakan header Terima, tetapi jika Anda masih ingin benar-benar REST secara filosofis, saya tidak akan keberatan sesuatu seperti:

GET /api/something?parm1=value1&return_type=xml

sebagai lawan

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Tetapi seperti yang saya katakan, perbedaan ini hanya filosofis.

Dipan Mehta
sumber
+1 Dipan, Anda benar kecuali untuk satu hal: / api / something? Return_type = xml masih tidak tenang . Alasannya bukan RESTful adalah URL-nya tidak jelas. TKI, dari sudut pandang protokol, tidak ada perbedaan antara / api / something / xml dan / api / something? Xml. Lihat w3.org/DesignIssues/Axioms.html .
Mark E. Haase
0

@artec: Saya pikir Anda salah

Prinsip resmi ISTIRAHAT yang tepat mengatakan tidak ada yang harus disembunyikan di header HTTP karena itu adalah URI yang diekspos atau direferensikan, setiap detail tentang permintaan / respons harus diberikan sebagai bagian dari URI

Oleh karena itu saya sangat menyarankan untuk menghindari menggunakan header untuk detail yang tentang permintaan & tanggapan, dan tetap berpegang pada

 GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Saya tidak dapat menemukan referensi dengan cepat, tetapi saya akan mempostingnya kembali (sebenarnya Anda dapat merujuk buku publikasi O'reilly "Layanan web yang tenang" ( http://shop.oreilly.com/product/9780596529260.do ) yang menegaskan hal yang sama

Basav
sumber
17
-1 Benar-benar salah. Untuk satu hal, URL yang dikirim dalam header HTTP. Selain itu, setiap URL yang berbeda harus mewakili sumber daya yang berbeda. Penyandian XML dan JSON untuk konten yang sama jelas bukan 2 sumber yang berbeda; mereka adalah 2 representasi berbeda dari sumber daya yang sama.
Mark E. Haase
Header HTTP adalah tempat yang sah dan disarankan untuk menyimpan "metadata pesan", seperti: kredensial keamanan, pengidentifikasi korelasi, ID sesi, konteks transaksional, format data. Informasi seperti ini seharusnya tidak mengacaukan URL Anda atau muatan pesan Anda.
Paulo Merson