postfuturist
postfuturist

Reputation: 22646

How do I quickly drop a request in a Jetty filter?

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

Answers (1)

Joakim Erdfelt
Joakim Erdfelt

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

Related Questions