Reputation: 6826
I have an HTTP GET endpoint that accepts some query parameters:
@GetMapping("/cat")
public ResponseEntity<Cat> getCat(@RequestParam("catName") String catName){ ...
If the clients will send additional query parameters, the endpoint will ignore them.
GET .../cat?catName=Oscar Getting Oscar
GET .../cat?catName=Oscar&gender=male Getting Oscar
GET .../cat?catName=Oscar&x=y Getting Oscar
I want to reject HTTP requests that will send additional query parameters:
GET .../cat?catName=Oscar OK
GET .../cat?catName=Oscar&gender=male Reject (HTTP error code XYZ)
GET .../cat?catName=Oscar&x=y Reject (HTTP error code XYZ)
I can change the signature of the method to accept a map and validate the values in the map as suggested here.
Is there a way to do with while keeping the cleaner and self explained method signature?
Upvotes: 4
Views: 1896
Reputation: 90497
You can try to implement a HandlerInterceptor
and validate such rule in preHandle()
. If the request contains the query parameters that does not defined in the controller method , you just throw a specific type of Exception
and configure a @ControllerAdvice
to handle this exception. Something like :
public class FooHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod hm = (HandlerMethod) handler;
Set<String> allowQueryParams = Stream.of(hm.getMethodParameters())
.map(p -> p.getParameterAnnotation(RequestParam.class))
.map(req -> req.value())
.collect(toSet());
for (String currentRequestParamName : request.getParameterMap().keySet()) {
if (!allowQueryParams.contains(currentRequestParamName)) {
throw new FooRestException();
}
}
}
return true;
}
}
And the @ControllerAdvice
to handle the Exception :
@ControllerAdvice
public class FooExceptionHandler {
@ExceptionHandler(FooRestException.class)
public ResponseEntity<Object> handle(FooRestException ex) {
return new ResponseEntity<>("Some query parameter are not defined", HttpStatus.BAD_REQUEST);
}
}
Finally register FooHandlerInterceptor
to use it :
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new FooHandlerInterceptor());
}
}
I just show you the idea. You can further tweak the codes in HandlerInterceptor
if you want such checking is only applied to a particular controller method.
Upvotes: 1