Open In App

Rate Limiting With Client IP in Spring Cloud Gateway

Last Updated : 23 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Rate limiting is a controlling strategy for the request rate of a network, server, or other resource. Its purpose is to prevent excessive or abusive resource use while ensuring it is available to all users. There exist multiple approaches for executing rate limitations. A popular method is setting over most requests a user or client may make in a certain amount of time, such as a minute or an hour. The user’s subsequent requests can be rejected or delayed until the rate limit is reset if they are over this restriction.

Example of Rate Limiting With Client IP in Spring Cloud Gateway:

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Optional;

@Configuration
public class RateLimitingConfig {

    @Autowired
    private CustomKeyResolver customKeyResolver;

    @Bean
    public CustomKeyResolver customKeyResolver() {
        return new CustomKeyResolver();
    }

    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> {
            // Extracting the client IP address from request
            String ip = Optional.ofNullable(exchange.getRequest().getRemoteAddress())
                                .map(address -> address.getAddress().getHostAddress())
                                .orElse("unknown");
            // Use custom key resolver to resolve IP-based keys
            return Mono.just(ip);
        };
    }
}
  • This Java configuration class defines a bean for resolving client IP addresses for rate limiting purposes in Spring Cloud Gateway.
  • It autowires a custom key resolver and provides a bean for resolving IP-based keys using the RemoteAddress of the incoming ServerWebExchange request.


Implementation of Rate Limiting With Client IP in Spring Cloud Gateway

Below are the implementation steps of Rate Limiting With Client IP in Spring Cloud Gateway.

Step 1: Configure a Route

Given that distributed systems are involved, it may be necessary for us to monitor all incoming requests coming from all of our application’s instances.

For this reason, storing the contents of the bucket in a distributed cache system is practical. In this instance, we simulated a real-world application by preconfiguring a Redis instance we’ll set up a route with a rate limiter next. We will listen for requests at the /example endpoint and send them to http://custom-service:

Java
@Bean
public RouteLocator customRoutes(RouteLocatorBuilder locatorBuilder) {
    return locatorBuilder.routes()
        .route("custom_route", predicate -> predicate
            .path("/custom-path") // Update the path according to requirements
            .filters(filter -> filter.requestRateLimiter(rateLimiter -> rateLimiter.setRateLimiter(customRateLimiter()))) // Customize the rate limiter as needed
            .uri("http://custom-service")) // Update the target URI to the appropriate endpoint
        .build();
}
  • We inject into the customRoutes bean the ipKeyResolver bean, which handles resolving client IP addresses.
  • Set up a route within the custom routes bean called “custom_route” to match requests made to the /custom-path endpoint.
  • then, specify the destination URI (http://custom-service) to which requests that correspond with this route should be sent. For your use case, you should substitute the proper endpoint URI for this one.


Step 2: The IP address of the client in KeyResolver

Since there is not yet a default implementation for this interface, we must create one while keeping in mind that we need the IP address of the client:

Java
@Component
public class CustomAddressResolver implements KeyResolver {

    // Resolve method to determine the client address for rate limiting
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        // Retrieve the remote address from the exchange's request
        return Optional.ofNullable(exchange.getRequest().getRemoteAddress())
            // Map the remote address to the host address
            .map(address -> address.getAddress().getHostAddress())
            // Wrap the host address into a Mono (asynchronous value) if present
            .map(Mono::just)
            // If the remote address is not available, return an empty Mono
            .orElseGet(Mono::empty);
    }
}


Step 3: Identify the Origin of IP Address

Determining the geographic location or network provider linked to an IP address is usually necessary to find its origin.

Java
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

// Indicates this bean as the primary one if multiple implementations are available
@Primary 
// Marks this class as a Spring component for component scanning and auto-configuration
@Component 
public class CustomProxyAddressResolver implements KeyResolver {

    // Resolve method to determine the client address for rate limiting
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        // Create an XForwardedRemoteAddressResolver with max trusted index
        XForwardedRemoteAddressResolver resolver = XForwardedRemoteAddressResolver.maxTrustedIndex(1);
        
        // Resolve the client's address from the exchange using the XForwardedRemoteAddressResolver
        InetSocketAddress inetSocketAddress = resolver.resolve(exchange);
        
        // Extract and return the host address from the resolved InetSocketAddress
        return Mono.just(inetSocketAddress.getAddress().getHostAddress());
    }
}
  • @Primary annotation suggests that if there are several implementations of the same type, this bean ought to be used as the main bean. When you wish to designate one bean as the default among several of the same kind, it’s helpful.
  • The rate-limiting feature in KeyResolver of Spring Cloud Gateway includes this interface. Based on the supplied ServerWebExchange object, it specifies a method called resolve(ServerWebExchange exchange) that resolves a key used for rate limitation.
  • If the application is running behind a load balancer or proxy, it uses Spring Cloud Gateway’s XForwardedRemoteAddressResolver to handle forwarded IP addresses.




Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads