Этот документ является выражением инциативы расширенного использования заголовка Pragma
для указания серверу явным образом возможностей и предпочтений пользователя, касающихся представления и поведения документа HTML.
Этот документ не является нормативным.
Используя стандартные заголовки HTTP, мы можем сообщить серверу, что желаем получить скорее HTML, нежели PDF; что, если есть возможность, серверу лучше предоставить страницу на русском языке; что браузер поддерживает сжатие данных, и можно использовать deflate, значительно уменьшив размер передаваемых данных.
Это, несомненно, замечательно, но лучшее — враг хорошего. Протокол HTTP предусматривает бесконечное расширение своего функционала и семантики за счет установки произвольных заголовков как запроса, так и ответа. Случаи, когда нестандарные заголовки становились де-факто стандартными, не единичны. В качестве примера можно привести X-Do-Not-Track
, указывающий серверу не изучать поведение пользователя для определения тематики рекламы, и X-Requested-With
, позволяющий определить, что совершается AJAX-запрос.
Однако, пожалуй, ни одна из используемых сейчас схем не может сообщить серверу обо всех потребностях (или пожеланиях) пользователя. И, тем более, не рассчитана на дальнейшее расширение. В качестве варианта отсылки серверу данных о предпочтениях пользователя и других мета-данных предлагаю расширить существующий HTTP-заголовок Pragma
.
RFC 2616 дает следующее определение заголовку Pragma
(выдержка, перевод):
Заголовок Pragma
используется для внедрения директив, зависящих от исполнения («implementation-specific»), которые могут быть применены к любому приёмнику в цепи запрос-ответ. Все директивы Pragma
указывают на необязательное поведение с точки зрения протокола, однако, некоторые системы МОГУТ («MAY» в терминах RFC) требовать, чтобы поведение соответствовало директивам.
Прагма = "Pragma" ":" 1#прагма-директива
прагма-директива = "no-cache" | прагма-расширения
прагма-расширения = токен [ "=" ( токен | закавыченная-строка ) ]
Прагма-директивы ДОЛЖНЫ быть переданы через прокси- или гейт-приложение, вне зависимости от их значимости для этого приложения, потому как директивы могут быть применены ко всем приёмникам в цепи запрос-ответ. Невозможно задать прагму для определенного приёмника, однако, любую прагму, не относящуюся к приёмнику, этому приёмнику СЛЕДУЕТ («SHOULD») проигнорировать.
Никаких новых директив Pragma
не будет определено в HTTP.
Таким образом, заголовок Pragma
служит для передачи произвольной мета-информации и директив, являясь неким подобием <meta>
в HTML. Учитывая также, что прагма может быть применена к любому звену в цепи, думаю, можно считать прагму «политикой» запроса. Уверен, расширение этого заголовка для передачи произвольных указаний и предпочтений от пользователя более семантически верно, чем изобретение новых заголовков.
Прагма = "Pragma" ":" директива-поведения
директива-поведения = определение-поведения "=" значение-поведения
определение-поведения = "user-limit" | "user-expect"
значение-поведения = [[аналогично media-range заголовка Accept]] !TODO развернуть в нормальную схему
Например:
Pragma: user-limit=bandwidth/images;q=0.5,dhtml/*,ads/*;vendor=Foobar,ads/behavior
Передает серверу предпочтения пользователя: по возможности (с коэффициентом 0,5) не использовать изображения в генерируемом документе, не использоавть DHTML, не вставлять рекламу, не показывать рекламу вендора Foobar, не использовать отслеживание пользовательского поведения для показа рекламы.
Такую прагму может направить, к примеру, браузер Opera Mini, чтобы избежать излишнего трафика за счет изображений и лишних перезагрузок страницы из-за отсутствия яваскрипта на клиентской стороне
Значение определение-поведения
"user-limit"
указывает серверному программному обеспечению воздержаться от использования элементов и техник, перечисленных в поле значение-поведения
.
Значение определение-поведения
"user-expect"
поощряет использование серверным программным обеспечением элементов и техник, перечисленных в поле значение-поведения
.
Цепь значений подобно заголовку Accept
. !TODO развернуть
В качестве парматеров используются q
— квалификатор, vendor
— поставщик.
В качестве типов и подтипов используются следующие (применимо к user-limit
):
ads/*
Не показывать никакую рекламу (при указании vendor
— от определенного поставщика).
ads/behavior
Не использовать отслеживание поведения пользователя. Аналогично X-Do-Not-Track
.
!TODO: расширить
bandwidth/*
Любыми способами способствовать уменьшению передаваемой информации. Может использоваться, к примеру, если у пользователя небольшой канал, или оплата за трафик.
bandwidth/images
Воздержаться от использования изображений в генерируемом документе.
bandwidth/presentation
Воздержаться от использования тяжеловесных декоративных элементов оформления
bandwidth/preload
Воздержаться от использования прелоада чего-либо.
!TODO: расширить
dhtml/*
Не использовать DHTML вообще. Например, при использовании Opera Mini, либо другого «тонкого» браузера, работающего через транскодер. DHTML в таких браузерах всё равно ведет к перезагрузке страницы.
dhtml/js
Не использовать javascript.
dhtml/ajax
Не использовать асинхронные запросы данных.
!TODO: расширить
Браузер может задавать другие типы и подтипы. Префикс «X-» не требуется.
Имея аналогичную схему, значение поведения при user-expect
инверсирует своё значение.
Например, Pragma: user-expect=dhtml/ajax;bandwidth/preload
указывает серверному ПО по возможности использовать ajax и прелоад в сгенерированной странице.
Если предпочтение пользователя не было указано ни с помощью Pragma:user-limit
, ни с помощью Pragma:user-expect
, серверное ПО может либо не применять ничего, касаемо содержимого документа, либо использовать автоматическое определение возможностей браузера и потенциальных потребностей пользователя. Т.е., как есть сейчас.
Серверное ПО может при ответе вернуть исходные значения Pragma:user-limit
и Pragma:user-expect
, либо включить лишь те предпочтения пользователя, которые были приняты во внимание при генерации документа.
Не использовать никакую прагму в ответе не рекомендуется из-за возможности кеширования.
Как указывает поределение заголовка Pragma
, его действие применимо ко всем элементам цепи запрос-ответ. Это даёт возможность более гибкого управления содежимым для пользователя, нежели настройка браузера.
К примеру пользователь отправляет запрос через прокси:
GET / HTTP/1.1
Host: Example.com
Accept: text/*,image/jpeg,image/webp,image/*;q=.1
Pragma: user-limit:bandwidth/images;q=.5
Прокси повторяет запрос серверу:
GET / HTTP/1.1
Host: Example.com
Accept: text/*,image/jpeg,image/webp,image/*;q=.1
Pragma: user-limit:bandwidth/images;q=.5
X-Forwarded-For: 1.2.3.4
Сервер отвечает:
HTTP/1.1 200 OK
Content-Type: image/jpeg
Content-Length: 9001
[Тело ответа]
Сервер не предоставил прокси значение используемой прагмы, поэтому прокси может пережать полученное изображение так, чтобы пользователь получил сжатую версию того же изображения. Прокси отвечает клиенту:
HTTP/1.1 200 OK
Content-Type: image/webp
Content-Length: 1337
Pragma: user-limit:bandwidth/images;q=.5
[Тело ответа]
!TODO: пример иллюстративный, но много шероховатостей
Предложенный выше функционал следует отличать от функционала и семантики заголовка Accept
. В то время, как заголовок Accept
передает данные о технической возможности воспроизвести тот или иной формат документа как таковой, Pragma:user-limit
и Pragma:user-expect
указывает на предпочтения пользователя насчет содержимого документа, но не его формата.
Таким образом, нежелание пользователя получать, к примеру, флеш, должно выражаться:
Accept: application/x-shockwave-flash;q=0
но не
Pragma: user-limit=features/flash
Несмотря на неточности описания, надеюсь, идея будет рассмотрена Вами и, разумеется, дополнена. Или отвергнута в пользу лучшего решения с той же идеологией: покончить с «зоопарком» различных средств догадок, что нужно пользователю в зависимости от типа устройства, браузера и фазы Луны в пользу ясного и точного указания. Разумеется, описаный метод потребует определенного изменения как клиентской, так и серверной стороны, однако, он оставляет достаточно места для обратной совместимости.