Transfer-Encoding: gzip vs. Encoding-Konten: gzip

100

Bagaimana keadaan saat ini tentang apakah harus melakukan

Transfer-Encoding: gzip

atau a

Content-Encoding: gzip

ketika saya ingin mengizinkan klien dengan misalnya bandwidth terbatas untuk memberi sinyal kesediaan mereka untuk menerima respons terkompresi dan server memiliki keputusan akhir apakah akan mengompres atau tidak .

Yang terakhir adalah apa yang dilakukan misalnya mod_deflate dan IIS Apache, jika Anda membiarkannya menangani kompresi. Bergantung pada ukuran konten yang akan dikompresi, itu akan melakukan tambahan Transfer-Encoding: chunked.

Ini juga akan menyertakan a Vary: Accept-Encoding, yang sudah mengisyaratkan masalah. Content-Encodingtampaknya menjadi bagian dari entitas, jadi mengubah Content-Encodingjumlah menjadi perubahan entitas, yaitu Accept-Encodingheader yang berbeda berarti misalnya cache tidak dapat menggunakan versi cache dari entitas yang identik.

Apakah ada jawaban pasti tentang ini yang saya lewatkan (dan itu tidak terkubur di dalam pesan di utas panjang di beberapa newsgroup Apache)?

Kesan saya saat ini adalah:

  • Transfer-Encoding sebenarnya akan menjadi cara yang tepat untuk melakukan apa yang sebagian besar dilakukan dengan Content-Encoding oleh server yang ada dan implementasi klien
  • Content-Encoding, karena implikasi semantiknya, membawa beberapa masalah (apa yang harus dilakukan server ETagketika secara transparan memampatkan respons?)
  • Alasannya adalah ayam'n'egg: Browser tidak mendukungnya karena server tidak mendukungnya karena browser tidak

Jadi saya berasumsi bahwa cara yang benar adalah a Transfer-Encoding: gzip(atau, jika saya juga memotong tubuh, itu akan menjadi Transfer-Encoding: gzip, chunked ). Dan tidak ada alasan untuk menyentuh Varyatau ETagatau tajuk lain dalam hal ini karena ini adalah hal tingkat pengangkutan.

Untuk saat ini saya tidak terlalu peduli tentang 'hop-by-hop'-ness Transfer-Encoding, sesuatu yang tampaknya menjadi perhatian orang lain pertama dan terutama, karena proxy mungkin membuka kompresi dan meneruskan tanpa kompresi ke klien. Namun, proxy mungkin juga meneruskannya sebagaimana adanya (dikompresi), jika permintaan asli memiliki Accept-Encodingtajuk yang tepat , yang dalam kasus ini semua browser yang saya tahu diberikan.

Ngomong-ngomong, masalah ini setidaknya sudah berumur satu dekade, lihat misalnya https://bugzilla.mozilla.org/show_bug.cgi?id=68517 .

Klarifikasi apa pun tentang ini akan dihargai. Baik dalam hal apa yang dianggap memenuhi standar dan apa yang dianggap praktis. Misalnya, pustaka klien HTTP yang hanya mendukung "Content-Encoding" transparan akan menjadi argumen yang menentang kepraktisan.

Eugene Beresovksy
sumber
2
Terkait: stackapps.com/questions/916/…
Jo Liss
Baru saja mengalami ini. Curl di PHP 5.3 tidak mengerti Transfer-Encoding:gzip, meskipun baris perintah curl mengerti . Agar aman, kirim keduanya, kecuali Anda menggabungkan chunked dan gzip.
Seva Alekseyev
1
@SevaAlekseyev mengirim keduanya akan sangat salah - klien mungkin mencoba mendekompresi dua kali
Joshua Wise
Ini adalah sesuatu yang mengganggu saya selamanya, juga ( pertanyaan yang saya ajukan )… berdasarkan salah satu jawaban atas pertanyaan yang dikutip @JoLiss, ada cara yang sangat logis, koheren secara semantik, dan sesuai standar untuk mengompresi permintaan / respons tubuh ... dan pada dasarnya tidak ada klien / server yang menggunakan atau mendukungnya. 🤦🏻‍
Dan Lenski

Jawaban:

35

Mengutip Roy T.Fielding , salah satu penulis RFC 2616:

mengubah pengkodean konten dengan cepat dengan cara yang tidak konsisten (baik "tidak pernah" maupun "selalu) tidak memungkinkan permintaan selanjutnya terkait konten tersebut (misalnya, PUT atau GET bersyarat) untuk ditangani dengan benar. Ini, tentu saja, mengapa melakukan on-the-fly content-encoding adalah ide yang bodoh, dan mengapa saya menambahkan Transfer-Encoding ke HTTP sebagai cara yang tepat untuk melakukan pengkodean on-the-fly tanpa mengubah sumber daya.

Sumber: https://issues.apache.org/bugzilla/show_bug.cgi?id=39727#c31

Dengan kata lain: Jangan lakukan Pengkodean Konten dengan cepat , gunakan Pengodean Transfer sebagai gantinya!

Sunting: Yaitu, kecuali Anda ingin menyajikan konten gzip kepada klien yang hanya memahami Pengkodean Konten . Yang, sayangnya, tampaknya sebagian besar dari mereka. Namun ketahuilah bahwa Anda meninggalkan ranah spesifikasi dan mungkin mengalami masalah seperti yang disebutkan oleh Fielding serta yang lainnya, misalnya saat proxy cache terlibat.

Evgeniy Berezovsky
sumber
3
Jadi, jika saya melakukannya dengan benar: 1. Pengkodean konten mengacu pada pengkodean konten di server secara abstrak, yaitu konten akan secara konsisten disajikan dalam pengkodean tertentu oleh server. 2. Transfer-encoding mengacu pada pengkodean yang diputuskan untuk digunakan oleh server untuk mengirimkannya ke agen pengguna dalam contoh ini, yaitu dalam respons ini. Hanya memastikan saya tidak salah menafsirkan jawaban Anda.
hack dot slash
30
@Welovehonda Tentang hak. Dengan kata lain: Menurut spesifikasi, Transfer-Encoding adalah detail lapisan transport murni , yaitu proxy perantara bebas untuk membatalkan, misalnya kompresi gzip pada tingkat itu, sedangkan Content-Encoding adalah properti lapisan bisnis , yang tidak akan menjadi proxy. diizinkan untuk berubah, selain konsekuensi lain (ETags dll). Namun pada kenyataannya , TE tidak biasanya digunakan untuk kompresi, dan banyak server / klien bahkan tidak mendukungnya di luar kotak, sedangkan CE digunakan kurang lebih seperti yang dimaksudkan TE untuk digunakan : sebagai detail lapisan transportasi .
Evgeniy Berezovsky
1
Jadi pada kenyataannya kita terpaksa mengabaikan nasihat Roy T. Fielding?
hack dot slash
11
@KemHeyndels Anda diwajibkan oleh idealisme untuk keluar dan pertama-tama menambahkan dukungan TE ke semua implementasi klien / server HTTP sumber terbuka. Kemudian dapatkan diri Anda dipekerjakan di setiap perusahaan yang memiliki implementasi HTTP sumber tertutup (saya pikir itu hanya Microsoft) dan tambahkan fitur di sana juga. Setelah itu, realitas dan spek akan bertepatan. ;) (Dan HTTP 2.0 akan dirilis, membuat masalah tetap hilang)
Evgeniy Berezovsky
10
Menunjukkan bahwa Anda mendukung Transfer-Encoding masih tidak menjelaskan bahwa Anda mendukung gzip melalui Transfer-Encoding, jadi itu tidak membeli apa pun. Indikasi dilakukan sebaliknya : Setiap klien yang dapat melakukan gzip melalui Transfer-Encoding akan memberi tahu server dengan menyetelnya TE: gzip. Dan kemudian server Anda harus pergi ke rute Transfer-Encoding. Jika klien hanya berkata Accept-Encoding: gzip, Anda harus melakukannya dengan Content-Encodingcara. Jika klien tidak menentukan keduanya dalam permintaannya, server tidak boleh melakukan gzip sama sekali.
Evgeniy Berezovsky
28

Penggunaan yang benar , seperti yang didefinisikan dalam RFC 2616 dan benar-benar diterapkan di alam liar, adalah agar klien mengirim Accept-Encodingheader permintaan (klien dapat menentukan beberapa pengkodean). Kemudian server dapat, dan hanya setelah itu, menyandikan respons sesuai dengan pengkodean yang didukung klien (jika data file belum disimpan dalam pengkodean itu), menunjukkan di Content-Encodingheader tanggapan pengkodean mana yang digunakan. Klien kemudian dapat membaca data dari soket berdasarkan Transfer-Encoding(yaitu, chunked) dan kemudian mendekodekannya berdasarkan Content-Encoding(yaitu:) gzip.

Jadi, dalam kasus Anda, klien akan mengirim Accept-Encoding: gzipheader permintaan, dan kemudian server dapat memutuskan untuk mengompresi (jika belum) dan mengirim header respons Content-Encoding: gzipdan opsional Transfer-Encoding: chunked.

Dan ya, Transfer-Encodingheader dapat digunakan dalam permintaan, tetapi hanya untuk HTTP 1.1, yang mengharuskan implementasi klien dan server mendukung chunkedpengkodean di kedua arah.

ETagsecara unik mengidentifikasi data sumber daya di server, bukan data yang sebenarnya sedang dikirim. Jika sumber daya URL tertentu mengubah ETagnilainya, itu berarti data sisi server untuk sumber daya itu telah berubah.

Remy Lebeau
sumber
14
content-coding adalah karakteristik dari entitas yang diidentifikasi oleh Request-URI Dengan kata lain: Berbeda Content-Encodingmemerlukan yang berbedaETag Ini adalah tentang bug mod_deflate yang saya maksud dalam jawaban saya. Membuat saya bertanya-tanya mengapa detail tingkat aplikasi ini ada dalam standar HTTP. Transfer-EncodingNamun, saat menggunakan , pengaturan tingkat transportasi, tidak perlu mengubah ETag. Kecuali tidak ada yang menerapkan Transfer-Enc.
Evgeniy Berezovsky
2
Content-Encoding bukan untuk pengkodean "dengan cepat". RFC 2616 mengatakan "Transfer-Encoding ... berbeda dari pengkodean konten di mana pengkodean transfer adalah properti pesan, bukan entitas." ( Tools.ietf.org/html/rfc2616#section-14.41 ), dan "Pengodean konten adalah karakteristik entitas yang diidentifikasi oleh URI Permintaan. Biasanya, badan-entitas disimpan dengan pengkodean ini" ( tools.ietf.org/html/rfc2616#section-14.11 ). Jadi saya menolak.
Robert
Apa yang saya jelaskan adalah apa yang " benar-benar diterapkan di alam liar ", terlepas dari Content-Encodingvs Transfer-Encoding. Ya, gzip harus menjadi properti transfer sumber daya, jika dilakukan secara on-the-fly. Di sisi lain, jika sumber daya disimpan terkompresi di server, itu harus menjadi properti konten sumber daya, jika dikirim sebagaimana adanya. Tetapi apa yang seharusnya dan apa yang sebenarnya tidak selalu sama.
Remy Lebeau