Невозможно проверить литерал '+' в параметре запроса с помощью TestRestTemplate - PullRequest
0 голосов
/ 29 апреля 2018

В микро-сервисе, основанном на Spring Boot 2.0.1, у меня есть GET Rest контроллер, который принимает fromDate & toDate, закодированные в виде строк ISO (укороченные):

@GetMapping(value = "/range")
public ResponseEntity<MyDTO> getDateRange(
        @RequestParam
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
                ZonedDateTime fromDate,
        @RequestParam
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
                ZonedDateTime toDate) {

    if (fromDate.isAfter(toDate) || fromDate.isEqual(toDate)) {
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    }

    return new ResponseEntity<>(HttpStatus.OK);
}

Таким образом, запросы должны выглядеть примерно так (полностью URLEncoded):

http://localhost:8080/range/?fromDate=2015-05-31T03%3A00%3A00.000%2B04%3A00&toDate=2015-05-31T03%3A30%3A00.000%2B04%3A00

Или только с экранированием +:

http://localhost:8080/range/?fromDate=2015-05-31T03:00:00.000%2B04:00&toDate=2015-05-31T03:30:00.000%2B04:00

Для справки, строка без кодировки URI:

http://localhost:8080/range/?fromDate=2015-05-31T03:00:00.000+04:00&toDate=2015-05-31T03:30:00.000+04:00 - что не работает.

Этот контроллер покоя работает просто отлично, когда я выполняю GETs через Почтальона или через тесты с использованием MockMvc в Spring Boot. Но для полноты и моего собственного понимания я бы также хотел проверить через TestRestTemplate. Однако кое-что об использовании + в параметрах проблематично. Но я не могу понять, почему.

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class IntegrationTests {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void test_get_in_range() throws Exception {
//        String uri = "/range?fromDate={fromDate}&toDate={toDate}";
//
//        Map<String, String> uriParams = new HashMap<>();
//        uriParams.put("fromDate", "2015-05-31T03:00:00.000+04:00");
//        uriParams.put("toDate", "2015-05-31T19:00:00.000+04:00");

        UriComponents uriComponents = UriComponentsBuilder
            .fromPath("/range")
            .queryParam("fromDate", "2015-05-31T03:00:00.000+04:00")
            .queryParam("toDate", "2015-05-31T19:00:00.000+04:00").build();
// Also tried with manually replacing + with %2B
// Also tried manually encoding the string

        ResponseEntity<String> getResponseEntity = restTemplate.withBasicAuth("cameraUser", "change_me")
                .getForEntity(uriComponents.toUriString(), String.class);
    }
}

Результат с сервера Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.ZonedDateTime] for value '2015-05-31T03:00:00.000 04:00'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2015-05-31T03:00:00.000 04:00] Кажется, что + в строке заменяется пробелом, что также происходит, когда я выполняю некодированный запрос GET от Почтальона.

Замена + на %2B в тесте дает:

Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.ZonedDateTime] for value '2015-05-31T03:00:00.000%2B04:00'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2015-05-31T03:00:00.000%2B04:00]

Кто-нибудь знает почему? Я подозреваю, что это как-то связано с автоконфигурацией и не использует те же фильтры / преобразователи (неясно с терминологией) в тестовом режиме, что и при выполнении по умолчанию. Я не регистрирую никаких дополнительных конвертеров и полностью полагаюсь на автоматическую настройку Spring Boot.

Редактировать: я создал пример приложения, показывающего проблему здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...