Почему JEE UriBuilder не выполняет двойное кодированиеJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Почему JEE UriBuilder не выполняет двойное кодирование

Сообщение Anonymous »

Рассмотрите этот метод:
import javax.ws.rs.core.UriBuilder;
import java.net.URI;

public class AnyParamRedirecter {

/**
* Generate a URI to target.com with one query parameter "extra"
*/
public URI generateNestedRedirectUrl(String extraParam) {
return UriBuilder.fromPath("http://target.com")
// encodes all special characters, except when they seem already be an encoding
.queryParam("extra", extraParam)
.build();
}
}

Похоже, что в этом коде есть ошибка: когда аргумент extraParam имеет закодированные значения, но все еще нуждается в кодировании (двойном кодировании), queryParam() не будет работать правильно.
(Обратите внимание, что queryParam выполняет одиночное кодирование всех символов, требующих кодирования.)
В качестве примера:
@Test
public void doubleEncodeTest() {
final String deeplyEmbeddedUrlEncoded = URLEncoder.encode("http://other2.com?x=1?y=2", StandardCharsets.UTF_8);
assertEquals(deeplyEmbeddedUrlEncoded, "http%3A%2F%2Fother2.com%3Fx%3D1%3Fy%3D2");
final String embeddedUrl = "http://other.com?c=" + deeplyEmbeddedUrlEncoded;

var redirecter = new AnyParamRedirecter();
URI result = redirecter.generateNestedRedirectUrl(embeddedUrl);
String nestedUrl = result.getQuery().substring("extra=".length());

// assert we get the same thing back that we put it
assertEquals(embeddedUrl, nestedUrl);
}

Даёт:
Expected :http://other.com?c=http%3A%2F%2Fother2. ... D1%3Fy%3D2
Actual :http://other.com?c=http://other2.com?x=1?y=2

где теперь очевидно, что параметры x и y принадлежат URL-адресу "other.com", а не URL-адресу "other2.com".
Я всегда мог бы просто закодировать .queryParam("extra", URLEncoder.encode(extraParam, StandardCharsets.UTF_8)), таким образом, всегда выполнять двойное кодирование, но почему метод queryParam имеет такую странную логику, когда он отказывается снова перекодировать значения, закодированные в процентах?
В javadoc для абстрактного класса javax.ws.rs.core.UriBuilder говорится:
URI template-aware utility class for building URIs from their components. See {@link javax.ws.rs.Path#value} for an explanation of URI templates.

Builder methods perform contextual encoding of characters not permitted in
* the corresponding URI component following the rules of the
* application/x-www-form-urlencoded
* media type for query parameters...

Note that only characters not permitted in a particular component are subject to encoding so,
e.g., a path supplied to one of the {@code path} methods may contain matrix parameters or
multiple path segments since the separators are legal characters and will not be encoded.
Percent encoded values are also recognized where allowed and will not be double encoded.

Мне кажется, что это ошибка спецификации: сказать «служебный класс для создания URI из их компонентов» и сделать исключение «Значения в процентном кодировании также распознаются там, где это разрешено, и не будут подвергаться двойному кодированию».
Можно либо указать, что класс будет создавать URI из своих компонентов, либо что он НЕ правильно кодирует строки для правильного декодирования позже. Кодирование некоторых специальных значений, но НЕ кодирование значений, закодированных в процентах, кажется спецификацией, которая никогда не имеет никакого смысла, если только когда-либо не ожидается обработка значений, которые либо содержат только неэкранированные специальные символы, либо только экранированные специальные символы (и если бы это было так, было бы полезно потерпеть неудачу, когда это предположение не выполняется, вместо того, чтобы возвращать необратимую неправильную мешанину).
Сам метод javadoc не дает никакого предупреждения о таком поведении:
Append a query parameter to the existing set of query parameters. If multiple values are supplied the parameter will be added once per value.

Parameters:
name - the query parameter name, may contain URI template parameters
values - the query parameter value(s), each object will be converted to a String using its toString() method. Stringified values may contain URI template parameters.
Returns:
the updated UriBuilder
Throws:
java.lang.IllegalArgumentException - if name or values is null


Подробнее здесь: https://stackoverflow.com/questions/798 ... ble-encode
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»