Странная проблема с кодировкой URL
У меня странная проблема с urlencoding знаком плюс+
в качестве параметра запроса для запроса к API. Документация API гласит:
Дата должна быть в формате W3C, например '2016-10-24T13: 33: 23 + 02: 00'.
Пока все хорошо, поэтому я использую этот код (минимизированный) для генерации URL, используя Spring UriComponentBuilder:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX");
ZonedDateTime dateTime = ZonedDateTime.now().minusDays(1);
String formated = dateTime.format(formatter);
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUriString(baseUrl);
uriComponentsBuilder.queryParam("update", formated);
uriComponentsBuilder.build();
String url = uriComponentsBuilder.toUriString();
Незакодированный запрос будет выглядеть так:
https://example.com?update=2017-01-05T12:40:44+01
Закодированная строка приводит к:
https://example.com?update=2017-01-05T12:40:44%2B01
которая (ИМХО) является правильно закодированной строкой запроса. Увидеть%2B
заменяя+
в+01
в конце строки запроса.
Однако теперь, когда я отправляю запрос к API с использованием закодированного URL, я получаю сообщение об ошибке, в котором говорится, что запрос не может быть обработан.
Если, однако, я заменяю%2B
с+
перед отправкой запроса работает:
url.replaceAll("%2B", "+");
Из моего понимания+
знак является заменойwhitespace
, Таким образом, URL, который сервер действительно видит после декодирования, должен быть
https://example.com?update=2017-01-05T12:40:44 01
Я прав с этим предположением?
Могу ли я что-нибудь сделать, кроме как связаться с владельцем API, чтобы заставить его работать с использованием правильно закодированного запроса, кроме странных нестандартных замен строк?
ОБНОВИТЬ:
Согласно спецификацииRFC 3986 (Раздел 3.4),+
войти в параметр запроса не нужно кодировать.
3.4. запрос
Компонент запроса содержит неиерархические данные, которые наряду с данными в компоненте пути (раздел 3.3) служат для идентификации
ресурс в рамках схемы URI и полномочий по именованию
(если есть). Компонент запроса обозначен первым вопросом
знак ("?") и оканчивается символом цифры ("#")
или к концу URI.
Бернерс-Ли и др. Отслеживание стандартов [Страница 23] Общий синтаксис RFC 3986 URI
Январь 2005
query = *( pchar / "/" / "?" )
Косая черта ("/") и знак вопроса ("?") Могут представлять данные в компоненте запроса. Помните, что некоторые старые, ошибочные реализации могут некорректно обрабатывать такие данные, когда они используются в качестве базового URI для относительных ссылок (раздел 5.1), по-видимому
потому что они не могут отличить данные запроса от данных пути, когда
ищу иерархические разделители. Однако в качестве компонентов запроса
часто используются для переноса идентифицирующей информации в форме
пары «ключ = значение» и одно часто используемое значение является ссылкой на
другой URI, иногда для удобства использования лучше избегать
кодирование этих символов.
В соответствии сэтот ответ на stackoverflowSpring UriComponentBuilder использует эту спецификацию, но, по-видимому, на самом деле это не так. Таким образом, новый вопрос будет, как заставить UriComponentBuilder следовать спецификациям?