diff --git a/src/main/java/com/auth0/exception/RateLimitException.java b/src/main/java/com/auth0/exception/RateLimitException.java new file mode 100644 index 00000000..c5e79e81 --- /dev/null +++ b/src/main/java/com/auth0/exception/RateLimitException.java @@ -0,0 +1,50 @@ +package com.auth0.exception; + +/** + * Represents a server error when a rate limit has been exceeded. + *
+ * Getters for {@code limit, remaining} and {@code reset} corresponds to {@code X-RateLimit-Limit, X-RateLimit-Remaining} and {@code X-RateLimit-Reset} HTTP headers. + * If the value of any headers is missing, then a default value -1 will assigned. + *
+ * To learn more about rate limits, visit https://auth0.com/docs/policies/rate-limits
+ */
+public class RateLimitException extends APIException {
+
+ private final long limit;
+ private final long remaining;
+ private final long reset;
+
+ private static final int STATUS_CODE_TOO_MANY_REQUEST = 429;
+
+ public RateLimitException(long limit, long remaining, long reset) {
+ super("Rate limit reached", STATUS_CODE_TOO_MANY_REQUEST, null);
+ this.limit = limit;
+ this.remaining = remaining;
+ this.reset = reset;
+ }
+
+ /**
+ * Getter for the maximum number of requests available in the current time frame.
+ * @return The maximum number of requests or -1 if missing.
+ */
+ public long getLimit() {
+ return limit;
+ }
+
+ /**
+ * Getter for the number of remaining requests in the current time frame.
+ * @return Number of remaining requests or -1 if missing.
+ */
+ public long getRemaining() {
+ return remaining;
+ }
+
+ /**
+ * Getter for the UNIX timestamp of the expected time when the rate limit will reset.
+ * @return The UNIX timestamp or -1 if missing.
+ */
+ public long getReset() {
+ return reset;
+ }
+
+}
diff --git a/src/main/java/com/auth0/net/CustomRequest.java b/src/main/java/com/auth0/net/CustomRequest.java
index 431e80f9..b67e84f0 100644
--- a/src/main/java/com/auth0/net/CustomRequest.java
+++ b/src/main/java/com/auth0/net/CustomRequest.java
@@ -2,6 +2,7 @@
import com.auth0.exception.APIException;
import com.auth0.exception.Auth0Exception;
+import com.auth0.exception.RateLimitException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -15,6 +16,7 @@
@SuppressWarnings("WeakerAccess")
public class CustomRequest request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType);
+ server.rateLimitReachedResponse(100, 10, 5);
+ Exception exception = null;
+ try {
+ request.execute();
+ server.takeRequest();
+ } catch (Exception e) {
+ exception = e;
+ }
+ assertThat(exception, is(notNullValue()));
+ assertThat(exception, is(instanceOf(RateLimitException.class)));
+ assertThat(exception.getCause(), is(nullValue()));
+ assertThat(exception.getMessage(), is("Request failed with status code 429: Rate limit reached"));
+ RateLimitException rateLimitException = (RateLimitException) exception;
+ assertThat(rateLimitException.getDescription(), is("Rate limit reached"));
+ assertThat(rateLimitException.getError(), is(nullValue()));
+ assertThat(rateLimitException.getValue("non_existing_key"), is(nullValue()));
+ assertThat(rateLimitException.getStatusCode(), is(429));
+ assertThat(rateLimitException.getLimit(), is(100L));
+ assertThat(rateLimitException.getRemaining(), is(10L));
+ assertThat(rateLimitException.getReset(), is(5L));
+ }
+
+ @Test
+ public void shouldDefaultRateLimitsHeadersWhenMissing() throws Exception {
+ CustomRequest
request = new CustomRequest<>(client, server.getBaseUrl(), "GET", listType);
+ server.rateLimitReachedResponse(-1, -1, -1);
+ Exception exception = null;
+ try {
+ request.execute();
+ server.takeRequest();
+ } catch (Exception e) {
+ exception = e;
+ }
+ assertThat(exception, is(notNullValue()));
+ assertThat(exception, is(instanceOf(RateLimitException.class)));
+ assertThat(exception.getCause(), is(nullValue()));
+ assertThat(exception.getMessage(), is("Request failed with status code 429: Rate limit reached"));
+ RateLimitException rateLimitException = (RateLimitException) exception;
+ assertThat(rateLimitException.getDescription(), is("Rate limit reached"));
+ assertThat(rateLimitException.getError(), is(nullValue()));
+ assertThat(rateLimitException.getValue("non_existing_key"), is(nullValue()));
+ assertThat(rateLimitException.getStatusCode(), is(429));
+ assertThat(rateLimitException.getLimit(), is(-1L));
+ assertThat(rateLimitException.getRemaining(), is(-1L));
+ assertThat(rateLimitException.getReset(), is(-1L));
+ }
-}
\ No newline at end of file
+}