javaspringspring-bootspring-mvchttp-request-parameters

Spring GET method how to raise Exception if an unknown request param in controller


So I have in my controller a GET method with optional request params:

@GetMapping(path = "/users/search")
    public @ResponseBody ResponseEntity<List<User>> getUserLike(
      @RequestParam(name = "id", required = false) Long id,
      @RequestParam(name = "name", required = false) String name,
      @RequestParam(name = "dateofbirth", required = false) @DateTimeFormat(pattern = "dd-MM-yyyy") LocalDate dateOfBirth
    ) {
      return userService.getUserLike(id, name, dateOfBirth);
    }

When I try to call this request with unknown parameters

/users/search?id=1&myunknownparam=unknownParam

I'd like to raise an Exception when request has unknown param such as myunknownparam here.

Though for now as all my parameters are optional my service returns the same result as it would with all the parameters set to null.


Solution

  • Query param are often optional, so it's rare that a server could reject you because of that.
    But what you are trying to achieve can be implemented with an Interceptor, you need some reflection to get the parameters of your method and verify that each client param is defined on the signature of your method.

    Something like:

    @Component
    public class QueryParamInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) {
            Map<String, String[]> clientRequestParameters = request.getParameterMap();
            MethodParameter[] methodParameters = ((HandlerMethod) handler).getMethodParameters();
            List<String> definedMethodsParameters = Arrays.stream(methodParameters)
                    .flatMap(methodParameter -> Arrays.stream(methodParameter.getParameterAnnotations()))
                    .filter(annotation -> annotation.annotationType().isAssignableFrom(RequestParam.class))
                    .map(annotation -> ((RequestParam) annotation).name())
                    .collect(Collectors.toList());
    
            for (String clientRequestParameterKey : clientRequestParameters.keySet()) {
                if (!definedMethodsParameters.contains(clientRequestParameterKey)) {
                    throw new IllegalArgumentException("The parameter " + clientRequestParameterKey + " passed by the client is unknown");
                }
            }
            return true;
        }
    }
    

    Note that an interceptor will be called at each request. So I would not use that in production due to the high cost of object introspection..