Search code examples
javatomcattomcat8tomcat8.5

Tomcat 8 is not able to handle get request with '|' in query parameters?


I am using Tomcat 8. In one case I need to handle external request coming from external source where the request has a parameters where it is separated by |.

Request is looks like this:

http://localhost:8080/app/handleResponse?msg=name|id|

In this case I am getting 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:467)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:667)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

EDIT 1

It works with Apache Tomcat 8.0.30 but not with Tomcat 8.5


Solution

  • This behavior is introduced in all major Tomcat releases:

    • Tomcat 7.0.73, 8.0.39, 8.5.7

    To fix, do one of the following:

    • set relaxedQueryChars to allow this character (recommended, see Lincoln's answer)
    • set requestTargetAllow option (deprecated in Tomcat 8.5) (see Jérémie's answer).
    • you can downgrade to one of older versions (not recommended - security)

    Based on changelog, those changes could affect this behavior:

    Tomcat 8.5.3:

    Ensure that requests with HTTP method names that are not tokens (as required by RFC 7231) are rejected with a 400 response

    Tomcat 8.5.7:

    Add additional checks for valid characters to the HTTP request line parsing so invalid request lines are rejected sooner.


    The best option (following the standard) - you want to encode your URL on client:

    encodeURI("http://localhost:8080/app/handleResponse?msg=name|id|")
    > http://localhost:8080/app/handleResponse?msg=name%7Cid%7C
    

    or just query string:

    encodeURIComponent("msg=name|id|")
    > msg%3Dname%7Cid%7C
    

    It will secure you from other problematic characters (list of invalid URI characters).