0

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.
ST-DDT
  • 2,615
  • 3
  • 30
  • 51
  • Did you define an ExceptionHandler? – Pao Sep 20 '22 at 16:08
  • Yes, I have both a Spring `@ExceptionHandler` (including one for Throwable) and `ErrorController` that work perfectly fine, for all exceptions that happen inside the scope of spring. Unfortunately, the parsing error happens before the request even reaches the Spring application. – ST-DDT Sep 20 '22 at 16:11
  • The error says it occured while parsing the **header**. No https issue? – Pao Sep 20 '22 at 16:16
  • The same error occurs with `http:` too. I don't really care what the error is, I just want to handle it like any other error (logging, monitoring, response). – ST-DDT Sep 20 '22 at 16:35
  • As for **header**, I assume the call url can be considered to be part of the headers as well, since it is the first line. Although technically it is called the request line and the headers start only at the second line. – ST-DDT Sep 20 '22 at 16:42
  • 1
    You've probably tried to define let your ```ExceptionHandler``` handle ```IllegalArgumentException```s? – Pao Sep 20 '22 at 16:45
  • Might this help? https://stackoverflow.com/questions/39376602/handle-embedded-tomcat-exception-in-spring-boot – Pao Sep 20 '22 at 16:47
  • It is the same error, but the situation/solution is different. I don't want to allow these suspicious requests. I just want to handle them slightly differently than native tomcat. – ST-DDT Sep 20 '22 at 16:55

1 Answers1

0

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.

Queeg
  • 7,748
  • 1
  • 16
  • 42
  • Then how do I tell my server to "hang up, (measure it for security reasons), and not to bother me with stacktraces"? It does return a proper HTTP response, so obviously tomcat treats it as an (in-)valid HTTP request. – ST-DDT Sep 21 '22 at 08:02