1

I am using a 3rd party grid, which generates the following GET API when a character is input :

http://localhost:4200/api/v1/driver/getDriverListForDropDown?firstName=[{%22field%22:%22DriverCode%22,%22operator%22:%22startsWith%22,%22value%22:%2212345%22,%22caseSensitive%22:false}]

Request param generated :

firstName:[{"field":"DriverCode","operator":"startsWith","value":"*","caseSensitive":false}]

I am trying to create a rest API on spring boot, but not able to hit the API.

I tried the following :

    @GetMapping(path = "/getDriverListForDropDown")
    public ResponseEntity<RestApiResponse<List<DriverDataForDropDown>>> getDriverListForDropDown(
        @ApiIgnore Context context, @RequestParam(value="firstName") List<DriverDropdownFilterRequest> firstName)

DriverDropdownFilterRequest :

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
@JsonIgnoreProperties(ignoreUnknown = true)
@Builder(toBuilder = true)
public class DriverDropdownFilterRequest
{
  String field;
  String operator;
  String value;
}

but I always get 400 error and on backend the following error :

java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986 at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:468) ~[tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:260) ~[tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) [tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1591) [tomcat-embed-core-9.0.29.jar:9.0.29] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.29.jar:9.0.29] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.29.jar:9.0.29]

I tried several options, but nothing is working. Please help.

user2332505
  • 619
  • 2
  • 10
  • 19
  • Since it is a GET method, try to get the param value as a String and parse it as a JSON. may help you – Ghost Rider Jan 21 '22 at 12:47
  • I tried that as well. It keeps on failing. The only thing that work was : http://localhost:4200/api/v1/driver/getDriverListForDropDown?firstName=%22field%22:%22DriverCode%22,%22operator%22:%22startsWith%22,%22value%22:%2212345%22,%22caseSensitive%22:false – user2332505 Jan 21 '22 at 12:50
  • Recently found that lombok is not so much complaint with hibernate and could lead to unrecognized object to map it with, but error looks more like problem with the Tomcat, so not sure if you have already checked https://stackoverflow.com/questions/41053653/tomcat-8-is-not-able-to-handle-get-request-with-in-query-parameters/44005213#44005213 – Vasil Jan 21 '22 at 12:51
  • Since I am using embedded tomcat of spring, is it possible to add this config? I saw this answer as well, but was not sure on how to add in embedded tomcat server – user2332505 Jan 21 '22 at 12:54
  • You can search (I already searched for some properties given in the answer and they are available) for them in : https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html and add them to your application.properties or even for the test you can try with externalized tomcat configuration. – Vasil Jan 21 '22 at 14:27
  • thanks... issue was even properties changes were not working for me. Added a separate config for it and it works now. – user2332505 Jan 22 '22 at 04:32

2 Answers2

0

I presume, as your exception suggests, check whether your request format is valid (maybe the char '[' and ']' in firstName params contradicts), or your tomcat version support your format, please refer to this post.

Suggestion: Maybe instead of assigning hash-like value to params, you can separate them by creating new params (not only first name), or by setting the API point capable of accepting a body of json. e.g.

@GetMapping(path = "/get")
public ResponseEntity<...> get(..., @RequestBody Map<...> firstname) 
{
    .
    .
    .
}

cheers!

Zukaru
  • 320
  • 2
  • 11
  • This get API is controlled by the UI framework, hence no support of sending a json. – user2332505 Jan 21 '22 at 13:16
  • I guess providing the client-side details would help the issue. Because this is more like of client problem, aka 400 error thing, since you might also want to encode the URL before hit the API. – Zukaru Jan 21 '22 at 13:23
0

Issue was the 3rd party was not properly encoding the parameter and tomcat was denying these characters.

Even when adding the relaxed characters in application.properties didn't worked.

the only solution that worked was to add the following config :

@Component
public class TomcatWebServerCustomizer implements 
WebServerFactoryCustomizer<TomcatServletWebServerFactory>
  {
    /**
     * Customize the specified
    * @param factory the web server factory to customize
    */
    @Override
    public void customize(TomcatServletWebServerFactory factory)
     {
       factory.addConnectorCustomizers(connector -> 
      connector.setAttribute("relaxedQueryChars", "<>[\\]^`{|}"));
     }
   }
user2332505
  • 619
  • 2
  • 10
  • 19