Передача-кодування: gzip проти кодування вмісту: gzip


98

Який зараз стан справ, коли мова заходить про те, чи потрібно це робити

Transfer-Encoding: gzip

або а

Content-Encoding: gzip

коли я хочу дозволити клієнтам, наприклад, обмежену пропускну здатність, сигналізувати про свою готовність прийняти стиснуту відповідь, і сервер має остаточне слово, чи потрібно стискати чи ні .

Останнє те, що роблять, наприклад, mod_deflate Apache та IIS, якщо ви дозволите йому подбати про стиснення. Залежно від розміру вмісту, який потрібно стиснути, це зробить додаткове Transfer-Encoding: chunked.

Він також включатиме символ Vary: Accept-Encoding, який вже натякає на проблему. Content-Encodingздається частиною сутності, тому зміна Content-Encodingсум на зміну сутності, тобто інший Accept-Encodingзаголовок означає, наприклад, кеш не може використовувати свою кешовану версію інакшої сутності.

Чи є на це чітка відповідь, яку я пропустив (і це не заховано в повідомленні довгою ниткою в якійсь групі новин apache)?

Моє поточне враження:

  • Трансферне кодування насправді було б правильним способом зробити те, що в основному робиться із кодуванням вмісту існуючими реалізаціями сервера та клієнта
  • Кодування вмісту через його семантичні наслідки містить кілька питань (що робити серверу, ETagколи прозоро стискає відповідь?)
  • Причиною є куряче яйце: браузери не підтримують це, оскільки сервери не підтримують те, що браузери не підтримують

Отже, я припускаю, що правильний шлях буде Transfer-Encoding: gzip(або, якщо я додатково порвати тіло, це стане Transfer-Encoding: gzip, chunked ). І немає жодної причини торкатися Varyабо ETagбудь-якого іншого заголовка в такому випадку, оскільки це річ транспортного рівня.

На даний момент я не надто дбаю про "стрибковість" Transfer-Encoding, про те, що, напевно, турбує інших в першу чергу, тому що проксі-сервери можуть стискати і пересилати нестисненим до клієнта. Однак проксі-сервери можуть так само переслати його як є (стиснутий), якщо вихідний запит має відповідний Accept-Encodingзаголовок, який у випадку всіх браузерів, які я знаю, є даними.

До речі, цьому випуску щонайменше десятиліття, див., Наприклад, https://bugzilla.mozilla.org/show_bug.cgi?id=68517 .

Будемо вдячні за будь-які роз’яснення щодо цього. Як з точки зору того, що вважається відповідним стандартам, так і того, що вважається практичним. Наприклад, клієнтські бібліотеки HTTP, що підтримують лише прозоре "Кодування вмісту", будуть аргументом проти практичності.



Просто натрапив на це. Curl на PHP 5.3 не розуміє Transfer-Encoding:gzip, хоча curl командного рядка це робить. Щоб бути в безпеці, надішліть обидва, якщо ви не поєднуєте фрагменти та gzip.
Сева Олексієв

1
@SevaAlekseyev відправляти обидва буде дуже неправильно - клієнти можуть спробувати декомпресувати двічі
Джошуа Мудрий

Це те, що мене також навіяло ( питання, яке я задав ) ... відповідно до однієї з відповідей на запитання, яке цитував @JoLiss, існує цілком логічний, семантично узгоджений і сумісний зі стандартами спосіб стиснення тіл запитів / відповідей ... і в основному жоден клієнт / сервер не використовує і не підтримує його. 🤦🏻‍
Ден Ленскі,

Відповіді:


35

Цитуючи Роя Т. Філдінга , одного з авторів RFC 2616:

зміна кодування вмісту на льоту на суперечливій основі (ні «ніколи», ні «завжди») унеможливлює правильну обробку пізніших запитів щодо цього вмісту (наприклад, PUT або умовного GET). Це, звичайно, чому кодування вмісту на льоту - дурна ідея, і чому я додав Transfer-Encoding до HTTP як правильний спосіб виконувати логічне кодування без зміни ресурсу.

Джерело: https://issues.apache.org/bugzilla/show_bug.cgi?id=39727#c31

Іншими словами: не робіть на льоту кодування вмісту, замість цього використовуйте Transfer-Encoding!

Редагувати: Тобто, якщо ви не хочете обслуговувати згорнутий вміст клієнтам, які розуміють лише кодування вмісту . Що, на жаль, здається більшості з них. Але майте на увазі, що ви залишаєте сфери специфікації і можете зіткнутися з такими проблемами, як згадана Філдінгом, а також іншими, наприклад, коли задіяні кешовані проксі.


3
Отже, якщо я правильно зрозумів: 1. Кодування вмісту означає абстрактне кодування вмісту на сервері, тобто вміст буде постійно подаватися сервером у зазначеному кодуванні. 2. Трансферне кодування відноситься до кодування, яке сервер вирішив використати, щоб доставити його агенту користувача в цьому випадку, тобто у цій відповіді. Просто переконуюсь, що я не неправильно інтерпретую вашу відповідь.
dot slash hack

30
@KemHeyndels Про право. Іншими словами: Відповідно до специфікацій, Transfer-Encoding є чистою деталлю транспортного шару , тобто проміжний проксі може скасувати, наприклад, стиснення gzip на цьому рівні, тоді як Content-Encoding - це властивість бізнес-рівня , яким проксі не буде дозволено змінювати, на додаток до інших наслідків (ETags тощо). Однак насправді TE зазвичай не використовується для стиснення, і багато серверів / клієнтів навіть не підтримують його з коробки, тоді як CE використовується більш-менш так , як передбачалося використовувати TE : як деталь транспортного рівня .
Євген Бересовський

1
Тож нас насправді зобов’язує ігнорувати пораду Роя Т. Філдінга?
dot slash hack

11
@KemHeyndels Ви ідеалізмом зобов'язані вийти і спершу додати підтримку TE до всіх реалізацій HTTP-клієнта / сервера з відкритим кодом. Тоді працевлаштуйтесь у кожній компанії, яка має впровадження HTTP із закритим кодом (я думаю, це все одно лише Microsoft), і додайте туди цю функцію. Після цього реальність і специфікація збігатимуться. ;) (І HTTP 2.0 буде випущено, і проблема все одно зникне)
Євген Бересовський

10
Вказівка ​​на те, що ви підтримуєте Transfer-Encoding, все ще не дає зрозуміти, що ви підтримуєте gzip через Transfer-Encoding, тому це нічого не купує. Індикація робиться навпаки : Будь-який клієнт, який може зробити gzip через Transfer-Encoding, повідомить сервер, встановивши параметр TE: gzip. І тоді ваш сервер повинен пройти шлях передачі-кодування. Якщо клієнт лише каже Accept-Encoding: gzip, ви повинні зробити це Content-Encodingтак, як потрібно. Якщо клієнт у своєму запиті не вказує жодного, сервер взагалі не повинен робити gzip.
Євген Бересовський

27

Правильне використання, як це визначено в RFC 2616 і фактично реалізовані в дикій природі, для клієнта , щоб послати Accept-Encodingзаголовок запиту (клієнт може вказати кілька кодувань). Тоді сервер може, і лише тоді, кодувати відповідь відповідно до підтримуваних клієнтом кодувань (якщо дані файлу ще не зберігаються в цьому кодуванні), вказати в Content-Encodingзаголовку відповіді, яке кодування використовується. Потім клієнт може зчитувати дані з сокета на основі Transfer-Encoding(тобто chunked), а потім декодувати їх на основі Content-Encoding(тобто:gzip .

Отже, у вашому випадку клієнт надішле Accept-Encoding: gzipзаголовок запиту, а потім сервер може вирішити стиснути (якщо ще не) і надіслати a Content-Encoding: gzipта за бажаннямTransfer-Encoding: chunked заголовок відповіді відповідь.

І так, Transfer-Encodingзаголовок можна використовувати в запитах, але лише для HTTP 1.1, який вимагає, щоб реалізації як клієнта, так і сервера підтримувалиchunked кодування в обох напрямках.

ETagоднозначно ідентифікує дані ресурсу на сервері, а не фактично передані дані. Якщо заданий ресурс URL-адреси змінює своє ETagзначення, це означає, що дані на стороні сервера для цього ресурсу змінилися.


14
кодування вмісту - це характеристика сутності, ідентифікованої за запитом-URI. Іншими словами: Різне Content-Encodingвимагає різнеETag Це, до речі, про що полягає помилка mod_deflate, про яку я посилаюся у своїй відповіді. Мене здивує, чому ця деталь на рівні додатку передусім є стандартом HTTP. При використанні , Transfer-Encodingпроте, установка транспортного рівня, немає необхідності міняти ETag. Окрім того, що ніхто не впровадив Transfer-Enc.
Євген Бересовський

2
Кодування вмісту не призначене для кодування "на льоту". RFC 2616 говорить: "Кодування передачі ... відрізняється від кодування вмісту тим, що кодування передачі є властивістю повідомлення, а не сутності." ( Tools.ietf.org/html/rfc2616#section-14.41 ), і "Кодування вмісту - це характеристика сутності, ідентифікованої за допомогою URI запиту. Зазвичай тіло сутності зберігається з цим кодуванням" ( tools.ietf.org/html/rfc2616#section-14.11 ). Тож я голосую проти.
Роберт

Те , що я описав те , що « на самому ділі реалізується в дикій природі », незалежно від того, Content-Encodingпроти Transfer-Encoding. Так, gzip повинен бути властивістю передачі ресурсу, якщо це робиться на льоту. З іншого боку, якщо ресурс зберігається стисненим на сервері, він повинен бути властивістю вмісту ресурсу, якщо він надсилається як є. Але те, що повинно бути і що є насправді , не завжди одне і те ж.
Remy Lebeau
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.