eln
eln

Reputation: 93

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.

Upvotes: 2

Views: 4053

Answers (2)

T.Okrajni
T.Okrajni

Reputation: 91

@GetMapping(path = "/users/search")
public @ResponseBody
ResponseEntity<List<User>> getUserLike(
        @RequestParam Map<String, String> allParams,
        @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
) {
    // here check if allParams contains only valid keys
    return userService.getUserLike(id, name, dateOfBirth);
}

Upvotes: 3

Micka&#235;l B.
Micka&#235;l B.

Reputation: 345

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..

Upvotes: 2

Related Questions