Является ли синтаксис массива с использованием квадратных скобок в строках 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 извлекается следующее:
-
Синтаксические компоненты
Общий синтаксис 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
Дэвид Н. Джаффериан ответ фантастический. Я просто хочу добавить пару обновлений и практических заметок:
-
В течение многих лет каждый браузер оставлял квадратные скобки в строках запроса, не закодированных при отправке запроса на сервер. (Источник: https://bugzilla.mozilla.org/show_bug.cgi?id=1152455#c6). Таким образом, я полагаю, что огромная часть Интернета стала полагаться на такое поведение, что делает его крайне маловероятным для изменения.
-
Мое прочтение стандарта 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 для]).