RestTemplate НЕ экранировать URL

Я успешно использую Spring RestTemplate следующим образом:

String url = "http://example.com/path/to/my/thing/{parameter}";
ResponseEntity<MyClass> response = restTemplate.postForEntity(url, payload, MyClass.class, parameter);

И это хорошо.

Однако иногда parameter равно %2F. Я знаю, что это не идеально, но это то, что есть. Правильный URL-адрес должен быть: http://example.com/path/to/my/thing/%2F, но когда я устанавливаю parameter в "%2F", он дважды экранируется в http://example.com/path/to/my/thing/%252F. Как предотвратить это?


person huwr    schedule 28.01.2015    source источник


Ответы (2)


Вместо использования URL-адреса String создайте URI с UriComponentsBuilder.

String url = "http://example.com/path/to/my/thing/";
String parameter = "%2F";
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).path(parameter);
UriComponents components = builder.build(true);
URI uri = components.toUri();
System.out.println(uri); // prints "http://example.com/path/to/my/thing/%2F"

Используйте UriComponentsBuilder#build(boolean) для указания

все ли компоненты, установленные в этом конструкторе, закодированы (true) или нет (false)

Это более или менее эквивалентно замене {parameter} и самостоятельному созданию объекта URI.

String url = "http://example.com/path/to/my/thing/{parameter}";
url = url.replace("{parameter}", "%2F");
URI uri = new URI(url);
System.out.println(uri);

Затем вы можете использовать этот объект URI в качестве первого аргумента метода postForObject.

person Sotirios Delimanolis    schedule 28.01.2015
comment
Спасибо. Я решил это немного по-другому. В реальной жизни мой URL больше похож на http://example.com/path/{param}/to/place, поэтому я сделал UriComponentsBuilder.fromHttpUrl(url.replace("{param}", parameter)). - person huwr; 28.01.2015
comment
Я обнаружил, что лучше использовать UriComponentsBuilder.fromUriString() вместо fromHttpUrl(), потому что он позволяет использовать URI в форме /path/without/host, что полезно при тестировании с Spring MockMvc. - person Adam Michalik; 07.07.2016
comment
Почему это не ошибка? Это должно быть как минимум задокументировано в Javadoc. - person George Sofianos; 04.04.2018
comment
@GeorgeSofianos Это задокументировано в Примечании в RestTemplate javadoc, здесь. Предполагается, что параметры шаблона нуждаются в кодировании. - person Sotirios Delimanolis; 04.04.2018

Вы можете сообщить оставшемуся шаблону, что вы уже закодировали uri. Это можно сделать с помощью UriComponentsBuilder.build(true). Таким образом, оставшийся шаблон не будет повторно пытаться избежать uri. Большинство остальных API-интерфейсов шаблонов принимают URI в качестве первого аргумента.

String url = "http://example.com/path/to/my/thing/{parameter}";
url = url.replace("{parameter}", "%2F");
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
// Indicate that the components are already escaped
URI uri = builder.build(true).toUri();
ResponseEntity<MyClass> response = restTemplate.postForEntity(uri, payload, MyClass.class, parameter);
person rouble    schedule 16.06.2017