-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
740e39a
commit a65dffa
Showing
21 changed files
with
258 additions
and
89 deletions.
There are no files selected for viewing
13 changes: 0 additions & 13 deletions
13
src/main/java/com/changolaxtra/cloud/ratelimiter/RateLimiterApplication.java
This file was deleted.
Oops, something went wrong.
11 changes: 11 additions & 0 deletions
11
src/main/java/com/changolaxtra/cloud/ratelimiter/annotations/ApiRateLimited.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.changolaxtra.cloud.ratelimiter.annotations; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ElementType.METHOD}) | ||
public @interface ApiRateLimited { | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/com/changolaxtra/cloud/ratelimiter/annotations/EnableApiRateLimiter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.changolaxtra.cloud.ratelimiter.annotations; | ||
|
||
import org.springframework.context.annotation.ComponentScan; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.TYPE) | ||
@ComponentScan(basePackages = "com.changolaxtra.cloud.ratelimiter") | ||
public @interface EnableApiRateLimiter { | ||
} |
52 changes: 52 additions & 0 deletions
52
src/main/java/com/changolaxtra/cloud/ratelimiter/aspect/ApiRateLimitedAspect.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.changolaxtra.cloud.ratelimiter.aspect; | ||
|
||
import com.changolaxtra.cloud.ratelimiter.configuration.RateLimiterConfiguration; | ||
import com.changolaxtra.cloud.ratelimiter.core.PlanLimitBucket; | ||
import com.changolaxtra.cloud.ratelimiter.storage.PlanLimitStorage; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.aspectj.lang.ProceedingJoinPoint; | ||
import org.aspectj.lang.annotation.Around; | ||
import org.aspectj.lang.annotation.Aspect; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.context.request.RequestContextHolder; | ||
import org.springframework.web.context.request.ServletRequestAttributes; | ||
|
||
import java.util.Optional; | ||
|
||
@Slf4j | ||
@Aspect | ||
@Component | ||
public class ApiRateLimitedAspect { | ||
|
||
private final PlanLimitStorage planLimitStorage; | ||
private final RateLimiterConfiguration rateLimiterConfiguration; | ||
|
||
public ApiRateLimitedAspect(final PlanLimitStorage planLimitStorage, | ||
final RateLimiterConfiguration rateLimiterConfiguration) { | ||
this.planLimitStorage = planLimitStorage; | ||
this.rateLimiterConfiguration = rateLimiterConfiguration; | ||
} | ||
|
||
@Around("@annotation(com.changolaxtra.cloud.ratelimiter.annotations.ApiRateLimited)") | ||
public Object rateLimitCheck(final ProceedingJoinPoint joinPoint) throws Throwable { | ||
final String apiKey = getApiKey(); | ||
final PlanLimitBucket planLimit = planLimitStorage.getPlanLimit(apiKey); | ||
if (planLimit.isAllowed()) { | ||
return joinPoint.proceed(); | ||
} else { | ||
return ResponseEntity | ||
.status(HttpStatus.TOO_MANY_REQUESTS) | ||
.body("API-Keys does not allow more calls at this moment."); | ||
} | ||
} | ||
|
||
private String getApiKey() { | ||
return Optional.ofNullable(RequestContextHolder.getRequestAttributes()) | ||
.map(requestAttributes -> (ServletRequestAttributes) requestAttributes) | ||
.map(ServletRequestAttributes::getRequest) | ||
.map(request -> request.getHeader(rateLimiterConfiguration.getApiKeyHeaderName())) | ||
.orElse(rateLimiterConfiguration.getDefaultApiKey()); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
...in/java/com/changolaxtra/cloud/ratelimiter/configuration/DefaultPlanLimitInitializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.changolaxtra.cloud.ratelimiter.configuration; | ||
|
||
import com.changolaxtra.cloud.ratelimiter.core.PlanLimitBucket; | ||
import com.changolaxtra.cloud.ratelimiter.exception.RateLimitException; | ||
import com.changolaxtra.cloud.ratelimiter.core.policy.RateLimitPolicy; | ||
import com.changolaxtra.cloud.ratelimiter.storage.PlanLimitStorage; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Slf4j | ||
@Component | ||
public class DefaultPlanLimitInitializer implements InitializingBean { | ||
|
||
private final PlanLimitStorage planLimitStorage; | ||
private final RateLimiterConfiguration rateLimiterConfiguration; | ||
|
||
public DefaultPlanLimitInitializer(final PlanLimitStorage planLimitStorage, | ||
final RateLimiterConfiguration rateLimiterConfiguration) { | ||
this.planLimitStorage = planLimitStorage; | ||
this.rateLimiterConfiguration = rateLimiterConfiguration; | ||
} | ||
|
||
|
||
@Override | ||
public void afterPropertiesSet() throws Exception { | ||
final RateLimitPolicy defaultPolicy = getDefaultPolicy(); | ||
final boolean isDefaultPolicyCreated = planLimitStorage.saveOrUpdate(new PlanLimitBucket(defaultPolicy)); | ||
if (!isDefaultPolicyCreated) { | ||
log.error("Default policy wasn't created."); | ||
throw new RateLimitException("Default policy wasn't created."); | ||
} | ||
log.info("Default policy was created correctly: {}", defaultPolicy); | ||
} | ||
|
||
private RateLimitPolicy getDefaultPolicy() { | ||
return RateLimitPolicy | ||
.builder() | ||
.apiKey(rateLimiterConfiguration.getDefaultApiKey()) | ||
.allowedRequests(rateLimiterConfiguration.getDefaultAllowedRequests()) | ||
.windowSizeInMilliSeconds(rateLimiterConfiguration.getDefaultWindowSizeInMilliSeconds()) | ||
.isUnlimited(rateLimiterConfiguration.isDefaultIsUnlimited()) | ||
.build(); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/com/changolaxtra/cloud/ratelimiter/configuration/RateLimiterConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,26 @@ | ||
package com.changolaxtra.cloud.ratelimiter.configuration; | ||
|
||
import lombok.Getter; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Getter | ||
@Configuration | ||
public class RateLimiterConfiguration { | ||
|
||
@Value("${rate-limiter.apiKey-header-name}") | ||
private String apiKeyHeaderName; | ||
|
||
@Value("${rate-limiter.default-policy.apiKey}") | ||
private String defaultApiKey; | ||
|
||
@Value("${rate-limiter.default-policy.allowedRequests}") | ||
private long defaultAllowedRequests; | ||
|
||
@Value("${rate-limiter.default-policy.windowSizeInMilliSeconds}") | ||
private long defaultWindowSizeInMilliSeconds; | ||
|
||
@Value("${rate-limiter.default-policy.isUnlimited}") | ||
private boolean defaultIsUnlimited; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/main/java/com/changolaxtra/cloud/ratelimiter/core/PlanLimitBucket.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.changolaxtra.cloud.ratelimiter.core; | ||
|
||
import com.changolaxtra.cloud.ratelimiter.core.policy.RateLimitPolicy; | ||
import lombok.EqualsAndHashCode; | ||
|
||
@EqualsAndHashCode(onlyExplicitlyIncluded = true) | ||
public class PlanLimitBucket { | ||
|
||
@EqualsAndHashCode.Include | ||
private final String apiKey; | ||
private final TokenBucket tokenBucket; | ||
|
||
public PlanLimitBucket(final RateLimitPolicy rateLimitPolicy) { | ||
this.apiKey = rateLimitPolicy.getApiKey(); | ||
this.tokenBucket = new TokenBucket(rateLimitPolicy); | ||
} | ||
|
||
public String getApiKey() { | ||
return apiKey; | ||
} | ||
|
||
public boolean isAllowed() { | ||
return tokenBucket.isAllowed(); | ||
} | ||
|
||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/com/changolaxtra/cloud/ratelimiter/core/PlanLimitDataRoot.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.changolaxtra.cloud.ratelimiter.core; | ||
|
||
import com.changolaxtra.cloud.ratelimiter.core.PlanLimitBucket; | ||
import lombok.Getter; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
@Getter | ||
public class PlanLimitDataRoot { | ||
private final Set<PlanLimitBucket> planLimitBuckets; | ||
|
||
public PlanLimitDataRoot() { | ||
planLimitBuckets = new HashSet<>(); | ||
} | ||
|
||
public boolean addPlanLimitBucket(final PlanLimitBucket planLimitBucket) { | ||
return planLimitBuckets.add(planLimitBucket); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 3 additions & 1 deletion
4
...d/ratelimiter/policy/RateLimitPolicy.java → ...elimiter/core/policy/RateLimitPolicy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 0 additions & 21 deletions
21
src/main/java/com/changolaxtra/cloud/ratelimiter/data/ApiLimitBucket.java
This file was deleted.
Oops, something went wrong.
15 changes: 0 additions & 15 deletions
15
src/main/java/com/changolaxtra/cloud/ratelimiter/data/ApiLimitDataRoot.java
This file was deleted.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
src/main/java/com/changolaxtra/cloud/ratelimiter/exception/RateLimitException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.changolaxtra.cloud.ratelimiter.exception; | ||
|
||
public class RateLimitException extends RuntimeException { | ||
|
||
public RateLimitException(final String message) { | ||
super(message); | ||
} | ||
} |
17 changes: 0 additions & 17 deletions
17
src/main/java/com/changolaxtra/cloud/ratelimiter/storage/ApiLimitEmbeddedStorage.java
This file was deleted.
Oops, something went wrong.
4 changes: 0 additions & 4 deletions
4
src/main/java/com/changolaxtra/cloud/ratelimiter/storage/ApiLimitStorage.java
This file was deleted.
Oops, something went wrong.
41 changes: 41 additions & 0 deletions
41
src/main/java/com/changolaxtra/cloud/ratelimiter/storage/EmbeddedPlanLimitStorage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package com.changolaxtra.cloud.ratelimiter.storage; | ||
|
||
import com.changolaxtra.cloud.ratelimiter.core.PlanLimitBucket; | ||
import com.changolaxtra.cloud.ratelimiter.core.PlanLimitDataRoot; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.eclipse.store.storage.embedded.types.EmbeddedStorageManager; | ||
import org.springframework.stereotype.Repository; | ||
|
||
import java.util.HashSet; | ||
import java.util.Optional; | ||
|
||
@Repository | ||
public class EmbeddedPlanLimitStorage implements PlanLimitStorage { | ||
|
||
private final EmbeddedStorageManager.Default embeddedStorageManager; | ||
|
||
public EmbeddedPlanLimitStorage(final EmbeddedStorageManager.Default embeddedStorageManager) { | ||
this.embeddedStorageManager = embeddedStorageManager; | ||
} | ||
|
||
@Override | ||
public PlanLimitBucket getPlanLimit(final String apiKey) { | ||
final PlanLimitDataRoot dataRoot = (PlanLimitDataRoot) embeddedStorageManager.root(); | ||
return Optional.ofNullable(dataRoot) | ||
.map(PlanLimitDataRoot::getPlanLimitBuckets) | ||
.orElse(new HashSet<>()) | ||
.stream() | ||
.filter(planLimitBucket -> StringUtils.equalsIgnoreCase(apiKey, planLimitBucket.getApiKey())) | ||
.findFirst() | ||
.orElse(null); | ||
} | ||
|
||
@Override | ||
public boolean saveOrUpdate(final PlanLimitBucket planLimitBucket) { | ||
final PlanLimitDataRoot dataRoot = (PlanLimitDataRoot) embeddedStorageManager.root(); | ||
return Optional.ofNullable(dataRoot) | ||
.map(root -> root.addPlanLimitBucket(planLimitBucket)) | ||
.orElse(false); | ||
} | ||
|
||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/com/changolaxtra/cloud/ratelimiter/storage/PlanLimitStorage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.changolaxtra.cloud.ratelimiter.storage; | ||
|
||
import com.changolaxtra.cloud.ratelimiter.core.PlanLimitBucket; | ||
|
||
public interface PlanLimitStorage { | ||
PlanLimitBucket getPlanLimit(String apiKey); | ||
boolean saveOrUpdate(PlanLimitBucket planLimitBucket); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
rate-limiter: | ||
apiKey-header-name: "X-API-Key" | ||
default-policy: | ||
apiKey: "" | ||
isUnlimited: false | ||
allowedRequests: 1 | ||
windowSizeInMilliSeconds: 60 |
Oops, something went wrong.