Пользовательские заголовки HTTP: соглашения об именах

1115

Некоторые из наших пользователей просили нас включить данные, относящиеся к их учетной записи, в заголовки HTTP запросов, которые мы им отправляем, или даже ответы, которые они получают от нашего API. Каково общее соглашение для добавления пользовательских заголовков HTTP, с точки зрения именования , формата ... и т. Д.

Кроме того, не стесняйтесь публиковать любые умные их использования, которые вы наткнулись в Интернете; Мы пытаемся реализовать это, используя то, что лучше всего в качестве цели :)

Жюльен Дженесту
источник
25
Имейте в виду, что брандмауэры могут удалять поля заголовка ответа. Некоторые удаляют все, что не упомянуто в RFC 2616 (июнь 1999, HTTP 1.1). Клиентская сторона должна быть пригодна для использования без новых полей.
stesch
5
Обратите внимание , что комментарий по @stesch не применяется при использовании HTTP S .
code_dredd
1
Обратите внимание, что комментарий @code_dredd является городской легендой. Брандмауэры могут фильтровать содержимое HTTPS. См. Howtoforge.com/filtering-https-traffic-with-squid и watchguard.com/help/docs/wsm/xtm_11/en-us/content/en-us/…
stesch
@stesch Учитывая, что ваша статья в основном превращает прокси во что-то похожее на MiTM (он берет зашифрованное соединение с клиентом, а затем создает новое), тогда, конечно, вы можете делать почти все, но этот факт сводит на нет шифрование PoV b / прокси. c он расшифровывает сам контент клиента. В этом случае, из PoV прокси-сервера, это в основном так, как если бы вы не использовали HTTPS на первом месте ...
code_dredd

Ответы:

1172

Эта рекомендация будет была начать свое имя с «Х-». Например X-Forwarded-For, X-Requested-With. Это также упоминается в разделе 5 RFC 2047 .


Обновление 1 : в июне 2011 года был опубликован первый черновик IETF, чтобы отказаться от рекомендации использовать префикс «X-» для нестандартных заголовков. Причина в том, что, когда нестандартные заголовки с префиксом «X-» становятся стандартными, удаление префикса «X-» нарушает обратную совместимость, заставляя прикладные протоколы поддерживать оба имени (например, x-gzip& gzipтеперь эквивалентны). Итак, официальная рекомендация - просто назвать их разумно без префикса «X-».


Обновление 2 : в июне 2012 года рекомендация об использовании префикса «X-» стала официальной как RFC 6648 . Ниже приведены ссылки на актуальность:

3. Рекомендации для создателей новых параметров

...

  1. НЕ СЛЕДУЕТ ставить перед именами их параметров "X-" или подобные конструкции.

4. Рекомендации для разработчиков протоколов

...

  1. НЕ ДОЛЖЕН запрещать регистрацию параметров с префиксом «X-» или аналогичных конструкций.

  2. НЕ ДОЛЖЕН оговариваться, что параметр с префиксом «X-» или аналогичными конструкциями следует понимать как нестандартный.

  3. НЕ ДОЛЖЕН оговариваться, что параметр без префикса "X-" или аналогичные конструкции должны пониматься как стандартизированные.

Обратите внимание, что «НЕ ДОЛЖНО» («не рекомендуется») не то же самое, что «НЕ ДОЛЖНО» («запрещено»), см. Также RFC 2119 для другой спецификации по этим ключевым словам. Другими словами, вы можете продолжать использовать заголовки с префиксом «X-», но это официально больше не рекомендуется, и вы можете определенно не документировать их, как если бы они были общедоступными стандартами.


Резюме :

  • официальная рекомендация состоит в том, чтобы просто назвать их разумно без префикса "X-"
  • вы можете продолжать использовать префикс «X-», но это больше официально не рекомендуется, и вы можете определенно не документировать их, как если бы они были общедоступными стандартами.
BalusC
источник
306
Так же, как есть много детей, которые никогда не станут профессиональными спортсменами, многие пользовательские заголовки никогда не станут стандартами. Я склонен держать "Х-" на тех.
G-Mac
19
@ G-Mac Согласен. Существует так много пользовательских заголовков, которые никогда не будут стандартизированы. Те немногие, которые это делают, легко редактируют ваш код из if (header == "x-gzip")в if (header == "x-gzip" || header == "gzip"). Что касается вашей аналогии, вот другая: это похоже на то, как военные говорят: «О, это сложно сменить кого-то с рядового на генерала. Итак, теперь вы все генералы. Теперь нам не нужно делать так много работы»
Коул Джонсон
24
@ColeJohnson Не уверен, что эта аналогия работает. Проблема здесь в том, что нет центральной точки, которую вы можете изменить имя. Каждый фрагмент кода, который ожидает x-gzip, теперь должен быть изменен, или старый заголовок должен продолжать использоваться в дополнение к новому. Лучше пойти с RFC 6648.
Vinod
4
@ Винод да. Это имеет смысл, но есть так много предлагаемых стандартов, которые никогда не увидят свет. Для типов файлов, конечно; сбросьте X-префикс. Я против этого, но продолжай и сделай это. Для заголовков OTOH, не бросайте это. Это позволяет легко смотреть и говорить: «О, это нестандартно; я могу проигнорировать это», поскольку есть те нестандартные X-заголовки, а затем есть тот, который я не узнаю; могу ли я проигнорировать это безопасно? »
Коул Джонсон
21
Хотя тон ответа Квикли неоправданно оборонителен, я считаю, что он прав, и его точка зрения решает проблему, проиллюстрированную в этой ветке комментариев. Короче говоря, не пытайтесь определить, будет ли заголовок «выпускаться» или нет; вместо этого определите, является ли это частным или общедоступным заголовком (специфичным для приложения или «универсальным» / «глобальным»). Для частных заголовков, при желании используйте, X-чтобы не допустить столкновения с общедоступными заголовками (благодаря RFC6648, который имеет дело с общедоступными заголовками), и дополнительно определенно используйте произвольный частный префикс. Для публичных заголовков не используйте X-ни при каких обстоятельствах.
12.12.14
535

Вопрос стоит перечитать. Заданный вопрос не похож на префиксы поставщиков в свойствах CSS, где уместно ориентироваться на будущее и думать о поддержке поставщиков и официальных стандартах. Фактический вопрос больше похож на выбор имен параметров запроса URL. Никого не должно волновать, кто они. Но использование именных интервалов является вполне допустимым - и распространенным, и правильным - делом.

Обоснование.
Речь идет о соглашениях разработчиков в отношении пользовательских заголовков для конкретных приложений - « данных, относящихся к их учетной записи », - которые не имеют ничего общего с поставщиками, органами стандартизации или протоколами, которые должны быть реализованы третьими сторонами, за исключением того, что разработчик просто нужно избегать имен заголовков, которые могут использоваться другими серверами, прокси или клиентами. По этой причине приведенные примеры «X-Gzip / Gzip» и «X-Forwarded-For / Forwarded-For» являются спорными. Поставленный вопрос касается соглашений в контексте частного API, схожего с соглашениями об именах параметров запроса URL. Это вопрос предпочтения и расстояния между именами; опасения по поводу того, что «X-ClientDataFoo» поддерживается любым прокси или поставщиком без «X»

В префиксе «X-» нет ничего особенного или волшебного, но это помогает прояснить, что это пользовательский заголовок. Фактически, RFC-6648 и др. Помогают подкрепить аргументы в пользу использования префикса «X-», потому что - поскольку производители HTTP-клиентов и серверов отказываются от префикса, - это зависит от вашего приложения, частного API, личных данных. Механизм передачи становится еще лучше изолированным от столкновений пространства имен с небольшим количеством официальных зарезервированных имен заголовков. Тем не менее, мое личное предпочтение и рекомендация - пойти дальше и сделать, например, «X-ACME-ClientDataFoo» (если ваша компания по производству виджетов - «ACME»).

ИМХО спецификация IETF недостаточно конкретна, чтобы ответить на вопрос OP, потому что она не может различить совершенно разные варианты использования: (A) поставщики вводят новые глобально применимые функции, такие как «Forwarded-For», с одной стороны, против (B) разработчики приложений передают специфичные для приложения строки клиенту и серверу. Спецификация касается только первого, (A). Вопрос здесь заключается в том, существуют ли соглашения для (B). Есть. Они включают в себя группировку параметров в алфавитном порядке и отделение их от множества соответствующих стандартам заголовков типа (A). Использование префикса «X-» или «X-ACME-» удобно и допустимо для (B) и не конфликтует с (A). Чем больше вендоров прекратят использовать «X-» для (A), тем более отчетливыми станут (B).

Пример:
Google (который имеет небольшой вес в различных органах стандартизации) - по состоянию на сегодня, 20141102 в этом небольшом редактировании моего ответа - в настоящее время использует «X-Mod-Pagespeed», чтобы указать версию своего модуля Apache участвует в преобразовании данного ответа. Кто-нибудь действительно предлагает, чтобы Google использовал «Mod-Pagespeed» без «X-» и / или попросил IETF благословить его использование?

Сводка:
если вы используете пользовательские заголовки HTTP (в качестве иногда подходящей альтернативы файлам cookie) в своем приложении для передачи данных на сервер или с него, и эти заголовки явно НЕ предназначены для использования вне контекста вашего применение, интервал имен с префиксом «X-» или «X-FOO-» является разумным и распространенным соглашением.

cweekly
источник
52
Я был бы признателен, если бы кто-нибудь из моих комментариев мог объяснить, какую часть моего ответа они считают нежелательной. Меня не очень заботит оценка моей репутации, но мне действительно любопытно. Где лежат разногласия? Спасибо.
13
56
Я полностью согласен с вашим ответом, и это единственный ответ, который отвечает на заданный вопрос. Мы говорим здесь о пользовательских, специфичных для приложения заголовках, которые никогда не будут стандартизированы в стандартах HTTP. Есть ли общее правило для них, которое люди склонны использовать? (например, возможно, перед ними стоит префикс "_"? т.е.: ("_ClientDataFoo")
Marchy
14
Спасибо, Марчи, да, принятый ответ не отвечает на заданный вопрос. Отмена IETF префикса «X-» для нестандартных (но общих) заголовков не имеет отношения к заголовкам пользовательских приложений, которые никогда не будут стандартизированы. Чтобы ответить на ваш вопрос, по моему мнению и опыту (16 лет работы в сети), наилучшим условием является использование вышеупомянутой «X-ACME-ClientData». «X-» bc, это не стандартно (и никогда не будет, именно поэтому здесь обсуждается вопрос об устаревании IETF), «ACME-» - пространство имен для вашей компании «ACME» или конкретного приложения, а «ClientData» может быть любым семантическое имя вам нравится. :)
еженедельно
5
@DarrelMiller ... отсюда и рекомендация использовать X-ACMECO-WIDGET-FOO. Я настаиваю на том, что для заданного вопроса ОП использование RF- просто не противопоказано RFC-6648 и тому подобным. Если вы являетесь поставщиком, предоставляющим инфраструктуру, библиотеку или модуль для использования в проектах других людей, это другая история, и во всех отношениях следуйте этому RFC до T. Но это просто вопрос для отдельных одноразовых приложений, где пользовательские Соглашения об именовании заголовков для конкретных приложений - фактически полностью частные API. Как они будут сталкиваться с именами "всех остальных"? Чьи это будут?
еженедельно
11
Честно говоря, у меня возникли небольшие проблемы с пониманием рассуждений RFC. Предполагается, что, если и когда параметр будет стандартизирован, будут как x-, так и не x-версии. Это проблема, только если поведение версий x и non-x одинаково. Я наткнулся здесь, потому что я смотрю на добавление заголовка «от имени» в мой API. Когда-нибудь он может стать общедоступным (так как это типичный вариант использования). Если я использовал «On-Behalf-Of» и когда-нибудь они добавят его в качестве стандартного заголовка, каковы шансы того, что моя семантика будет идентична стандартной?
fool4jesus
62

Формат заголовков HTTP определен в спецификации HTTP. Я собираюсь поговорить о HTTP 1.1, для которого спецификация RFC 2616 . В разделе 4.2 «Заголовки сообщений» определена общая структура заголовка:

   message-header = field-name ":" [ field-value ]
   field-name     = token
   field-value    = *( field-content | LWS )
   field-content  = <the OCTETs making up the field-value
                    and consisting of either *TEXT or combinations
                    of token, separators, and quoted-string>

Это определение опирается на два основных столпа, токен и текст. Оба они определены в разделе 2.2 «Основные правила». Токен это:

   token          = 1*<any CHAR except CTLs or separators>

В свою очередь опираясь на CHAR, CTL и разделители:

   CHAR           = <any US-ASCII character (octets 0 - 127)>

   CTL            = <any US-ASCII control character
                    (octets 0 - 31) and DEL (127)>

   separators     = "(" | ")" | "<" | ">" | "@"
                  | "," | ";" | ":" | "\" | <">
                  | "/" | "[" | "]" | "?" | "="
                  | "{" | "}" | SP | HT

ТЕКСТ это:

   TEXT           = <any OCTET except CTLs,
                    but including LWS>

Где LWS - линейный пробел, определение которого я не буду воспроизводить, а OCTET:

   OCTET          = <any 8-bit sequence of data>

Есть примечание, сопровождающее определение:

The TEXT rule is only used for descriptive field contents and values
that are not intended to be interpreted by the message parser. Words
of *TEXT MAY contain characters from character sets other than ISO-
8859-1 [22] only when encoded according to the rules of RFC 2047
[14].

Итак, два вывода. Во-первых, ясно, что имя заголовка должно состоять из подмножества символов ASCII - буквенно-цифровых символов, некоторой пунктуации, а не чего-то еще. Во- вторых, нет ничего в определении заголовка значения , что накладывает ограничения на это в ASCII или исключает 8-битных символов: это явно состоит из октетов, с символами только управления перемычкой (обратите внимание , что CR и LF рассматриваются элементы управления). Кроме того, комментарий к продукции TEXT подразумевает, что октеты должны интерпретироваться как находящиеся в ISO-8859-1, и что существует механизм кодирования (который, кстати, ужасен) для представления символов вне этой кодировки.

Итак, для ответа на @BalusC, в частности, совершенно ясно, что согласно спецификации значения заголовков приведены в ISO-8859-1. Я отправил символы высокого уровня 8859-1 (в частности, некоторые ударные гласные, как они используются на французском языке) в заголовке из Tomcat, и правильно интерпретировал их Firefox, так что в некоторой степени это работает на практике так же, как и в теории (хотя это был заголовок Location, который содержит URL, и эти символы недопустимы в URL, так что это было фактически недопустимо, но по другому правилу!).

Тем не менее, я бы не стал полагаться на ISO-8859-1, работающий на всех серверах, прокси-серверах и клиентах, поэтому я бы придерживался ASCII в качестве защитного программирования.

Том Андерсон
источник
3
Более новая спецификация HTTP RFC7230 гласит: «Вновь определенные поля заголовка ДОЛЖНЫ ограничивать значения своих полей октетами US-ASCII».
Роберт Тупело-Шнек
23

RFC6648 рекомендует, чтобы вы предположили, что ваш пользовательский заголовок "может стать стандартизированным, общедоступным, широко развернутым или использоваться в нескольких реализациях". Поэтому он рекомендует не ставить перед ним префикс «X-» или аналогичные конструкции.

Однако есть исключение «когда крайне маловероятно, что [ваш заголовок] когда-либо будет стандартизирован». Для таких заголовков «для конкретной реализации и частного использования» RFC говорит, что пространство имен, такое как префикс поставщика, является оправданным.

Эдвард Брей
источник
6
«RFC6648 рекомендует, чтобы вы предполагали, что ваш пользовательский заголовок» может стать стандартизированным, общедоступным, широко развернутым или пригодным для использования в нескольких реализациях. «Я думаю, что это дает основание использовать X-префикс, поскольку более вероятно, что что-то без какого-либо префикса может стать стандартизированным.
Конрад
@Konrad Если вы предполагаете, что чужой аналогичный заголовок (не ваш заголовок) может стать стандартизированным, вы можете избежать конфликта с ним X-, но это предположение отличается от того, которое в первую очередь принимает RFC6648. Исключение RFC учитывает потенциальные конфликты между будущим стандартным заголовком и заголовком другого поставщика, чья технология может стать интегрированной с вашей в результате слияния компаний и т. Д. Именно поэтому исключение требует использования префикса поставщика.
Эдвард Брей
17

Изменение или, вернее, добавление дополнительных заголовков HTTP - отличный инструмент для отладки кода, если ничего больше.

Когда запрос URL-адреса возвращает перенаправление или изображение, отсутствует html-страница для временной записи результатов кода отладки - по крайней мере, не той, которая видна в браузере.

Один из подходов - записать данные в локальный файл журнала и просмотреть его позже. Другой способ - временно добавить заголовки HTTP, отражающие отлаживаемые данные и переменные.

Я регулярно добавляю дополнительные заголовки HTTP, такие как X-fubar-somevar: или X-testing-someresult: чтобы проверить это, - и обнаружил множество ошибок, которые иначе было бы очень трудно отследить.

g1smd
источник
2
Почему он должен использовать этот «стандарт»? Заголовки работают так же. Даже с префиксом WHO_EVER_READS_THIS_IS_DUMB_ ...
Невероятный
16

Реестр имен полей заголовков определен в RFC3864 , и ничего особенного в «X-» нет.

Насколько я могу судить, нет никаких указаний для частных заголовков; сомневайся, избегай их. Или взгляните на HTTP Extension Framework ( RFC 2774 ).

Было бы интересно понять больше варианта использования; почему нельзя добавить информацию в тело сообщения?

Джулиан Решке
источник
13
Основная причина, по которой я рассматриваю некоторые пользовательские заголовки, заключается в том, что я могу принимать решения о маршрутизации без разбора тела ...
Розвель