Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid to have unexpected exception on status code 429 TooManyRequests #433

Merged
merged 7 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/main/java/org/stellar/sdk/requests/ResponseHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.stellar.sdk.requests;

import com.google.common.base.Optional;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like an un-used import now, does your IDE highlight/warn? if using Intellij, can do 'optimize imports', will re-order and remove unused.

import com.google.gson.reflect.TypeToken;

import org.stellar.sdk.responses.GsonSingleton;
Expand Down Expand Up @@ -28,7 +29,14 @@ public T handleResponse(final Response response) throws IOException, TooManyRequ
try {
// Too Many Requests
if (response.code() == 429) {
int retryAfter = Integer.parseInt(response.header("Retry-After"));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for consideration, could removeheader variable usage

Integer retryAfter = null;
try {
  retryAfter = Integer.parseInt(response.header("Retry-After"));
} catch (Exception ignored) {}
        

Integer retryAfter = null;
String header = response.header("Retry-After");
if (header != null) {
try {
retryAfter = Integer.parseInt(header);
} catch (NumberFormatException ignored) {}
}
throw new TooManyRequestsException(retryAfter);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package org.stellar.sdk.requests;


import com.google.common.base.Optional;

/**
* Exception thrown when too many requests were sent to the Horizon server.
* @see <a href="https://developers.stellar.org/api/introduction/rate-limiting/" target="_blank">Rate Limiting</a>
*/
public class TooManyRequestsException extends RuntimeException {
private int retryAfter;
private Integer retryAfter;

public TooManyRequestsException(int retryAfter) {
public TooManyRequestsException(Integer retryAfter) {
super("The rate limit for the requesting IP address is over its alloted limit.");
this.retryAfter = retryAfter;
}

/**
* Returns number of seconds a client should wait before sending requests again.
* Returns number of seconds a client should wait before sending requests again,
* or -1 this time is unknown.
*/
public int getRetryAfter() {
return retryAfter;
public Optional<Integer> getRetryAfter() {
return Optional.fromNullable(retryAfter);
}
}
66 changes: 66 additions & 0 deletions src/test/java/org/stellar/sdk/requests/ResponseHandlerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.stellar.sdk.requests;

import static org.junit.Assert.assertEquals;

import java.io.IOException;

import com.google.common.base.Optional;
import org.junit.Assert;
import org.junit.Test;

import okhttp3.OkHttpClient;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;

public class ResponseHandlerTest {

@Test
public void testTooManyRequests() throws IOException, InterruptedException {

MockResponse response = new MockResponse();
response.setResponseCode(429);
response.setHeader("Retry-After", "10");

MockWebServer mockWebServer = new MockWebServer();
mockWebServer.start();
mockWebServer.enqueue(response);

OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
try {

AccountsRequestBuilder.execute(okHttpClient, mockWebServer.url("/"));
Assert.fail();
} catch (TooManyRequestsException tmre) {
assertEquals(Optional.of(10), tmre.getRetryAfter());
} finally {

mockWebServer.shutdown();
mockWebServer.close();
}
}

@Test
public void testTooManyRequestsNoHeader() throws IOException, InterruptedException {

MockResponse response = new MockResponse();
response.setResponseCode(429);

MockWebServer mockWebServer = new MockWebServer();

mockWebServer.start();
mockWebServer.enqueue(response);

OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();

try {
AccountsRequestBuilder.execute(okHttpClient, mockWebServer.url("/"));
Assert.fail();
} catch (TooManyRequestsException tmre) {
assertEquals(Optional.absent(), tmre.getRetryAfter());
} finally {

mockWebServer.shutdown();
mockWebServer.close();
}
}
}