2015-04-09 3 views
2

Я разбираю заголовки HTTP. Я хочу разбить значения заголовков на массивы, где это имеет смысл.Как разделять значения заголовков?

Например, Cache-Control: no-cache, no-store должен вернуть ['no-cache','no-store'].

HTTP RFC2616 говорит:

Несколько полей заголовка с тем же имя поля может присутствовать в сообщении, если и только если все значения поля для этого поля заголовка определяется как список, разделенный запятыми [т.е., # (значения)]. Можно объединить несколько полей заголовка в одну строку «field-name: field-value» , не меняя семантики сообщения , добавив каждое последующее значение поля к первому, каждый , разделенный символом « », каждый из которых равен . запятая. Порядок, в котором получены поля заголовка с тем же имя поля имеет значение для интерпретации значения комбинированного поля, и, таким образом, прокси-сервер НЕ ДОЛЖЕН изменять порядок этих значений полей, когда сообщение пересылается

Но я не уверен, верно ли обратное - безопасно ли оно split по запятой?

Я уже нашел один пример, где это вызывает проблемы. Моя строка User-Agent, например,

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36 

, т.е. он содержит запятую после "KHTML". Очевидно, что у меня не более одного пользовательского агента, поэтому разделить этот заголовок не имеет смысла.

Является ли строка User-Agent единственным исключением, или есть еще?

ответ

2

Нет, это не безопасно разделять заголовки на основе запятых. В качестве примера Accept: foo/bar;p="A,B,C", bob/dole;x="apples,oranges" является допустимым заголовком, но если вы попытаетесь разделить запятую с целью получения списка типов mime, вы получите недопустимые результаты.

Правильный ответ заключается в том, что каждый заголовок указан с использованием ABNF, большинство из них в различных RFC, например. Accept: является defined in RFC7231 Section 5.3.2.

У меня была эта специфическая проблема и wrote a parser и tested it on edge cases. Не только parsing the header non-trivial, интерпретируя его и давая correct result is also non-trivial.

Некоторые заголовки более сложны, чем другие, но по существу у каждого заголовка есть своя грамматика, которая должна соблюдаться для правильной (и безопасной) обработки.

1

, если все поле значение для этого поля заголовка определен как разделенный запятыми список [то есть, # (значения)]

Так что это наоборот. Вы можете только предположить, что Field: value1, value2 эквивалентен Field: value1 + Field: value2, когда спецификации говорят, что Field поддерживает #(value), то есть список значений, разделенных запятыми.

+0

Ну, вот что я пытался сказать «Я не уверен, верно ли обратное». Где-то я могу найти список заголовков, которые поддерживают разделение запятой, чтобы я мог хотя бы создать черный или белый список? – mpen

+0

@Mark Я пытался найти их, но [RFC2616] (http://tools.ietf.org/html/rfc2616), [RFC7230] (http://tools.ietf.org/html/rfc7230) и [RFC7231] (http://tools.ietf.org/html/rfc7231) не являются исчерпывающими. – CodeCaster

0

Читая спецификации, я пришел к выводу, что следующие заголовки поддерживают несколько (через запятую) значения:

  • Accept
  • Accept-Charset
  • Accept-Encoding
  • Accept-Language
  • Приемо-патч
  • Диапазон принимающих
  • Разрешить
  • Cache-Control
  • Подключение
  • Content-Encoding
  • Content-Language
  • Ожидать
  • If-Match
  • If-None-Match
  • Pragma
  • Proxy -Аутентификация
  • TE
  • Прицеп
  • Transfer-Encoding
  • Upgrade
  • Варах
  • Via
  • Предупреждение
  • WWW-Authenticate
  • X-Forwarded-For

Вы можете использовать это создать белый список расщепляемых заголовков.

+0

И Set-Cookie конечно. – CodeCaster

+0

@CodeCaster Я намеренно оставил «Set-Cookie» на самом деле.Пример из Википедии показывает 'sessionToken = abc123; Expires = Wed, 09 Jun 2021 10:18:14 GMT' - в середине даты есть запятая. Я не уверен, что есть способ поставить более одного Set-Cookie на линию, не так ли? – mpen

+1

Как насчет 'Accept: foo/bar; p =" A, B "'? Это верно, но разделение на запятую не даст желаемых результатов. Лучше использовать конкретные парсеры на основе спецификаций RFC, например. https://github.com/ioquatix/http-accept – ioquatix

 Смежные вопросы

  • Нет связанных вопросов^_^