I am adding rate-limiting to a restful webservice using Spring MVC 4.1.
I created a @RateLimited
annotation that I can apply to controller methods. A S
See if it's feasible for you to implement similar logic for @@AfterThrowing advice as well which will have similar pointcut.
I eventually gave up on trying to find an AOP solution and created a Spring Interceptor instead. The interceptor preHandle
s all requests and watches for requests whose handler is @RateLimited
.
@Component
public class RateLimitingInterceptor extends HandlerInterceptorAdapter {
@Autowired
private final RateLimitService rateLimitService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (HandlerMethod.class.isAssignableFrom(handler.getClass())) {
rateLimit(request, (HandlerMethod)handler);
}
return super.preHandle(request, response, handler);
}
private void rateLimit(HttpServletRequest request, HandlerMethod handlerMethod) throws TooManyRequestsException {
if (handlerMethod.getMethodAnnotation(RateLimited.class) != null) {
String ip = request.getRemoteAddr();
int secondsToWait = rateLimitService.secondsUntilNextAllowedInvocation(ip);
if (secondsToWait > 0) {
throw new TooManyRequestsException(secondsToWait);
} else {
rateLimitService.recordInvocation(ip);
}
}
}
}