Skip to content

Commit 8f61fa5

Browse files
committed
modified Rate Limit Exception
1 parent 1377e5a commit 8f61fa5

File tree

5 files changed

+121
-66
lines changed

5 files changed

+121
-66
lines changed

src/main/java/com/auth0/exception/RateLimitException.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.auth0.exception;
22

3+
import com.auth0.net.TokenQuotaBucket;
4+
35
import java.util.Map;
46

57
/**
@@ -15,21 +17,27 @@ public class RateLimitException extends APIException {
1517
private final long limit;
1618
private final long remaining;
1719
private final long reset;
20+
private final TokenQuotaBucket clientQuotaLimit;
21+
private final TokenQuotaBucket organizationQuotaLimit;
1822

1923
private static final int STATUS_CODE_TOO_MANY_REQUEST = 429;
2024

21-
public RateLimitException(long limit, long remaining, long reset, Map<String, Object> values) {
25+
public RateLimitException(long limit, long remaining, long reset, TokenQuotaBucket clientQuotaLimit, TokenQuotaBucket organizationQuotaLimit, Map<String, Object> values) {
2226
super(values, STATUS_CODE_TOO_MANY_REQUEST);
2327
this.limit = limit;
2428
this.remaining = remaining;
2529
this.reset = reset;
30+
this.clientQuotaLimit = clientQuotaLimit;
31+
this.organizationQuotaLimit = organizationQuotaLimit;
2632
}
2733

28-
public RateLimitException(long limit, long remaining, long reset) {
34+
public RateLimitException(long limit, long remaining, long reset, TokenQuotaBucket clientQuotaLimit, TokenQuotaBucket organizationQuotaLimit) {
2935
super("Rate limit reached", STATUS_CODE_TOO_MANY_REQUEST, null);
3036
this.limit = limit;
3137
this.remaining = remaining;
3238
this.reset = reset;
39+
this.clientQuotaLimit = clientQuotaLimit;
40+
this.organizationQuotaLimit = organizationQuotaLimit;
3341
}
3442

3543
/**
@@ -56,4 +64,20 @@ public long getReset() {
5664
return reset;
5765
}
5866

67+
/**
68+
* Getter for the client quota limit.
69+
* @return The client quota limit or null if missing.
70+
*/
71+
public TokenQuotaBucket getClientQuotaLimit() {
72+
return clientQuotaLimit;
73+
}
74+
75+
/**
76+
* Getter for the organization quota limit.
77+
* @return The organization quota limit or null if missing.
78+
*/
79+
public TokenQuotaBucket getOrganizationQuotaLimit() {
80+
return organizationQuotaLimit;
81+
}
82+
5983
}

src/main/java/com/auth0/net/BaseRequest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.auth0.exception.RateLimitException;
77
import com.auth0.json.ObjectMapperProvider;
88
import com.auth0.net.client.*;
9+
import com.auth0.utils.HttpResponseHeadersUtils;
910
import com.fasterxml.jackson.core.type.TypeReference;
1011
import com.fasterxml.jackson.databind.ObjectMapper;
1112
import com.fasterxml.jackson.databind.type.MapType;
@@ -219,13 +220,21 @@ private RateLimitException createRateLimitException(Auth0HttpResponse response)
219220
long remaining = Long.parseLong(response.getHeader("x-ratelimit-remaining", "-1"));
220221
long reset = Long.parseLong(response.getHeader("x-ratelimit-reset", "-1"));
221222

223+
TokenQuotaBucket clientQuotaLimit = null;
224+
TokenQuotaBucket organizationQuotaLimit = null;
225+
226+
if (response.getHeaders().containsKey("x-rate-limit-remaining") && response.getHeaders().get("x-rate-limit-remaining").equals("0")) {
227+
clientQuotaLimit = HttpResponseHeadersUtils.getClientQuotaLimit(response.getHeaders());
228+
organizationQuotaLimit = HttpResponseHeadersUtils.getOrganizationQuotaLimit(response.getHeaders());
229+
}
230+
222231
String payload = response.getBody();
223232
MapType mapType = mapper.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class);
224233
try {
225234
Map<String, Object> values = mapper.readValue(payload, mapType);
226-
return new RateLimitException(limit, remaining, reset, values);
235+
return new RateLimitException(limit, remaining, reset, clientQuotaLimit, organizationQuotaLimit, values);
227236
} catch (IOException e) {
228-
return new RateLimitException(limit, remaining, reset);
237+
return new RateLimitException(limit, remaining, reset, clientQuotaLimit, organizationQuotaLimit);
229238
}
230239
}
231240

src/main/java/com/auth0/net/Response.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,4 @@ public interface Response<T> {
2323
* @return the HTTP status code.
2424
*/
2525
int getStatusCode();
26-
27-
TokenQuotaBucket getClientQuotaLimit();
28-
29-
TokenQuotaBucket getOrganizationQuotaLimit();
3026
}

src/main/java/com/auth0/net/ResponseImpl.java

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -31,62 +31,4 @@ public T getBody() {
3131
public int getStatusCode() {
3232
return statusCode;
3333
}
34-
35-
@Override
36-
public TokenQuotaBucket getClientQuotaLimit() {
37-
String quotaHeader = headers.get("X-Quota-Client-Limit");
38-
if (quotaHeader != null) {
39-
return parseQuota(quotaHeader);
40-
}
41-
return null;
42-
}
43-
44-
@Override
45-
public TokenQuotaBucket getOrganizationQuotaLimit() {
46-
String quotaHeader = headers.get("X-Quota-Organization-Limit");
47-
if (quotaHeader != null) {
48-
return parseQuota(quotaHeader);
49-
}
50-
return null;
51-
}
52-
53-
public static TokenQuotaBucket parseQuota(String tokenQuota) {
54-
55-
TokenQuotaLimit perHour = null;
56-
TokenQuotaLimit perDay = null;
57-
58-
String[] parts = tokenQuota.split(",");
59-
for (String part : parts) {
60-
String[] attributes = part.split(";");
61-
int quota = 0, remaining = 0, time = 0;
62-
63-
for (String attribute : attributes) {
64-
String[] keyValue = attribute.split("=");
65-
if (keyValue.length != 2) continue;
66-
67-
String key = keyValue[0].trim();
68-
String value = keyValue[1].trim();
69-
70-
switch (key) {
71-
case "q":
72-
quota = Integer.parseInt(value);
73-
break;
74-
case "r":
75-
remaining = Integer.parseInt(value);
76-
break;
77-
case "t":
78-
time = Integer.parseInt(value);
79-
break;
80-
}
81-
}
82-
83-
if (attributes[0].contains("per_hour")) {
84-
perHour = new TokenQuotaLimit(quota, remaining, time);
85-
} else if (attributes[0].contains("per_day")) {
86-
perDay = new TokenQuotaLimit(quota, remaining, time);
87-
}
88-
}
89-
90-
return new TokenQuotaBucket(perHour, perDay);
91-
}
9234
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.auth0.utils;
2+
3+
import com.auth0.json.auth.TokenQuotaLimit;
4+
import com.auth0.net.TokenQuotaBucket;
5+
6+
import java.util.Map;
7+
8+
public class HttpResponseHeadersUtils {
9+
10+
/**
11+
* Gets the client token quota limits from the provided headers.
12+
*
13+
* @param headers the HTTP response headers.
14+
* @return a TokenQuotaBucket containing client rate limits, or null if not present.
15+
*/
16+
public static TokenQuotaBucket getClientQuotaLimit(Map<String, String> headers) {
17+
String quotaHeader = headers.get("X-Quota-Client-Limit");
18+
if( quotaHeader == null) {
19+
quotaHeader = headers.get("x-quota-client-limit");
20+
}
21+
if (quotaHeader != null) {
22+
return parseQuota(quotaHeader);
23+
}
24+
return null;
25+
}
26+
27+
/**
28+
* Gets the organization token quota limits from the provided headers.
29+
*
30+
* @param headers the HTTP response headers.
31+
* @return a TokenQuotaBucket containing organization rate limits, or null if not present.
32+
*/
33+
public static TokenQuotaBucket getOrganizationQuotaLimit(Map<String, String> headers) {
34+
String quotaHeader = headers.get("X-Quota-Organization-Limit");
35+
if( quotaHeader == null) {
36+
quotaHeader = headers.get("x-quota-organization-limit");
37+
}
38+
if (quotaHeader != null) {
39+
return parseQuota(quotaHeader);
40+
}
41+
return null;
42+
}
43+
44+
public static TokenQuotaBucket parseQuota(String tokenQuota) {
45+
46+
TokenQuotaLimit perHour = null;
47+
TokenQuotaLimit perDay = null;
48+
49+
String[] parts = tokenQuota.split(",");
50+
for (String part : parts) {
51+
String[] attributes = part.split(";");
52+
int quota = 0, remaining = 0, time = 0;
53+
54+
for (String attribute : attributes) {
55+
String[] keyValue = attribute.split("=");
56+
if (keyValue.length != 2) continue;
57+
58+
String key = keyValue[0].trim();
59+
String value = keyValue[1].trim();
60+
61+
switch (key) {
62+
case "q":
63+
quota = Integer.parseInt(value);
64+
break;
65+
case "r":
66+
remaining = Integer.parseInt(value);
67+
break;
68+
case "t":
69+
time = Integer.parseInt(value);
70+
break;
71+
}
72+
}
73+
74+
if (attributes[0].contains("per_hour")) {
75+
perHour = new TokenQuotaLimit(quota, remaining, time);
76+
} else if (attributes[0].contains("per_day")) {
77+
perDay = new TokenQuotaLimit(quota, remaining, time);
78+
}
79+
}
80+
81+
return new TokenQuotaBucket(perHour, perDay);
82+
}
83+
84+
}

0 commit comments

Comments
 (0)