forked from I2P_Developers/i2p.i2p
Handle 429 responses
Some checks failed
Java CI / build (push) Has been cancelled
Java CI / javadoc-latest (push) Has been cancelled
Java CI / build-java7 (push) Has been cancelled
Java with IzPack Snapshot Setup / setup (push) Has been cancelled
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
Some checks failed
Java CI / build (push) Has been cancelled
Java CI / javadoc-latest (push) Has been cancelled
Java CI / build-java7 (push) Has been cancelled
Java with IzPack Snapshot Setup / setup (push) Has been cancelled
Sync Primary Repository to GitHub Mirror / sync (push) Has been cancelled
untested
This commit is contained in:
@ -19,6 +19,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import net.i2p.CoreVersion;
|
||||
@ -57,6 +58,7 @@ class RemoteSearch {
|
||||
private static final AtomicInteger _lastSent = new AtomicInteger();
|
||||
private static final AtomicInteger _lastRcvd = new AtomicInteger();
|
||||
private static final AtomicReference<String> _currentSearch = new AtomicReference<String>();
|
||||
private static final AtomicLong _bannedUntil = new AtomicLong();
|
||||
// positive/negative cache, Result.result may be null
|
||||
private static final Map<String, Result> _cache = new LHMCache<String, Result>(16);
|
||||
//private static final List<Thread> _waiting = new ArrayList<Thread>(16);
|
||||
@ -175,6 +177,19 @@ class RemoteSearch {
|
||||
return null;
|
||||
}
|
||||
|
||||
long currentBan = _bannedUntil.get();
|
||||
if (currentBan > 0) {
|
||||
long now = _ctx.clock().now();
|
||||
if (currentBan > now) {
|
||||
long retry = currentBan - now;
|
||||
if (retry <= 10*60*1000)
|
||||
return _t("Rate limited for {0}", DataHelper.formatDuration(retry));
|
||||
else
|
||||
return _t("Rate limited until {0}", DataHelper.formatTime(currentBan));
|
||||
}
|
||||
_bannedUntil.compareAndSet(currentBan, 0);
|
||||
}
|
||||
|
||||
// if a new search comes in within 650 ms, interrupt the old one
|
||||
if (isXHR) {
|
||||
Thread us = Thread.currentThread();
|
||||
@ -239,7 +254,11 @@ class RemoteSearch {
|
||||
code = -1;
|
||||
if (code > 0) {
|
||||
buf.append(code);
|
||||
String text = get.getStatusText();
|
||||
String text;
|
||||
if (code == 429)
|
||||
text = process429(out);
|
||||
else
|
||||
text = get.getStatusText();
|
||||
if (text != null)
|
||||
buf.append(' ').append(DataHelper.escapeHTML(text));
|
||||
} else {
|
||||
@ -304,6 +323,27 @@ class RemoteSearch {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private String process429(ByteArrayStream out) {
|
||||
try {
|
||||
Reader in = new InputStreamReader(out.asInputStream(), "UTF-8");
|
||||
JsonObject map = (JsonObject) Jsoner.deserialize(in);
|
||||
long retry = map.getIntegerOrDefault(RETRY) * 1000L;
|
||||
long until = _ctx.clock().now() + retry;
|
||||
long currentBan = _bannedUntil.get();
|
||||
while (until > currentBan && !_bannedUntil.compareAndSet(currentBan, until)) {
|
||||
currentBan = _bannedUntil.get();
|
||||
}
|
||||
if (retry <= 10*60*1000)
|
||||
return _t("Rate limited for {0}", DataHelper.formatDuration(retry));
|
||||
else
|
||||
return _t("Rate limited until {0}", DataHelper.formatTime(until));
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("json error input=\"" + DataHelper.getUTF8(out.toByteArray()), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// keys with defaults
|
||||
private static final JsonKey ADDED = Jsoner.mintJsonKey("added", "");
|
||||
private static final JsonKey ALIVE = Jsoner.mintJsonKey("is_alive", Integer.valueOf(0));
|
||||
@ -319,6 +359,7 @@ class RemoteSearch {
|
||||
private static final JsonKey LINK = Jsoner.mintJsonKey("download_link", "");
|
||||
private static final JsonKey NAME = Jsoner.mintJsonKey("name", "");
|
||||
private static final JsonKey OWNER = Jsoner.mintJsonKey("owner", "");
|
||||
private static final JsonKey RETRY = Jsoner.mintJsonKey("retry_after", Integer.valueOf(60));
|
||||
private static final JsonKey SEEDS = Jsoner.mintJsonKey("seeders", Integer.valueOf(0));
|
||||
private static final JsonKey SIZE = Jsoner.mintJsonKey("size", Long.valueOf(0));
|
||||
private static final JsonKey TORRENTS = Jsoner.mintJsonKey("torrents", null);
|
||||
|
Reference in New Issue
Block a user