Skip to content
This repository was archived by the owner on May 3, 2023. It is now read-only.

Commit dda724a

Browse files
fix: replace guava ratelimiter by my own rate limiter
1 parent 5cb85e3 commit dda724a

File tree

8 files changed

+221
-13
lines changed

8 files changed

+221
-13
lines changed

pom.xml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,23 @@
2121
<artifactId>httpclient</artifactId>
2222
<version>4.5.13</version>
2323
</dependency>
24-
<!-- Google Guava -->
25-
<dependency>
26-
<groupId>com.google.guava</groupId>
27-
<artifactId>guava</artifactId>
28-
<version>20.0</version>
29-
</dependency>
3024
<!-- Json -->
3125
<dependency>
3226
<groupId>org.json</groupId>
3327
<artifactId>json</artifactId>
3428
<version>20220320</version>
3529
</dependency>
30+
<dependency>
31+
<groupId>org.jetbrains</groupId>
32+
<artifactId>annotations</artifactId>
33+
<version>23.0.0</version>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.junit.jupiter</groupId>
37+
<artifactId>junit-jupiter</artifactId>
38+
<version>RELEASE</version>
39+
<scope>test</scope>
40+
</dependency>
3641
</dependencies>
3742

3843
<properties>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package net.httpclient.wrapper;
2+
3+
import net.httpclient.wrapper.events.HttpClientSessionEvent;
4+
import net.httpclient.wrapper.events.HttpClientSessionListener;
5+
import net.httpclient.wrapper.exception.HttpClientException;
6+
import net.httpclient.wrapper.exception.HttpServerException;
7+
import net.httpclient.wrapper.response.RequestResponse;
8+
import net.httpclient.wrapper.session.HttpClientSession;
9+
import net.httpclient.wrapper.utils.BasicCookieStoreSerializerUtils;
10+
import org.apache.http.impl.client.BasicCookieStore;
11+
12+
import java.io.IOException;
13+
14+
public class Test implements HttpClientSessionListener {
15+
16+
public static void main(String[] args) throws HttpClientException, IOException, HttpServerException {
17+
System.out.println("Hello World!");
18+
HttpClientSessionEvent.addHttpClientSessionListener(new Test());
19+
20+
21+
HttpClientSession httpClientSession = new HttpClientSession();
22+
RequestResponse requestResponse = httpClientSession.sendGet("https://lincos.tools/content/11-cookie");
23+
System.out.println(requestResponse.getStatusCode());
24+
System.out.println(BasicCookieStoreSerializerUtils.serializableToBase64(httpClientSession.getHttpCookieStore()));
25+
requestResponse = httpClientSession.sendGet("https://www.nautiljon.com/");
26+
System.out.println(requestResponse.getStatusCode());
27+
System.out.println(BasicCookieStoreSerializerUtils.serializableToBase64(httpClientSession.getHttpCookieStore()));
28+
System.out.println("Finished !\n");
29+
30+
// print all cookies
31+
for (org.apache.http.cookie.Cookie cookie : httpClientSession.getHttpCookieStore().getCookies()) {
32+
System.out.println(cookie.getDomain() + " : " + cookie.getPath());
33+
System.out.println("\t => " + cookie.getName() + " : " + cookie.getValue());
34+
}
35+
36+
}
37+
38+
@Override
39+
public void onHttpClientCookiesUpdated(HttpClientSession httpClientSession) {
40+
System.out.println("Cookies updated");
41+
}
42+
}

src/main/java/net/httpclient/wrapper/events/HttpClientSessionEvent.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import net.httpclient.wrapper.session.HttpClientSession;
44

55
import java.util.ArrayList;
6+
import java.util.List;
67

78
/**
89
* This static class manage the HttpClientSession events.
@@ -20,15 +21,19 @@ public class HttpClientSessionEvent {
2021
* @param listener The listener to add.
2122
*/
2223
public static void addHttpClientSessionListener(HttpClientSessionListener listener) {
23-
httpClientSessionBasics.add(listener);
24+
synchronized (httpClientSessionBasics) {
25+
httpClientSessionBasics.add(listener);
26+
}
2427
}
2528

2629
/**
2730
* Remove a listener from the list of listeners.
2831
* @param listener The listener to remove.
2932
*/
3033
public static void removeHttpClientSessionListener(HttpClientSessionListener listener) {
31-
httpClientSessionBasics.remove(listener);
34+
synchronized (httpClientSessionBasics) {
35+
httpClientSessionBasics.remove(listener);
36+
}
3237
}
3338

3439
/*
@@ -40,8 +45,24 @@ public static void removeHttpClientSessionListener(HttpClientSessionListener lis
4045
* @param httpClientSession The HttpClientSession who has updated his cookies.
4146
*/
4247
public static void triggerHttpClientCookiesUpdated(HttpClientSession httpClientSession) {
43-
httpClientSessionBasics.forEach(listener -> listener.onHttpClientCookiesUpdated(httpClientSession));
48+
synchronized (httpClientSessionBasics) {
49+
httpClientSessionBasics.forEach(listener -> listener.onHttpClientCookiesUpdated(httpClientSession));
50+
}
4451
}
4552

4653

54+
/*
55+
$ Getters
56+
*/
57+
58+
/**
59+
* This method return a list copy of the listeners.
60+
* @return A list copy of the listeners.
61+
*/
62+
public static List<HttpClientSessionListener> getHttpClientSessionListeners() {
63+
synchronized (httpClientSessionBasics) {
64+
return new ArrayList<>(httpClientSessionBasics);
65+
}
66+
}
67+
4768
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package net.httpclient.wrapper.ratelimiter;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
import org.jetbrains.annotations.Nullable;
5+
6+
import java.time.Duration;
7+
import java.time.Instant;
8+
9+
public class RateLimiter {
10+
11+
private Duration duration;
12+
private Instant lastAcquire;
13+
14+
/*
15+
$ Constructor
16+
*/
17+
18+
/**
19+
* Create a rate limiter with a duration.
20+
* @param duration The duration between each acquire.
21+
*/
22+
public RateLimiter(@NotNull Duration duration) {
23+
this.duration = duration;
24+
}
25+
26+
/**
27+
* Sleep until the duration is passed.
28+
*/
29+
public void acquire() {
30+
synchronized (this) {
31+
try {
32+
dangerousAcquire();
33+
} catch (InterruptedException e) {
34+
e.printStackTrace();
35+
}
36+
}
37+
}
38+
39+
public void dangerousAcquire() throws InterruptedException {
40+
synchronized (this) {
41+
if (lastAcquire == null) {
42+
lastAcquire = Instant.now();
43+
return;
44+
}
45+
Duration durationToSleep = getRemainingTime();
46+
if (durationToSleep.isZero()) Thread.sleep(durationToSleep.toMillis());
47+
lastAcquire = Instant.now();
48+
}
49+
}
50+
51+
/**
52+
* Reset the rate limiter.
53+
*/
54+
public void reset() {
55+
lastAcquire = null;
56+
}
57+
58+
/**
59+
* Get the remaining time before the next acquire.
60+
* @return The remaining time in milliseconds.
61+
*/
62+
public @NotNull Duration getRemainingTime() {
63+
if (lastAcquire == null) return Duration.ZERO;
64+
long lastRequest = lastAcquire.toEpochMilli();
65+
long now = Instant.now().toEpochMilli();
66+
long result = lastRequest + duration.toMillis() - now;
67+
return (result > 0) ? Duration.ofMillis(result) : Duration.ZERO;
68+
}
69+
70+
/*
71+
$ Getters
72+
*/
73+
74+
public @NotNull Duration getDuration() {
75+
return duration;
76+
}
77+
78+
public @Nullable Instant getLastAcquire() {
79+
return lastAcquire;
80+
}
81+
82+
public void setDuration(@NotNull Duration duration) {
83+
this.duration = duration;
84+
}
85+
86+
}

src/main/java/net/httpclient/wrapper/response/RequestResponse.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,19 @@ public String getRawResponse() {
5757
}
5858

5959
public JSONObject toJSONObject() {
60-
return (new JSONObject(rawResponse));
60+
try {
61+
return (new JSONObject(rawResponse));
62+
} catch (Exception e) {
63+
return (null);
64+
}
6165
}
6266

6367
public JSONArray toJSONArray() {
64-
return (new JSONArray(rawResponse));
68+
try {
69+
return (new JSONArray(rawResponse));
70+
} catch (Exception e) {
71+
return (null);
72+
}
6573
}
6674

6775
public long getTime() {

src/main/java/net/httpclient/wrapper/session/HttpClientSession.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public class HttpClientSession {
5454
protected final BasicCookieStore httpCookieStore = new BasicCookieStore();
5555
protected RequestConfig.Builder requestConfig;
5656
protected String userAgent = RandomUserAgent.getRandomUserAgent();
57+
protected Object metadata = null;
5758

5859
private final long TIMEOUT = TimeUnit.MILLISECONDS.convert(10, TimeUnit.SECONDS);
5960

@@ -227,6 +228,8 @@ else if (statusCode >= 400 && statusCode <= 499)
227228
* @param serializedOldCookieStore The old cookie store before the request serialized as string.
228229
*/
229230
private void verifyCookiesEvents(String serializedOldCookieStore) {
231+
if (HttpClientSessionEvent.getHttpClientSessionListeners().size() == 0)
232+
return;
230233
try {
231234
String serializedNewCookieStore = BasicCookieStoreSerializerUtils.serializableToBase64(httpCookieStore);
232235
if (!serializedOldCookieStore.equals(serializedNewCookieStore))
@@ -289,4 +292,11 @@ public void setUserAgent(String userAgent) {
289292
this.userAgent = userAgent;
290293
}
291294

295+
public Object getMetadata() {
296+
return metadata;
297+
}
298+
299+
public void setMetadata(Object metadata) {
300+
this.metadata = metadata;
301+
}
292302
}

src/main/java/net/httpclient/wrapper/session/HttpClientSessionRateLimited.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package net.httpclient.wrapper.session;
22

3-
import com.google.common.util.concurrent.RateLimiter;
43
import net.httpclient.wrapper.exception.HttpClientException;
54
import net.httpclient.wrapper.exception.HttpServerException;
5+
import net.httpclient.wrapper.ratelimiter.RateLimiter;
66
import net.httpclient.wrapper.response.RequestResponse;
77
import org.apache.http.NameValuePair;
88
import org.apache.http.entity.ContentType;
99

1010
import java.io.IOException;
11+
import java.time.Duration;
1112
import java.util.List;
1213

1314
public class HttpClientSessionRateLimited extends HttpClientSession {
@@ -20,7 +21,7 @@ public HttpClientSessionRateLimited() {
2021

2122
public HttpClientSessionRateLimited(double permitsPerSecond) {
2223
super();
23-
rateLimiter = RateLimiter.create(permitsPerSecond);
24+
rateLimiter = new RateLimiter(Duration.ofSeconds((int)permitsPerSecond));
2425
}
2526

2627
@Override
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package net.httpclient.wrapper.ratelimiter;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.time.Duration;
6+
import java.time.Instant;
7+
8+
import static org.junit.jupiter.api.Assertions.*;
9+
10+
class RateLimiterTest {
11+
12+
@Test
13+
public void constructTest() {
14+
assertThrows(IllegalArgumentException.class, () -> new RateLimiter(null));
15+
assertDoesNotThrow(() -> new RateLimiter(Duration.ofSeconds(1)));
16+
}
17+
18+
@Test
19+
public void acquireTest() {
20+
RateLimiter rateLimiter = new RateLimiter(Duration.ofSeconds(1));
21+
assertDoesNotThrow(() -> rateLimiter.acquire());
22+
assertDoesNotThrow(() -> rateLimiter.acquire());
23+
}
24+
25+
@Test
26+
public void getRemainingTimeTest() throws InterruptedException {
27+
int durationInSeconds = 3;
28+
RateLimiter rateLimiter = new RateLimiter(Duration.ofSeconds(durationInSeconds));
29+
rateLimiter.acquire();
30+
assertEquals(durationInSeconds, rateLimiter.getRemainingTime().toSeconds());
31+
rateLimiter.reset();
32+
assertEquals(Duration.ZERO, rateLimiter.getRemainingTime());
33+
}
34+
35+
}

0 commit comments

Comments
 (0)