URL для кодировки URI изменяет «% 3D» на «% 253D» - PullRequest
13 голосов
/ 01 февраля 2011

У меня проблемы с кодированием URL-адреса в URI:

mUrl = "A string url that needs to be encoded for use in a new HttpGet()";
URL url = new URL(mUrl);
URI uri = new URI(url.getProtocol(), url.getAuthority(), url.getPath(), 
    url.getQuery(), null);

Это не соответствует ожиданиям для следующего URL-адреса:

Передача строки:

http://m.bloomingdales.com/img?url=http%3A%2F%2Fimages.bloomingdales.com%2Fis%2Fimage%2FBLM%2Fproducts%2F3%2Foptimized%2F1140443_fpx.tif%3Fwid%3D52%26qlt%3D90%2C0%26layer%3Dcomp%26op_sharpen%3D0%26resMode%3Dsharp2%26op_usm%3D0.7%2C1.0%2C0.5%2C0%26fmt%3Djpeg&ttl=30d

Выпускается как:

http://m.bloomingdales.com/img?url=http%253A%252F%252Fimages.bloomingdales.com%252Fis%252Fimage%252FBLM%252Fproducts%252F3%252Foptimized%252F1140443_fpx.tif%253Fwid%253D52%2526qlt%253D90%252C0%2526layer%253Dcomp%2526op_sharpen%253D0%2526resMode%253Dsharp2%2526op_usm%253D0.7%252C1.0%252C0.5%252C0%2526fmt%253Djpeg&ttl=30d

Что сломано.Например, %3D превращается в %253D Кажется, он делает что-то загадочное с%, уже находящимся в строке.

Что происходит и что я здесь не так делаю?

Ответы [ 4 ]

28 голосов
/ 01 февраля 2011

Сначала вы помещаете (уже экранированную) строку в класс URL. Это ничего не избежит. Затем вы вытаскиваете секции URL, которые возвращают их без какой-либо дальнейшей обработки (то есть - они по-прежнему экранированы, поскольку они были экранированы, когда вы их вставляли). Наконец, вы помещаете разделы в класс URI, используя конструктор с несколькими аргументами . Этот конструктор указан как кодирующий компоненты URI с использованием процентов.

Следовательно, именно на этом последнем этапе, например, ":" становится "%3A" (хорошо), а "%3A" становится "%253A" (плохо). Поскольку вы вводите URL-адреса, которые уже закодированы *, вы не хотите их кодировать снова.

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

mUrl = "A string url is already percent-encoded for use in a new HttpGet()";
URI uri = new URI(mUrl);

* Единственная проблема в том, что ваши URL-адреса иногда не кодируются в процентах, а иногда и так. Тогда у вас есть большая проблема. Вам нужно решить, начинается ли ваша программа с URL-адреса, который всегда закодирован, или с тем, который необходимо кодировать.

Обратите внимание, что нет такой вещи как полный URL, который не кодируется в процентах. Например, вы не можете взять полный URL-адрес «http://example.com/bob&co» и каким-то образом превратить его в правильно закодированный URL-адрес «http://example.com/bob%26co» - как вы можете определить разницу между синтаксисом (который не должен быть экранирован) а персонажи (которые должны)? Вот почему форма единственного аргумента URI требует, чтобы строки уже экранировались. Если у вас есть неэкранированные строки, вам нужно кодировать их в процентах до , вставляя их в полный синтаксис URL, и это то, что помогает вам сделать конструктор с несколькими аргументами URI.

Редактировать: Я пропустил тот факт, что оригинальный код отбрасывает фрагмент. Если вы хотите удалить фрагмент (или любую другую часть) URL-адреса, вы можете создать URI, как указано выше, а затем вытянуть все части по мере необходимости (они будут декодированы в обычные строки). , а затем передайте их обратно в URI конструктор с несколькими аргументами (где они будут перекодированы в качестве компонентов URI):

uri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(),
              uri.getPath(), uri.getQuery(), null)  // Remove fragment
4 голосов
/ 04 августа 2015

% 3d означает-> = (равно)

А

% 253D -> = (равно) десятичное 6hex (байт) 3D

% 253D шестнадцатеричный индикатор для CGI: % 3D

4 голосов
/ 01 февраля 2011

Класс URL не декодировал% -последовательности при разборе URL, но класс URI кодирует их (снова).Используйте URI для анализа строки URL.

Javadocs:

http://download.oracle.com/javase/6/docs/api/java/net/URL.html

Класс URL несам кодирует или декодирует любые компоненты URL в соответствии с механизмом экранирования, определенным в RFC2396.Вызывающая сторона несет ответственность за кодирование любых полей, которые должны быть экранированы до вызова URL, а также за декодирование любых экранированных полей, которые возвращаются из URL.Кроме того, поскольку URL не знает, что такое экранирование, он не распознает эквивалентность между закодированной или декодированной формой одного и того же URL.Например, два URL-адреса:

http://foo.com/hello world/ and http://foo.com/hello%20world

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

Рекомендованным способом управления кодированием и декодированием URL-адресов является использование URI и преобразование между этими двумя классами с помощью toURI () и URI.toURL ().

0 голосов
/ 01 февраля 2011

Здесь происходит то, что знаки % с первого URL-адреса экранируются, что означает, что они выводятся в %25 на выходе.Вы должны принять меры предосторожности, чтобы ваш сценарий экранировал только буквенно-цифровые символы, а также некоторые символы - но не уже экранированные символы.

Это некоторые символы, которые НУЖНЫ экранировать:

<
>
"
!
#
$
'
(
)
*
,
-
.
/
:
;
@
[
\
]
^
_
`
{
|
}
~

Остальные, как =, % и &, а также буквенно-цифровые символы, не являются.

...