Allow to retrieve Rate Limit headers#153
Conversation
lbalmaceda
left a comment
There was a problem hiding this comment.
@rvillablanca Thanks for your PR! I've left a few comments. 🎉
| } | ||
|
|
||
| protected Auth0Exception createResponseException(Response response) { | ||
| if (response.code() == 429) { |
There was a problem hiding this comment.
Move the 429 to a private constant like STATUS_CODE_TOO_MANY_REQUEST
| long limit = parseRateLimitHeader("X-RateLimit-Limit", response); | ||
| long remaining = parseRateLimitHeader("X-RateLimit-Remaining", response); | ||
| long reset = parseRateLimitHeader("X-RateLimit-Reset", response); | ||
| return new RateLimitException(limit, remaining, reset, "Rate limits reached"); |
There was a problem hiding this comment.
I'd make the parseRateLimitHeader method parse all the headers at the same time and then throw the exception. Maybe something like this:
if (code == 429){
throw buildRateLimitException(response);
}Also, seems like a rate limit exception would always have the same message/description. Let's remove that argument from the constructor and just keep the numbers.
I'm not so sure about this, but I think the message should be "Rate limit reached". (no "limits")
There was a problem hiding this comment.
In this case I didn't want to couple the exception and the response so I modified the method to parse the headers and create the exception
There was a problem hiding this comment.
I didn't want to couple the exception and the response
That was a good call 👍
| private final long reset; | ||
|
|
||
| public RateLimitException(long limit, long remaining, long reset, String message) { | ||
| super(message, 429, null); |
There was a problem hiding this comment.
Message can be "hardcoded" here. No need for an arg.
| import java.io.IOException; | ||
| import java.nio.file.Files; | ||
| import java.nio.file.Paths; | ||
| import java.util.Date; |
| server.enqueue(response); | ||
| } | ||
|
|
||
| public void rateLimitResponse() throws IOException { |
There was a problem hiding this comment.
I'd call this rateLimitReachedResponse and pass the 3 values on the args. This way, you can test how defaults are being assigned if the header is missing (not just for 1 header)
| exception = e; | ||
| } | ||
| assertThat(exception, is(notNullValue())); | ||
| assertThat(exception, is(instanceOf(APIException.class))); |
There was a problem hiding this comment.
No need to test for APIException since RateLimitException is already a subclass.
|
|
||
| /** | ||
| * Represents a server error when a rate limit has been exceeded. | ||
| */ |
There was a problem hiding this comment.
Please add a line linking to the docs. Such as
"To learn more about rate limits, visit https://auth0.com/docs/policies/rate-limits"
| this.reset = reset; | ||
| } | ||
|
|
||
| public long getLimit() { |
There was a problem hiding this comment.
Javadoc for this 3 getters. You can use the docs to take some input. The idea is to explain in no more than a line what each of this numbers represent and most important, what value would be returned when the header is missing.
lbalmaceda
left a comment
There was a problem hiding this comment.
A few small comments. Please add 1 more test that asserts that when headers are not set, the returned value is -1
|
|
||
| /** | ||
| * Getter for the maximum number of requests available in the current time frame. | ||
| * @return The maximun number of requests. |
There was a problem hiding this comment.
typo: should be "maximum"
Please change to "The maximum number of requests or -1 if missing."
| * 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. | ||
| * <p> | ||
| * "To learn more about rate limits, visit <a href="https://auth0.com/docs/policies/rate-limits">https://auth0.com/docs/policies/rate-limits</a> |
There was a problem hiding this comment.
Remove the " at the beginning
|
|
||
| /** | ||
| * Getter for the number of remaining requests in the current time frame. | ||
| * @return Number of remaining requests. |
There was a problem hiding this comment.
Please change to "The number of remaining requests or -1 if missing."
|
|
||
| /** | ||
| * Getter for the UNIX timestamp of the expected time when the rate limit will reset. | ||
| * @return The UNIX timestamp. |
There was a problem hiding this comment.
Please change to "The UNIX timestamp or -1 if missing."
| public void rateLimitReachedResponse(long limit, long remaining, long reset) throws IOException { | ||
| MockResponse response = new MockResponse() | ||
| .setResponseCode(429) | ||
| .addHeader("X-RateLimit-Limit", String.valueOf(limit)) |
There was a problem hiding this comment.
You might want to add a check whether the arg is "-1" to avoid setting the header, so you can test that.
There was a problem hiding this comment.
All suggestions have been done!
This PR resolve #99 to allow get the rate limit values from
X-RateLimit-*headers.I have made some decisions for default values, for example, when an http response code with value
429is received then the information about rate limits should be recovered from headersX-RateLimit-*, but I don't know if these values are always sent so, if I couldn't get some header then a default-1will be assigned.The primitive data type chosen was
longsince theX-RateLimit-Resetis a Unix timestamp and the others values are normal numbers.