Что допустимо, а что нет в запросе URI?
фон (вопрос дальше)
я гуглил это взад и вперед, читая RFC, и поэтому вопросы пытаются взломать это, но у меня все еще нет Джека.
так что я думаю, мы просто голосуем за "лучший" ответ, и это все, или?
в основном это сводится к этому.
3.4. Компонент Запроса
компонент запроса представляет собой строку информации, которая должна быть интерпретирована ресурсом.
query = *uric
в компоненте запроса, символы ";", "/", "?", ":", "@", "&", "=", "+", ",", и " $ " зарезервированы.
первое, что меня поражает, это то, что * uric определяется так
uric = reserved | unreserved | escaped
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
однако это несколько проясняется такими пунктами, как
" зарезервированный " синтаксический класс выше относится к этим символам они разрешены в URI, но не могут быть разрешены в конкретном компоненте общего синтаксиса URI; они используются в качестве разделителей компонентов, описанных в разделе 3.
символы в наборе" зарезервировано " зарезервированы не во всех контекстах. Набор символов, фактически зарезервированных в любом данном компоненте URI, определяется этим компонентом. В общем случае символ резервируется, если семантика URI изменяется, если символ заменяется его экранированным Кодировка US-ASCII.
этот последний отрывок кажется несколько обратным, но он ясно указывает, что зарезервированный набор символов зависит от контекста. Однако 3.4 утверждает, что все зарезервированные символы зарезервированы в компоненте запроса, однако единственное, что может изменить семантику здесь, - это избежать знака вопроса (?) поскольку URI не определяют понятие строки запроса.
на данный момент я полностью отказался от RFC, но нашел RFC 1738 особенно интересный.
HTTP URL принимает вид:
http://<host>:<port>/<path>?<searchpart>
в компонентах и , "/", ";", "?- зарезервированы. Символ " / " может использоваться в HTTP для обозначения иерархической структуры.
я интерпретирую это, по крайней мере, в отношении http-адресов, которые RFC 1738 заменяет RFC 2396. Поскольку запрос URI не имеет понятия о строке запроса, также интерпретация reserved на самом деле не позволяет мне определять строки запроса, как я привык делать сейчас.
вопрос
все это началось, когда я хотел передать список номеров вместе с запросом другого ресурса. Я не думал об этом, и просто передал его как значения, разделенные запятыми. К моему удивлению, хотя запятая убежала. Запрос page.html?q=1,2,3 закодированный превратился в page.html?q=1%2C2%2C3 это работает, но это некрасиво и не ожидали. Вот тогда я и начал переживать документ RFC.
мой первый вопрос просто, является ли кодирование запятых действительно необходимо?
мой ответ, согласно RFC 2396: да, согласно RFC 1738: нет
позже я нашел связанные сообщения, касающиеся передачи списков между запросами. Где подход csv был сбалансирован как плохой. Это появилось вместо этого, (не видел этого раньше).
page.html?q=1;q=2;q=3
мой второй вопрос, это действительный URL?
мой ответ, согласно RFC 2396: нет, согласно RFC 1738: нет (; зарезервировано)
у меня нет никаких проблем с передачей csv, пока это числа, Но да, вы рискуете столкнуться с необходимостью кодировать и декодировать значения взад и вперед, если запятая вдруг понадобится для чего-то еще. В любом случае, я попробовал строку запроса с запятой ASP.NET и результат оказался не таким, как я ожидал.
Default.aspx?a=1;a=2&b=1&a=3
Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"
Я не вижу, как это сильно отличается от подхода csv, так как когда я прошу "a", я получаю строку с запятые в нем. ASP.NET конечно, это не эталонная реализация, но она еще не подвела меня.
но самое главное -- мой третий вопрос-где спецификация? и что бы вы сделали или не сделали?
7 ответов:
то, что символ зарезервирован в общем компоненте URL, не означает, что он должен быть экранирован, когда он появляется в компоненте или в данных в компоненте. Символ также должен быть определен как разделитель в рамках общего или специфичного для схемы синтаксиса, и внешний вид символа должен быть в пределах данных.
текущий стандарт для универсальных URI RFC 3986, который имеет это, чтобы сказать:
2.2. Зарезервированный Персонажи
URI включают компоненты и подкомпоненты, которые разделены символами в "зарезервированном" наборе. Эти символы называются "зарезервированными", потому что они могут (или не могут) быть определены как разделители общим синтаксисом, каждым синтаксисом конкретной схемы или синтаксисом конкретной реализации алгоритма разыменования URI. Если данные для компонента URI будут конфликт с целью зарезервированного символа в качестве разделителя [Курсив мой], то конфликтующие данные должны быть закодированы в процентах до формирования URI.
reserved = gen-delims / sub-delims gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="3.3. Компонент Пути
[...]pchar = unreserved / pct-encoded / sub-delims / ":" / "@"[...]3.4 Компонент Запроса
[...]query = *( pchar / "/" / "?" )таким образом, запятые явно разрешены в строках запроса и должны быть экранированы только в данных, если определенные схемы определяют его как разделитель. Схема HTTP не использует запятую или точку с запятой в качестве разделителя в строках запроса, поэтому они не должны быть уцелевший. Следуют ли браузеры этому стандарту-другой вопрос.
использование CSV должно отлично работать для строковых данных, вам просто нужно следовать стандартным соглашениям CSV и либо цитировать данные, либо избегать запятых с обратными косыми чертами.
как в RFC 2396, он также позволяет для неэкранированных запятые в HTTP-строки запроса:
2.2. Зарезервированные Символы
многие URI включают компоненты, состоящие из или разделенные, определенные специальный письмена. Эти символы называются "зарезервированными", так как их использование в компоненте URI ограничено их зарезервированными цель. Если данные для компонента URI будут конфликтовать с зарезервированная цель, то конфликтующие данные должны быть экранированы до формирование URI.
поскольку запятые не имеют зарезервированной цели в схеме HTTP, их не нужно экранировать в данных. Примечание из § 2.3 о зарезервированных символах, которые изменяются семантика, когда процентное кодирование применяется только в общем случае; символы могут быть закодированы в процентах без изменения семантики для конкретных схем и все же быть зарезервированы.
чтобы ответить, что допустимо в строке запроса, я проверил, какие специальные символы заменяются chrome при выполнении запроса:
Space -> %20 ! -> ! " -> %22 # -> removed, marks the end of the query string % -> % & -> & ' -> %27 ( -> ( ) -> ) * -> * + -> + (this usually means blank when received at the server, so encode if necessary) , -> , - -> - . -> . / -> / : -> : ; -> ; < -> %3C = -> = > -> %3E ? -> ? @ -> @ [ -> [ \ -> \ ] -> ] ^ -> ^ _ -> _ ` -> ` { -> { | -> | } -> } ~ -> ~ Extended ASCII (like °) -> Every character from this set is encodedПримечание: это, вероятно, не означает, что вы не должны экранировать символы, которые не были заменены при создании URI для ссылок. Например, часто рекомендуется не использовать
~в URI из-за проблем совместимости, но это все еще допустимый символ.еще одним примером может быть знак "плюс", который является допустимым, но обычно обрабатывается как закодированный пробел, когда сервер получает его как часть запроса. Таким образом, он должен быть закодирован, даже если он действителен, когда его цель-представить плюс, а не пробел.
Итак, чтобы ответить, что должно быть закодировано: недопустимые символы и символы, которые вы хотите рассматривать буквально, но имеют особое значение или могут вызвать проблемы на конце сервера.
просто использовать
?q=1+2+3я отвечаю здесь на четвертый вопрос :) который не спрашивал, но все началось с: как я могу передать список чисел а-ля запятые значения? Мне кажется, лучший подход - просто передать их через пробел, где пробелы получат url-форму, закодированную в
+. Отлично работает, пока вы знаете, что значения в списке не содержат пробелов (что-то числа, как правило, не).
страница.HTML-код?q=1;q=2; q=3
это допустимый URL?
Да. Элемент
;зарезервировано, но не RFC. Контекст, который определяет этот компонент является определениеapplication/x-www-form-urlencodedтип носителя, который является частью стандарта HTML (раздел 17.13.4.1). В частности, скрытая записка скрыта в разделе Б. 2.2:мы рекомендуем, чтобы разработчики HTTP-сервера, и в частности, CGI разработчики поддерживают использование"; "вместо"&", чтобы избавить авторов от проблем с экранированием символов " & " таким образом.
к сожалению, многие популярные серверные скриптовые платформы, включая ASP.NET не поддерживайте это использование.
Я хотел бы отметить, что
page.html?q=1&q=2&q=3также является допустимым url. Это совершенно законный способ выражения массива в строке запроса. Ваша серверная технология определит, как именно это представлено.в классическом ASP, вы проверяете
Response.QueryString("q").Countи затем использоватьResponse.QueryString("q")(0)(и (1) и (2)).обратите внимание, что вы видели это в вашем ASP.NET тоже (я думаю, что это не было задумано, но посмотрите):
Default.aspx?a=1;a=2&b=1&a=3 Request.QueryString["a"] = "1;a=2,3" Request.QueryString["b"] = "1"обратите внимание, что точка с запятой игнорируется, поэтому у вас есть
aопределено дважды, и вы получили его значение дважды, разделенное запятой. Используя все амперсандыDefault.aspx?a=1&a=2&b=1&a=3дастaкак "1,2,3". Но я уверен, что есть способ получить каждый отдельный элемент, в случае, если сами элементы содержат запятые. Это просто свойство по умолчанию неиндексированные страницы querystring, что объединяет подгруппы значений с разделителями запятая.
у меня была та же проблема. URL-адрес, который был гиперссылкой, был сторонним URL-адресом и ожидал список параметров в формате
page.html?q=1,2,3только и URLpage.html?q=1%2C2%2C3не работает. Я смог заставить его работать с помощью javascript. Возможно, это не лучший подход, но вы можете проверить решение здесь если это кому-то поможет.
Если вы отправляете закодированные символы в FLASH / SWF файл, то вы должны кодировать символ дважды!! (из-за Flash parser)
Comments