Кодирование передачи: gzip и Content-Encoding: gzip
Каково текущее состояние дел, когда дело доходит до
Transfer-Encoding: gzip
или
Content-Encoding: gzip
когда я хочу разрешить клиентам, например. ограниченная полоса пропускания до сигнализирует о готовности принять сжатый отклик, а сервер имеет окончательное мнение о том, следует ли сжимать.
Последний - это то, что, например, Apache mod_deflate и IIS делают, если вы позволите ему позаботиться о сжатии. В зависимости от размера сжатого содержимого он будет делать дополнительные Transfer-Encoding: chunked
.
Он также будет включать Vary: Accept-Encoding
, который уже намекает на проблему. Content-Encoding
представляется частью сущности, поэтому изменение Content-Encoding
сводится к изменению объекта, то есть другого заголовка Accept-Encoding
, например, кеш не может использовать свою кешированную версию идентично идентичного объекта.
Есть ли определенный ответ на этот вопрос, который я пропустил (и который не зарылся внутри сообщения в длинном потоке в какой-то новостной группе apache)?
Мое настоящее впечатление:
- Передача-кодирование на самом деле будет правильным способом делать то, что в основном делается с Content-Encoding, с помощью существующих имплантаций сервера и клиента.
- Content-Encoding из-за его семантических последствий имеет несколько проблем (что должен делать сервер с
ETag
при прозрачном сжатии ответа?)
- Причина chicken'n'egg: браузеры не поддерживают его, потому что серверы не потому, что браузеры не
Итак, я предполагаю, что правильный путь будет Transfer-Encoding: gzip
(или, если я дополнительно куском тела, станет Transfer-Encoding: gzip, chunked
). И нет причин касаться Vary
или ETag
или любого другого заголовка в этом случае, поскольку это вещь транспортного уровня.
На данный момент меня не слишком волнует "hop-by-hop" из Transfer-Encoding
, что-то, что другие, похоже, беспокоят в первую очередь, потому что прокси могут распаковывать и пересылать несжатые клиенту, Однако прокси-серверы могут так же перенаправить его как-есть (сжатый), если исходный запрос имеет правильный заголовок Accept-Encoding
, который в случае всех браузеров, которые, как я знаю, являются данными.
Btw, эта проблема составляет, по меньшей мере, десятилетие, см., например,
https://bugzilla.mozilla.org/show_bug.cgi?id=68517.
Любые разъяснения по этому вопросу будут оценены. Как с точки зрения того, что считается стандартным, так и с точки зрения практичности. Например, HTTP-клиентские библиотеки, поддерживающие только прозрачную "Content-Encoding", будут аргументом против практичности.
Ответы
Ответ 1
Цитата Рой Т. Филдинг, один из авторов RFC 2616:
изменение кодирования контента "на лету" непоследовательно (ни "никогда", ни "всегда" ) делает невозможным последующие запросы относительно этого содержимого (например, PUT или условного GET) для обработки правильно. Это, конечно, почему выполнение на лету контент-кодирование - это глупая идея, и почему я добавил Transfer-Encoding для HTTP как правильный способ делать "на лету" кодирование без изменения ресурс.
Источник: https://issues.apache.org/bugzilla/show_bug.cgi?id=39727#c31
Другими словами: не выполняйте на лету Content-Encoding, используйте вместо этого Transfer-Encoding!
Изменить: То есть , если вы не хотите обслуживать gzipped-контент для клиентов, которые понимают Content-Encoding. К сожалению, большинство из них. Но имейте в виду, что вы покидаете сферы спецификации и можете столкнуться с такими проблемами, как упомянутые Fielding, а также другие, например. когда задействуются кэширующие прокси.
Ответ 2
Использование правильного, как определено в RFC 2616 и фактически реализованное в дикой природе, заключается в том, что клиент отправляет заголовок запроса Accept-Encoding
(клиент может указать несколько кодировок). Затем сервер может и только тогда кодировать ответ в соответствии с поддерживаемыми клиентом кодировками (если данные файла еще не сохранены в этой кодировке), укажите в заголовке ответа Content-Encoding
, какая кодировка используется. Затем клиент может считывать данные сокета на основе Transfer-Encoding
(т.е. chunked
), а затем декодировать его на основе Content-Encoding
(то есть: gzip
).
Итак, в вашем случае клиент отправит заголовок запроса Accept-Encoding: gzip
, а затем сервер может решить сжать (если это еще не так) и отправить заголовок ответа Content-Encoding: gzip
и необязательно Transfer-Encoding: chunked
.
И да, заголовок Transfer-Encoding
может использоваться в запросах, но только для HTTP 1.1, который требует, чтобы и клиентские, и серверные реализации поддерживали кодировку chunked
в обоих направлениях.
ETag
уникально идентифицирует данные ресурса на сервере, а не данные, которые фактически передаются. Если данный ресурс URL меняет значение ETag
, это означает, что данные на стороне сервера для этого ресурса изменились.