Reputation: 22646
I've written a Jetty Filter to detect and drop requests from users that are spamming the endpoint with a flood of requests, effectively DOSing other users. What I'd really like to do once I've detected that it is a bad actor, is drop the request immediately with as little processing as possible. The best thing I have come up with so far is this:
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (spamRequest()) {
response.reset();
response.setStatus(HttpStatus.TOO_MANY_REQUESTS_429);
response.flushBuffer();
}
I believe that should respond with a 429 Too Many Requests
and no body. But this is a flood of requests, and I really just want to short-circuit any processing at all and drop the connection. Throwing exceptions just causes Jetty to return a 500 with some default html response, which is no better than my current solution.
Upvotes: 1
Views: 898
Reputation: 49462
If using Jetty, you can use a special non-standard call ...
response.sendError(-1);
This is essentially javax.servlet.http.HttpServletResponse.sendError(int)
with a special "error status code" of -1
.
Important: The above is not compliant to the Servlet Spec and will not work outside of Jetty.
That will abort the Http Channel and close the connection without sending a response.
Be aware, that you might see IOException's on your server logs due to the unwinding of the Servlet layers.
If you have a RequestLog
these responses might look strange, so don't forget to at least do response.setStatus(HttpStatus.TOO_MANY_REQUESTS_429)
before you call sendError(-1)
to get something meaningful to key off of in the generated request log.
Alternatively, if you don't like this behavior, don't forget to indicate a Connection: close
before you send a valid response to force the server to close the connection after the response.
eg:
if (spamRequest()) {
response.reset();
response.setHeader("Connection", "close");
response.setStatus(HttpStatus.TOO_MANY_REQUESTS_429);
response.flushBuffer();
}
Upvotes: 2