Является ли синтаксис массива с использованием квадратных скобок в строках URL-запроса действительным?

Действительно ли безопасно/допустимо использовать синтаксис многомерного массива в строке запроса URL?

http://example.com?abc[]=123&abc[]=456

Кажется, он работает в каждом браузере, и я всегда думал, что это нормально использовать, но accodring к комментарию в этой статье это не: http://www.456bereastreet.com/archive/201008/what_characters_are_allowed_unencoded_in_query_strings/#comment4

Я хотел бы услышать второе мнение.

Ответы

Ответ 1

Ответ прост.

Из раздела 3.2.2 RFC 3986 извлечено следующее:

Хост, идентифицированный литеральным адресом интернет-протокола, версия 6
[RFC3513] или более поздняя версия, отличается тем, что содержит IP-литерал в квадратных скобках ( "[" и "]" ). Это единственное место, где символы квадратной скобки допускаются в синтаксисе URI.

Это, кажется, отвечает на вопрос, настойчиво заявляя, что квадратные скобки не разрешены нигде в URI. Но существует разница между символом квадратной скобки и символом квадратной скобки, закодированным в процентах.

Из начала раздела 3 RFC 3986 извлекается следующее:

  1. Синтаксические компоненты

    Общий синтаксис URI состоит из иерархической последовательности компоненты, обозначенные как схема, полномочия, путь, запрос и фрагмент.

    URI = схема ":" hier-part [ "?" query] [ "#" фрагмент]

Таким образом, "запрос" является компонентом "URI".

Из раздела 2.2 RFC 3986 извлечено следующее:

2,2. Зарезервированные символы

URI включают компоненты и подкомпоненты, которые ограничены с помощью символов в "зарезервированном" наборе. Эти символы называются "зарезервировано", потому что они могут (или не могут) быть определены как разделители с помощью общий синтаксис, каждый синтаксис конкретной схемы или специфичный для реализации синтаксис алгоритма разыменования URI.
Если данные для компонента URI будут конфликтовать с зарезервированным назначение символа в качестве разделителя, тогда конфликтующие данные должны быть закодированным до кодирования URI.

  reserved    = gen-delims / sub-delims

  gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"

  sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

Таким образом, квадратные скобки могут появляться в строке запроса, но только в том случае, если они закодированы в процентах. Если это не так, объясните далее в разделе 2.2:

Приложения, создающие URI, должны иметь октеты данных с процентным кодированием, которые
соответствуют символам зарезервированного набора, если только эти символы специально разрешены схемой URI для представления данных в том, что компонент. Если зарезервированный символ найден в компоненте URI и
для этого персонажа не определена роль разграничения, тогда она должна быть интерпретируется как представляющий октет данных, соответствующий тому, что кодировка символов в US-ASCII.

Так как квадратные скобки разрешены только в подкомпоненте "хозяин", они "должны" быть закодированы в процентах в других компонентах и ​​подкомпонентах, и в этом случае в компоненте "запрос", если RFC 3986 явно не разрешает квадратные скобки без привязки к представляют данные в компоненте запроса, а это не так.

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

Вот почему, например, это не является нарушением RFC 3986, когда PHP принимает как незакодированные, так и закодированные в процентах квадратные скобки как допустимые символы в строке запроса и даже присваивает им особую цель. Тем не менее, похоже, что авторы, которые пытаются использовать эту лазейку, а не проценты, кодирующие квадратные скобки, являются нарушением RFC 3986.

Ответ 2

Согласно RFC 3986, компонент запроса URL-адреса имеет следующую грамматику:

*( pchar / "/" / "?" )

Из приложение A того же RFC:

pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
[...]
pct-encoded   = "%" HEXDIG HEXDIG

unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
[...]    
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
             / "*" / "+" / "," / ";" / "="

Моя интерпретация этого заключается в том, что все, что не является:

 ALPHA / DIGIT / "-" / "." / "_" / "~" / 
     "!" / "$" / "&" / "'" / "(" / ")" / 
     "*" / "+" / "," / ";" / "=" / ":" / "@"

... должен быть закодирован в pct, то есть в процентах. Таким образом, [ и ] должны быть закодированы в процентах, чтобы следовать RFC 3986.

Ответ 3

Дэвид Н. Джаффериан ответ фантастический. Я просто хочу добавить пару обновлений и практических заметок:

  1. В течение многих лет каждый браузер оставлял квадратные скобки в строках запроса, не закодированных при отправке запроса на сервер. (Источник: https://bugzilla.mozilla.org/show_bug.cgi?id=1152455#c6). Таким образом, я полагаю, что огромная часть Интернета стала полагаться на такое поведение, что делает его крайне маловероятным для изменения.

  2. Мое прочтение стандарта URL WHATWG, который, по крайней мере для веб-целей, можно рассматривать как замену RFC 3986, заключается в том, что он кодифицирует такое поведение, как не кодирование [ и ] в строках запроса. Я полагаю, что соответствующая часть: https://url.spec.whatwg.org/#query-state, которая не упоминает о процентном кодировании этих символов.

Ответ 4

У меня всегда было искушение пойти на такой запрос, когда мне пришлось передать массив, но я отступил от него. Причина в том, что:

  • Он не очищается в RFC.
  • Различные языки могут интерпретировать его по-разному.

У вас есть пара опций для передачи массива:

  • Кодировать строковое представление массива (JSON может быть?)
  • Параметры, такие как "val1 = blah & val2 = blah &.." или что-то в этом роде.

И если вы уверены в том, какой язык вы используете, вы можете (безопасно) пойти на тип строки запроса, которую вы имеете (просто, что вам нужно также% -encode []).

Ответ 5

Мое понимание того, что квадратные скобки в любом случае не являются первоклассными гражданами. Вот цитата: http://tools.ietf.org/html/rfc1738

Другие символы небезопасны, поскольку шлюзы и другой транспорт агенты, как известно, иногда модифицируют такие символы. Эти символы "{", "}", "|", "\", "^", "~", "[", "]" и "`".

Ответ 6

В идеале я бы хотел прокомментировать ответ Итана, но у меня недостаточно репутации, чтобы это сделать.

Я не уверен, что здесь упоминается соответствующая часть стандарта URL WHATWG. Я думаю, что правильная часть могла бы быть в определении допустимой строки запроса URL, которую она описывает как составленную из единиц URL, которые сами сформированы из кодовых точек URL и байтов, закодированных в процентах. Квадратные скобки перечислены в кодовых точках URL и, таким образом, попадают в категорию байтов в процентах.

Таким образом, в ответ на исходный вопрос допустим синтаксис многомерного массива (т.е. использование квадратных скобок для представления индексации массива) в части запроса URL-адреса, при условии, что квадратные скобки кодируются в процентах (как% 5B для [и% 5D для]).