I'm introducing Bucket4J in my Spring Web application. A basic test setup can be found here:
Bucket4J offers to rate limit on IP basis - so every IP gets its own pool of tokens. This can be done by adding expression: "getRemoteAddress()"
to the config:
bucket4j:
enabled: true
filters:
- metrics:
types:
- consumed-counter
- rejected-counter
- cache-name: buckets
filter-method: webflux
url: .*
filter-order: 1
rate-limits:
- bandwidths:
- capacity: 1
time: 10
unit: seconds
expression: "getRemoteAddress()"
I'm having a hard time figuring out how to programmatically test if filter by IP
is working.
The test for a single IP looks like this:
@ActiveProfiles("test")
@SpringBootTest
class RateLimitTest(
@Autowired val context: ApplicationContext
) {
@Test
fun `FAILS with status code 429 if rate limit is exceeded`() {
// arrange
val client = WebTestClient
.bindToApplicationContext(context)
.configureClient()
.build()
// ac
client.get()
.uri("/api/someendpoint")
.exchange()
.expectStatus().isOk
.expectHeader().valueEquals("X-Rate-Limit-Remaining", "0")
client.get()
.uri("/api/someendpoint")
.exchange()
.expectStatus().isEqualTo(HttpStatus.TOO_MANY_REQUESTS)
.expectBody().jsonPath("error", "Too many requests!")
// assert
}
What should a test look like that verifies behaviour for multiple IPs / IP rate limiting?
FAILS with status code 429 if rate limit * for IP * is exceeded
Actually my approach was wrong in general. The application in question is behind a load balancer so querying
getRemoteAddress()
will only give me the IP of the load balancer.I had to use the header
X-FORWARDED-FOR
and this made it super easy to create a test for itand the test for this is