Handle tomcat request parsing failure in Spring-Boot

568 Views Asked by At

I have a Spring-Boot-Web JSON-API that has a custom error handling with specific error responses. However, if I call my server with a bad URL then neither Spring's ErrorController, nor Spring's @ExceptionHandler will be called.

Example Call:

curl 'https://example.com/fail|no'

Response

<!doctype html><html lang="en"><head><title>HTTP Status 400 – Bad Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400 – Bad Request</h1></body></html>

Log Output:

2022-09-20 17:38:29.410 INFO 1 --- [nio-443-exec-1] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header 
Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level. 
java.lang.IllegalArgumentException: Invalid character found in the request target [/fail|no ]. The valid characters are defined in RFC 7230 and RFC 3986
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:502) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:271) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1787) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.64.jar!/:na]
    at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]

I would like to change the error handling to use the same pipeline as the rest of my error handling (ErrorController or ExceptionHandler). Thus changing the (error) logging and the response. If that isn't possible, I would like to at least return a hardcoded JSON response.

{
    "errorCode": "http.request_parse_error",
    "errorId": "abc-def-ghi"
    ...
}
  • Spring-Boot-Web 2.6
  • No Thymeleaf or any other templating engine.
1

There are 1 best solutions below

1
queeg On

The problem is that the client is not sending a correct HTTP request. And you want to respond with a proper HTTP response. This will not work.

Just imagine someone configures a JDBC driver to connecto to your Tomcat's http or https port. Of course this will fail, but do not expect the client to understand any HTTP response. The best the server can do in that case is hang up.