Spring отвечает 400 параметром запроса массива

У меня есть следующее сопоставление запроса весенней загрузки @RestController:

@RequestMapping({"/api/blog"})
@RestController
public class BlogController {

   @RequestMapping(value = "/test", method = RequestMethod.GET)
   public Iterable<Blog> filterBy(
        @RequestParam(required = false, name = "filter") String filterStr,
        @RequestParam(required = false, name = "range") String rangeStr,
        @RequestParam(required = false, name = "sort") String sortStr) {

           ...
   }
}

Запрос должен выглядеть так:

GET http://my.api.url/api/blog/test?sort=['title','ASC']&range=[0, 24]&filter = {title:'bar'}

Однако предоставление любого из параметров запроса массива (диапазон и/или сортировка) вызывает ответ 400 без каких-либо подробностей, кроме: «Статус HTTP 400 — неверный запрос».

Выполнение запроса только с параметром запроса файла работает. Добавление диапазона и/или сортировки с нулевыми значениями работает. Вскоре, когда я добавляю скобки [], кажется, что это не удается.

Я попытался добавить следующий обработчик исключений для отладки проблемы как для контроллера, так и для класса ControllerAdvice:

@ExceptionHandler
@ResponseStatus(HttpStatus.BAD_REQUEST)
public void handle(HttpMessageNotReadableException e) {
  logger.warn("Returning HTTP 400 Bad Request", e);
}

Однако это не срабатывает. У меня есть подозрение, что что-то происходит во фреймворке, вызывая 400, прежде чем он даже попадет в контроллер.

Любая помощь приветствуется.

Не могли бы вы опубликовать трассировку стека?

Piotr Podraza 09.02.2019 23:57

Хотел бы я. Ответ равен 400 без каких-либо исключений, что затрудняет отладку.

brad12s 10.02.2019 02:49
1
2
1 351
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

вы должны URL кодировать ваши параметры! при тестировании вы должны URL-кодировать фильтр, диапазон и параметры сортировки. Попробуйте следующее:

 http://my.api.url/api/blog/test?sort%3D%5B%27title%27%2C%27ASC%27%5D%26range%3D%5B0%2C+24%5D%26filter%3D%7Btitle%3A%27bar%27%7D

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

brad12s 10.02.2019 02:57

Попробуйте определить свои параметры как Lists и не используйте скобки.

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public Iterable<Blog> filterBy(
        @RequestParam(required = false, name = "filter") List<String> filterStr,
        @RequestParam(required = false, name = "range") List<String> rangeStr,
        @RequestParam(required = false, name = "sort") List<String> sortStr) {

     filterStr.forEach(s -> System.out.print(", "+ s));
     System.out.println();
     rangeStr.forEach(s -> System.out.print(", "+ s));
     System.out.println();
     sortStr.forEach(s -> System.out.print(", "+ s));
     System.out.println();
     return new ArrayList<>();
    }

    // test url with mockmvc  
    @Test
    public void filterBy() throws Exception {
        mockMvc.perform(get("/test?filter=1,2,3,4&range=5,7,8&sort=desc"))
            .andExpect(status().is2xxSuccessful());
    }

    @Test
    public void filterBy() throws Exception {
       mockMvc.perform(get("/test?filter=1&filter=2&filter=3&filter=4&range=[5,7,8]&sort=desc"))
            .andExpect(status().is2xxSuccessful());
    }

Для меня первые тестовые отпечатки:

, 1, 2, 3, 4
, 5, 7, 8
, desc

Второй тест печатает:

, 1, 2, 3, 4
, [5, 7, 8] // brackets dont seem to work that good
, desc

Я использую внешнюю библиотеку, которая определяет параметры запроса и не может изменить их для этого проекта.

brad12s 10.02.2019 03:03

Другие вопросы по теме