How to check spring RestController for unknown query parameters?

I have a basic rest controller that accepts parameters.

How can I refuse a connection if the query string contains parameters that I did not define?

@RestController @RequestMapping("/") public class MyRest { @RequestMapping(value = "/{id}", method = RequestMethod.GET) @ResponseBody public String content(@PathVariable id, @RequestParam(value = "page", required = false) int page) { return id; } } 

localhost:8080/myapp/123?pagggge=1

Currently, when this URL is called, the method runs only with an identifier, and the unknown paggge parameter paggge simply ignored. Which is generally normal, but how can I check them if the HTTP status code returns?

0
source share
3 answers

Add the HttpServletRequest request to the method parameters, do

 String query = request.getQueryString() 

in the body of the method and confirm it.

+1
source

You can get all incoming and processed parameters the way you want. Quoting spring documentation:

When the @RequestParam annotation is used in a Map <String, String> or MultiValueMap <String, String> argument, the map is populated with all the request parameters.

+5
source

In your controller method, you can include an argument of type @RequestParam Map<String, String> to access all the request parameters passed to. The generic ArgsChecker class can be used to check if the user passed in an invalid argument. If so, you can throw an exception that can be handled by the @ControllerAdvice class.

 @RestController @ExposesResourceFor(Widget.class) @RequestMapping("/widgets") public class WidgetController { @Autowired ArgsChecker<Widget> widgetArgsChecker; @RequestMapping(value = "", method = RequestMethod.GET, produces = {"application/hal+json"}) public HttpEntity<PagedResources<WidgetResource>> findAll(@RequestParam @ApiIgnore Map<String, String> allRequestParams, Pageable pageable, PagedResourcesAssembler pageAssembler) { Set<String> invalidArgs = widgetArgsChecker.getInvalidArgs(allRequestParams.keySet()); if (invalidArgs.size() > 0) { throw new QueryParameterNotSupportedException("The user supplied query parameter(s) that are not supported: " + invalidArgs + " . See below for a list of query paramters that are supported by the widget endpoint.", invalidArgs, widgetArgsChecker.getValidArgs()); } 

ArgsChecker can be defined as follows:

 import com.widgetstore.api.annotation.Queryable; import lombok.Getter; import org.apache.commons.lang3.reflect.FieldUtils; import java.lang.reflect.Field; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; public class ArgsChecker<T> { @Getter private Set<String> validArgs; private ArgsChecker(){}; public ArgsChecker(Class<T> someEntityClass){ validArgs= FieldUtils.getFieldsListWithAnnotation(someEntityClass,Queryable.class) .stream() .map(Field::getName) .collect(Collectors.toSet()); validArgs.add("page"); validArgs.add("size"); } public Set<String> getInvalidArgs(final Set<String> args){ Set<String> invalidArgs=new HashSet<>(args); invalidArgs.removeAll(validArgs); return invalidArgs; } } 

which uses reflection to search for fields that are annotated with @Queryable annotation:

 package com.widgetstore.api.annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface Queryable { } 

Now mark the fields of your domain class that you want to request using this annotation:

 @Getter @Setter public class Widget { @Queryable private String productGuid; @Queryable private String serialNumber; private String manufacturer; 

Now make sure that the ArgsChecker bean is created when the application starts:

 @SpringBootApplication public class StartWidgetApi{ public static void main(String[] args){ SpringApplication.run(StartWidgetApi.class); } @Bean(name="widgetArgsChecker") public ArgsChecker<Widget> widgetArgsChecker(){ return new ArgsChecker<Widget>(Widget.class); } //Other ArgsCheckers of different types may be used by other controllers. @Bean(name="fooArgsChecker") public ArgsChecker<Foo> fooArgsChecker(){ return new ArgsChecker<Foo>(Foo.class); } } 

Finally,

Define the @ControllerAdvice class that will listen for exceptions thrown by your application:

 package com.widgetstore.api.exception; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @ControllerAdvice @RequestMapping(produces = "application/json") @ResponseBody public class RestControllerAdvice { @ExceptionHandler(QueryParameterNotSupportedException.class) public ResponseEntity<Map<String,Object>> unrecogonizedParameter(final QueryParameterNotSupportedException e){ Map<String,Object> errorInfo = new LinkedHashMap<>(); errorInfo.put("timestamp",new Date()); errorInfo.put("errorMessage",e.getMessage()); errorInfo.put("allowableParameters",e.getValidArgs()); return new ResponseEntity<Map<String, Object>>(errorInfo,HttpStatus.BAD_REQUEST); } } 

and define a QueryParameterNotSupportedException:

 import lombok.Getter; import java.util.Set; @Getter public class QueryParameterNotSupportedException extends RuntimeException{ private Set<String> invalidArgs; private Set<String> validArgs; public QueryParameterNotSupportedException(String msg, Set<String> invalidArgs, Set<String> validArgs){ super(msg); this.invalidArgs=invalidArgs; this.validArgs=validArgs; } } 

Now, when does the user hit / widgets? someUnknownField = abc & someOtherField = xyz, it will get a json response along the lines

  {"timestamp": 2017-01-10'T'blahblah, "errorMessage": "The user supplied query parameter(s) that are not supported: ["someUnknownField","someOtherField"]. See below for a list of allowed query parameters." , "allowableParameters": ["productGuid","serialNumber"] } 
+1
source

All Articles