package org.geoserver.flow.controller; import static org.junit.Assert.*; import javax.servlet.http.Cookie; import org.geoserver.ows.HttpErrorCodeException; import org.geoserver.ows.Request; import org.junit.Test; import org.springframework.mock.web.MockHttpServletResponse; public class RateFlowControllerTest extends AbstractFlowControllerTest { @Test public void testCookieRateControl() { RateFlowController controller = new RateFlowController(new OWSRequestMatcher(), 2, Long.MAX_VALUE, 1000, new CookieKeyGenerator()); // run the first request Request firstRequest = buildCookieRequest(null); assertTrue(controller.requestIncoming(firstRequest, Integer.MAX_VALUE)); checkHeaders(firstRequest, "Any OGC request", 2, 1); // grab the cookie Cookie cookie = (Cookie) ((MockHttpServletResponse) firstRequest.getHttpResponse()) .getCookies()[0]; String cookieValue = cookie.getValue(); // second request Request request = buildCookieRequest(cookieValue); assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); checkHeaders(request, "Any OGC request", 2, 0); // third one, this one will have to wait long start = System.currentTimeMillis(); assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); long end = System.currentTimeMillis(); long delay = end - start; assertTrue("Request was not delayed enough: " + delay, delay >= 1000); checkHeaders(request, "Any OGC request", 2, 0); // fourth one, this one will bail out immediately because we give it not enough wait assertFalse(controller.requestIncoming(request, 500)); checkHeaders(request, "Any OGC request", 2, 0); } private void checkHeaders(Request request, String context, int limit, int remaining) { MockHttpServletResponse response = (MockHttpServletResponse) request.getHttpResponse(); assertEquals(context, response.getHeader(RateFlowController.X_RATE_LIMIT_CONTEXT)); assertEquals(String.valueOf(limit), response.getHeader(RateFlowController.X_RATE_LIMIT_LIMIT)); assertEquals(String.valueOf(remaining), response.getHeader(RateFlowController.X_RATE_LIMIT_REMAINING)); } @Test public void testCookie429() { RateFlowController controller = new RateFlowController(new OWSRequestMatcher(), 2, Long.MAX_VALUE, 0, new CookieKeyGenerator()); // run the first request Request firstRequest = buildCookieRequest(null); assertTrue(controller.requestIncoming(firstRequest, Integer.MAX_VALUE)); // grab the cookie Cookie cookie = (Cookie) ((MockHttpServletResponse) firstRequest.getHttpResponse()) .getCookies()[0]; String cookieValue = cookie.getValue(); // second request Request request = buildCookieRequest(cookieValue); assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); // this one should fail with a 429 try { assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); } catch (HttpErrorCodeException e) { assertEquals(429, e.getErrorCode()); } } @Test public void testIpRateControl() { RateFlowController controller = new RateFlowController(new OWSRequestMatcher(), 2, Long.MAX_VALUE, 1000, new IpKeyGenerator()); // run two requests Request request = buildIpRequest("127.0.0.1", ""); assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); // third one, this one will have to wait long start = System.currentTimeMillis(); assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); long end = System.currentTimeMillis(); long delay = end - start; assertTrue("Request was not delayed enough: " + delay, delay >= 1000); // fourth one, this one will bail out immediately because we give it not enough wait assertFalse(controller.requestIncoming(request, 500)); } @Test public void testIp429() { RateFlowController controller = new RateFlowController(new OWSRequestMatcher(), 2, Long.MAX_VALUE, 0, new IpKeyGenerator()); // run two requests Request request = buildIpRequest("127.0.0.1", ""); assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); // this one should fail with a 429 try { assertTrue(controller.requestIncoming(request, Integer.MAX_VALUE)); } catch (HttpErrorCodeException e) { assertEquals(429, e.getErrorCode()); } } }