Skip to content

Latest commit

History

167 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

rate limiter javaee

Enterprise rate limiter for javaee web applications, based on rate-limiter-web-core.

We believe that rate limiting should be as simple as:

@Rate("10/s") // 10 permits per second for all methods in this class@Path("/api")
publicclassGreetingResource {
@Rate(permits=10, when="web.request.user.role = GUEST")
@GET@Path("/smile")
publicStringsmile() {
return":)";
}
@Rate(permits=1, when="jvm.memory.available < 1gb")
@GET@Path("/greet")
publicStringgreet(@QueryParam("who") Stringwho) {
return"Hello " + who;
}
}

Please first read the rate-limiter-web-core documentation.

To add a dependency on rate-limiter-javaee using Maven, use the following:

 <dependency>
<groupId>io.github.poshjosh</groupId>
<artifactId>rate-limiter-javaee</artifactId>
<version>0.8.0</version> </dependency>

Usage

1. Implement RateLimitProperties

publicclassRateLimitPropertiesImplimplementsRateLimitProperties {
// If not using annotations, return an empty list@OverridepublicList<String> getResourcePackages() {
returnCollections.singletonList("com.myapp.web.rest");
}
// If not using properties, return an empty map@OverridepublicList<Rates> getRates() {
// Accept only 2 tasks per secondreturnCollections.singletonList(Rates.of("task_queue", Rate.ofSeconds(2)));
}
}

2. Extend RateLimitingDynamicFeature

This way a rate limiter will be created an automatically applied based on rate limiter related properties and annotations.

@javax.ws.rs.ext.ProviderpublicclassDynamicFeatureImplextendsRateLimitingDynamicFeature {
@javax.inject.InjectpublicDynamicFeatureImpl(RateLimitPropertiesproperties) {
super(properties);
}
}

At this point, your application is ready to enjoy the benefits of rate limiting.

3. Annotate classes and/or methods.

@Path("/api")
classMyResource {
// Only 10 calls per second for users in role GUEST@Rate("10/s")
@RateCondition("web.request.user.role = GUEST")
@GET@Path("/greet")
@Produces("text/plain")
Stringgreet(Stringname) {
return"Hello " + name;
}
}

Fine-grained configuration of rate limiting

Configure rate limiting as described in the rate-limiter-web-core documentation.

When you configure rate limiting using properties, you could:

  • Rate limit a class from properties by using the class ID.

  • Rate limit a method from properties by using the method ID.

publicclassRateLimitPropertiesImplimplementsRateLimitProperties {
@OverridepublicList<Rates> getRates() {
List<Rates> ratesList = newArrayList<>();
// Rate limit a classStringclassId = RateId.of(MyResource.class);
ratesList.add(Rates.of(classId, Rate.ofMinutes(10)));
// Rate limit a methodStringmethodId = RateId.of(MyResource.class.getMethod("greet", String.class));
ratesList.add(Rates.of(methodId, Rate.ofMinutes(10)));
returnratesList;
}
}

Expression Language

The expression language allows us to write expressive rate conditions, e.g:

@RateCondition("web.request.user.role = GUEST")

@RateCondition("jvm.memory.free < 1GB")

formatexampledescription
LHS = RHSweb.request.header[X-RateLimit-Limit] !=true, when the X-RateLimit-Limit header exists
LHS[key] = valweb.request.parameter[limited] = truetrue, when request parameter limited equals true
LHS = [A ⎢ B]web.request.user.role = [GUEST ⎢ RESTRICTED]true, when the user role is either GUEST or RESTRICTED
LHS[key] = [A ⎢ B]web.request.cookie[name] = [val_0 ⎢ val_1]true, when cookie named name is either val_0 or val_1
LHS[key] = [A & B]web.request.header[name] = [val_0 & val_1]true, when header named name has both val_0 and val_1 as values

A rich set of conditions may be expressed as detailed in the web specification.

Manually create and use a RateLimiter

Usually, you are provided with appropriate RateLimiters based on the annotations and properties you specify. However, you could manually create and use RateLimiters.

classMyResource {
RateLimiterrateLimiter = RateLimiterRegistry.of(MyResource.class, "smile");
@Rate(id = "smile", permits = 2)
Stringsmile() {
return":)";
}
}

This way you use the RateLimiter as you see fit.

Annotation Specifications

Please read the annotation specs. It is concise.

Enjoy! 😉

Releases

Packages

Used by

Contributors

Languages