Skip to content

Commit e727566

Browse files
committed
apply rate limiter per ip
1 parent b944c12 commit e727566

2 files changed

Lines changed: 36 additions & 6 deletions

File tree

src/main/java/dev/zenith/web/api/WebServer.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package dev.zenith.web.api;
22

33
import com.fasterxml.jackson.databind.DeserializationFeature;
4+
import com.google.common.cache.Cache;
5+
import com.google.common.cache.CacheBuilder;
46
import com.zenith.Globals;
57
import com.zenith.command.api.CommandContext;
68
import com.zenith.discord.EmbedSerializer;
@@ -9,7 +11,6 @@
911
import dev.zenith.web.api.model.CommandRequest;
1012
import dev.zenith.web.api.model.CommandResponse;
1113
import io.javalin.Javalin;
12-
import io.javalin.http.util.NaiveRateLimit;
1314
import io.javalin.json.JavalinJackson;
1415
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
1516

@@ -21,6 +22,9 @@
2122

2223
public class WebServer {
2324
private Javalin server;
25+
private final Cache<String, Integer> rateLimitCache = CacheBuilder.newBuilder()
26+
.expireAfterWrite(1, TimeUnit.MINUTES)
27+
.build();
2428

2529
public synchronized void start() {
2630
if (server != null) {
@@ -56,6 +60,20 @@ private Javalin createServer() {
5660
config.jsonMapper(new JavalinJackson(objectMapper, false));
5761
})
5862
.beforeMatched(ctx -> {
63+
if (PLUGIN_CONFIG.rateLimiter) {
64+
String ip = ctx.ip();
65+
synchronized (this) {
66+
int reqCount = rateLimitCache.get(ip, () -> 0);
67+
rateLimitCache.put(ip, reqCount + 1);
68+
if (reqCount >= PLUGIN_CONFIG.rateLimitRequestsPerMinute) {
69+
ctx.status(429);
70+
ctx.json(new AuthErrorResponse("Rate limit exceeded"));
71+
ctx.skipRemainingHandlers();
72+
LOG.warn("Rate limit exceeded for IP: {}", ip);
73+
return;
74+
}
75+
}
76+
}
5977
var authHeaderValue = ctx.header("Authorization");
6078
if (authHeaderValue != null) {
6179
var expectedHeaderValue = PLUGIN_CONFIG.authToken;
@@ -73,9 +91,6 @@ private Javalin createServer() {
7391
LOG.warn("Denied request from {}: {}", ctx.ip(), reason);
7492
})
7593
.post("/command", ctx -> {
76-
if (PLUGIN_CONFIG.rateLimiter) {
77-
NaiveRateLimit.requestPerTimeUnit(ctx, PLUGIN_CONFIG.rateLimitRequestsPerMinute, TimeUnit.MINUTES);
78-
}
7994
var req = ctx.bodyAsClass(CommandRequest.class);
8095
var command = req.command();
8196
var context = CommandContext.create(command, WebAPICommandSource.INSTANCE);

src/main/java/dev/zenith/web/command/WebAPICommand.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ public CommandUsage commandUsage() {
2929
"on/off",
3030
"port <port>",
3131
"auth <token>",
32-
"commandsAccountOwnerPerms on/off"
32+
"commandsAccountOwnerPerms on/off",
33+
"rateLimiter on/off",
34+
"rateLimiter requestsPerMinute <requestCount>"
3335
)
3436
.build();
3537
}
@@ -64,7 +66,18 @@ public LiteralArgumentBuilder<CommandContext> register() {
6466
PLUGIN_CONFIG.commandsAccountOwnerPerms = getToggle(c, "toggle");
6567
c.getSource().getEmbed()
6668
.title("Commands Account Owner Perms " + toggleStrCaps(PLUGIN_CONFIG.commandsAccountOwnerPerms));
67-
})));
69+
})))
70+
.then(literal("rateLimiter")
71+
.then(argument("toggle", toggle()).executes(c -> {
72+
PLUGIN_CONFIG.rateLimiter = getToggle(c, "toggle");
73+
c.getSource().getEmbed()
74+
.title("Rate Limiter " + toggleStrCaps(PLUGIN_CONFIG.rateLimiter));
75+
}))
76+
.then(literal("requestsPerMinute").then(argument("requests", integer(1)).executes(c -> {
77+
PLUGIN_CONFIG.rateLimitRequestsPerMinute = getInteger(c, "requests");
78+
c.getSource().getEmbed()
79+
.title("Rate Limiter Requests Per Minute Set");
80+
}))));
6881
}
6982

7083
@Override
@@ -74,6 +87,8 @@ public void defaultEmbed(Embed embed) {
7487
.addField("Port", PLUGIN_CONFIG.port)
7588
.addField("Auth Token", PLUGIN_CONFIG.authToken)
7689
.addField("Commands Account Owner Perms", PLUGIN_CONFIG.commandsAccountOwnerPerms)
90+
.addField("Rate Limiter", toggleStr(PLUGIN_CONFIG.rateLimiter))
91+
.addField("Rate Limit Requests Per Minute", PLUGIN_CONFIG.rateLimitRequestsPerMinute)
7792
.primaryColor();
7893
}
7994
}

0 commit comments

Comments
 (0)