Предыстория (вопрос ниже)
Я гуглил это взад и вперед, читая RFC и вопросы SO, пытаясь взломать это, но у меня все еще нет разъема.
Думаю, мы просто голосуем за «лучший» ответ и все, или?
В основном все сводится к этому.
3.4. Компонент запроса
Компонент запроса - это строка информации, которую должен интерпретировать ресурс.
query = *uric
Внутри компонента запроса символы «;», «/», «?», «:», «@», «&», «=», «+», «,» И «$» зарезервированы.
Первое, что меня смущает, это то, что * uric определяется так
uric = reserved | unreserved | escaped
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
Однако это несколько поясняется такими параграфами, как
Вышеупомянутый «зарезервированный» синтаксический класс относится к тем символам, которые разрешены в URI, но не могут быть разрешены в конкретном компоненте универсального синтаксиса URI; они используются как разделители компонентов, описанных в разделе 3.
Символы в «зарезервированном» наборе зарезервированы не во всех контекстах. Набор символов, фактически зарезервированных в любом данном компоненте URI, определяется этим компонентом. Как правило, символ зарезервирован, если семантика URI изменяется, если символ заменяется его экранированной кодировкой US-ASCII.
Этот последний отрывок кажется несколько отсталым, но он ясно заявляет, что зарезервированный набор символов зависит от контекста. Тем не менее, в 3.4 говорится, что все зарезервированные символы зарезервированы в компоненте запроса, однако единственное, что может изменить семантику здесь, - это экранирование вопросительного знака (?), Поскольку URI не определяют концепцию строки запроса.
На этом этапе я полностью отказался от RFC, но нашел RFC 1738 особенно интересным.
URL-адрес HTTP принимает форму:
http://<host>:<port>/<path>?<searchpart>
Внутри компонентов <path> и <searchpart> "/", ";", "?" зарезервированы. Символ «/» может использоваться в HTTP для обозначения иерархической структуры.
Я интерпретирую это, по крайней мере, в отношении URL-адресов HTTP, которые RFC 1738 заменяет RFC 2396. Поскольку запрос URI не имеет понятия о строке запроса, также интерпретация зарезервированного не позволяет мне определять строки запроса, как я привык делаю к настоящему времени.
Вопрос
Все началось с того, что я хотел передать список чисел вместе с запросом другого ресурса. Я не особо задумывался об этом и просто передал его как значения, разделенные запятыми. К моему удивлению, запятая была убрана. 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, конечно, не эталонная реализация, но меня она еще не подвела.
Но самое главное - третий вопрос - а где для этого спецификация? и что бы вы сделали или не стали бы делать?
источник
Ответы:
То, что символ зарезервирован в общем компоненте URL, не означает, что он должен быть экранирован, когда он появляется в компоненте или в данных в компоненте. Символ также должен быть определен как разделитель в общем синтаксисе или синтаксисе конкретной схемы, и внешний вид символа должен находиться в данных.
Текущий стандарт универсальных URI - RFC 3986 , в котором говорится следующее:
Таким образом, запятые явно разрешены в строках запроса и должны быть экранированы в данных только в том случае, если определенные схемы определяют это как разделитель. Схема HTTP не использует запятую или точку с запятой в качестве разделителя в строках запроса, поэтому их не нужно экранировать. Другой вопрос, соответствуют ли браузеры этому стандарту.
Использование CSV должно нормально работать для строковых данных, вам просто нужно следовать стандартным соглашениям CSV и либо указывать данные, либо экранировать запятые с помощью обратной косой черты.
Что касается RFC 2396, он также позволяет использовать неэкранированные запятые в строках запроса HTTP:
Поскольку в схеме HTTP запятые не имеют зарезервированного назначения, их не нужно экранировать в данных. Замечание из п. 2.3 о зарезервированных символах, которые изменяют семантику при процентном кодировании, применяется только в общем случае; символы могут быть закодированы в процентах без изменения семантики для конкретных схем и при этом оставаться зарезервированными.
источник
Чтобы ответить, что допустимо в строке запроса, я проверил, какие специальные символы заменяются хромом при выполнении запроса:
Примечание. Это, вероятно, не означает, что вам не следует экранировать символы, которые не были заменены при создании URI для ссылок. Например, часто рекомендуется не использовать
~
в URI из-за проблем совместимости, но это все еще допустимый символ.Другим примером может быть знак плюса, который действителен, но обычно рассматривается как закодированный пробел, когда сервер получает его как часть запроса. Таким образом, он должен быть закодирован, даже если он действителен, когда его цель - представить плюс, а не пробел.
Итак, чтобы ответить, что следует закодировать: недопустимые символы и символы, которые вы хотите обрабатывать буквально, но имеют особое значение или могут вызвать проблемы на стороне сервера.
источник
/programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b#1;c#2
допустимый параметр запроса?#
не может отображаться внутри части запроса URI как есть. Вам нужно будет закодировать его как%23
, чтобы URI был/programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b%231;c%232
.Просто используйте
?q=1+2+3
Я отвечаю здесь на четвертый вопрос :), который не задавал, но все началось с: как передать список чисел а-ля значения, разделенные запятыми? Мне кажется, лучший подход - просто передать их через пробел, где пробелы будут закодированы в форме URL
+
. Отлично работает, если вы знаете, что значения в списке не содержат пробелов (а числа, как правило, не содержат).источник
+
имеет даже больше смысла в конкретном случае, когда я хотел использовать запятую.Да.
;
Зарезервирован, но не в RFC. Контекст, который определяет этот компонент, - это определение типаapplication/x-www-form-urlencoded
носителя, который является частью стандарта HTML (раздел 17.13.4.1 ). В частности, скрытая заметка, спрятанная в разделе B.2.2 :К сожалению, многие популярные серверные платформы сценариев, включая ASP.NET, не поддерживают такое использование.
источник
?q=1;q=2;q=3
запрос действителен, он неоднозначен: одни серверные фреймворки будут читать его как означающее{ q: '1;q=2;q=3' }
, другие могут делать то же самое{ q: {'1', '2', '3'}}
.;
, что означает, что HTML4 и HTML5 несовместимы. Ух, опасность ненормативного языка в документе спецификации ...{ q: 3 }
Я хотел бы отметить, что
page.html?q=1&q=2&q=3
это тоже действующий URL. Это вполне законный способ выражения массива в строке запроса. Ваша серверная технология определит, как именно это будет представлено.В классическом ASP вы проверяете,
Response.QueryString("q").Count
а затем используетеResponse.QueryString("q")(0)
(и (1) и (2)).Обратите внимание, что вы также видели это в своем ASP.NET (я думаю, что это не было предназначено, но посмотрите):
Обратите внимание, что точка с запятой игнорируется, поэтому вы
a
определили дважды и дважды получили ее значение, разделенное запятой. Использование всех амперсандовDefault.aspx?a=1&a=2&b=1&a=3
даст результатa
«1,2,3». Но я уверен, что есть способ получить каждый отдельный элемент, если сами элементы содержат запятые. Это просто свойство по умолчанию для неиндексированной QueryString, которое объединяет вложенные значения вместе с разделителями-запятыми.источник
Я была такая же проблема. URL-адрес, на который была сделана гиперссылка, был сторонним URL-адресом и ожидал список параметров
page.html?q=1,2,3
ТОЛЬКО в формате, а URL-адресpage.html?q=1%2C2%2C3
не работал. Мне удалось заставить его работать с помощью javascript. Возможно, это не лучший подход, но вы можете проверить решение здесь, если оно кому-то поможет.источник
Если вы отправляете закодированные символы в файл FLASH / SWF , вам следует КОДИРОВАТЬ символ дважды !! (из-за парсера Flash)
источник