brad12s
brad12s

Reputation: 409

Spring responds 400 with array query param

I have the following spring boot @RestController request mapping:

@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) {

           ...
   }
}

The request should look like so:

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

However providing any of the array query parameters (range and/or sort) causes a response of 400 with no details other than: "HTTP Status 400 - Bad Request"

Making a request with only the filer query parm works. Adding range and/or sort with null values works. Soon as i add the brackets [] it appears to fail.

I have tried to add the following Exception handler to debug the problem to both the controller and a ControllerAdvice class:

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

However this does not get triggered. I have a suspicion that something is happening in the framework causing the 400 before it even gets to the controller.

Any help is appreciated.

Upvotes: 1

Views: 4205

Answers (2)

thomas77
thomas77

Reputation: 1150

Try defining your parameters as Lists and dont use brackets.

    @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());
    }

For me the first test prints:

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

The second test prints:

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

Upvotes: 1

Hasson
Hasson

Reputation: 1914

you have to URL encode your parameters! when you test, you should URL encode the filter, the range and the sort parameters. Try the following:

 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

Upvotes: 0

Related Questions