The RewritePath filter in Spring Cloud Gateway is used to
modify the request path before it reaches the downstream service. This is
particularly useful when you want to change the URL structure of requests
without requiring the downstream service to be aware of these changes.
How RewritePath Works
- Routing:
     When a request comes into the Spring Cloud Gateway, it is matched against
     the defined routes. Each route can have filters that modify the incoming
     request before it is forwarded to the target service.
 - Path
     Rewriting: The RewritePath filter allows you to define a pattern to
     match the incoming path and a replacement for that path. For example, if
     you have a service that expects a request at /service/v1/resource, but
     your gateway receives requests at /api/resource, you can use the RewritePath
     filter to transform the request path accordingly.
 - Configuration:
     You can configure the RewritePath filter in your application.yml or application.properties
     file, or directly in your Java configuration.
 
The YAML configuration of rewrites the path for
the service_route in Spring Cloud Gateway. This uses a RewritePath
filter to remove the /service prefix from incoming requests and forward them to
the backend service.
Here’s an explanation of what each part does:
YAML Explanation:
yaml
| 
   spring:   cloud:     gateway:       routes:       - id: service_route         uri: http://localhost:8081         predicates:         - Path=/service/**         filters:         -
  RewritePath=/service(?<segment>/?.*), $\{segment}  | 
 
1. Route ID:
- id:
     service_route: This is the unique identifier for this route.
 
2. URI:
- uri:
     http://localhost:8081: The URI where the request will be forwarded once it
     passes the gateway. In this case, it's a local service running on port
     8081.
 
3. Predicate:
- -
     Path=/service/**: This predicate matches all requests that start with /service.
     Only requests that match this path will be routed to this backend service.
 
4. Filter:
- RewritePath=/service(?<segment>/?.*),
     ${segment}:
 - This
      filter rewrites the incoming request path by removing the /service
      prefix.
 - (?<segment>/?.*):
      This is a regular expression used to capture the remaining path after /service.
 - ${segment}:
      Refers to the captured path segment, meaning the remaining part of the
      path (after /service) will be forwarded to the target service.
 
Example:
- Incoming
     Request:
If you send a request like http://localhost:8080/service/api/v1/resource to the gateway: - The
      predicate (Path=/service/**) will match this request.
 - The
      filter (RewritePath=/service(?<segment>/?.*), ${segment}) will
      rewrite the path to /api/v1/resource.
 - Forwarded
     Request:
The rewritten request will be forwarded to the backend service at http://localhost:8081/api/v1/resource. 
Why Use This Filter?
The RewritePath filter is commonly used when you want to
keep your gateway paths structured but need to remove specific prefixes before
forwarding requests to backend services that do not expect those prefixes.
Possible Enhancements
- Additional
     Filters: You can add other filters like RequestRateLimiter, Retry, or
     custom filters like Debouncing or Throttling as discussed
     earlier to handle specific traffic conditions.
 - Security:
     You could add Authorization or CORS filters to manage access
     to your routes.
 
Here’s how you can configure RequestRateLimiter, Retry,
and custom filters in Spring Cloud Gateway using YAML.
1. RequestRateLimiter Filter Example:
This filter limits the number of requests allowed to hit
your service per second based on a key (such as user ID or IP).
yaml
| 
   spring:   cloud:     gateway:       routes:         - id: rate_limited_route           uri: http://localhost:8081           predicates:             - Path=/service/**           filters:             -
  RewritePath=/service(?<segment>/?.*), $\{segment}             - name: RequestRateLimiter               args:                 key-resolver:
  "#{@userKeyResolver}"  #
  Custom key resolver bean to resolve user identity                 redis-rate-limiter:                   replenishRate: 10   # Requests per second                   burstCapacity: 20   # Maximum burst capacity                   requestedTokens: 1  # Tokens required per request  | 
 
Explanation:
- key-resolver:
     Used to define how to identify the user making the request. You need a
     custom bean (like userKeyResolver) to determine the key (such as user IP
     or user ID).
 - replenishRate:
     Defines how many tokens are added to the bucket every second (requests per
     second).
 - burstCapacity:
     Defines how many requests the system can handle in bursts.
 - requestedTokens:
     Number of tokens required for each request.
 
You will need to define the userKeyResolver in a
configuration class as a bean:
java
| 
   @Bean public
  KeyResolver userKeyResolver() {     return exchange ->
  Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()); }  | 
 
2. Retry Filter Example:
The Retry filter automatically retries failed
requests based on specific conditions (like status codes or exceptions).
yaml
| 
   spring:   cloud:     gateway:       routes:         - id: retry_route           uri: http://localhost:8082           predicates:             - Path=/service/retry/**           filters:             -
  RewritePath=/service/retry(?<segment>/?.*), $\{segment}             - name: Retry               args:                 retries: 3          # Number of retries                 statuses: BAD_GATEWAY,
  GATEWAY_TIMEOUT  # HTTP status codes to
  retry                 backoff:                   firstBackoff: 100ms  # Delay before the first retry                   maxBackoff: 1s       # Maximum delay between retries                   factor: 2            # Exponential factor for backoff                   jitter: true         # Adds random jitter to avoid retry
  collisions  | 
 
Explanation:
- retries:
     The number of retry attempts.
 - statuses:
     List of HTTP statuses to trigger a retry.
 - backoff:
     Defines the backoff strategy for retries.
 - firstBackoff:
      Initial wait time before retrying.
 - maxBackoff:
      Maximum time between retries.
 - factor:
      Multiplies the backoff delay for each retry.
 - jitter:
      Adds random variation to backoff timing to prevent repeated retries from
      overwhelming the server.
 
3. Custom Filter Example (Debouncing or Throttling):
You can implement custom logic like Debouncing or Throttling
in your own Spring Cloud Gateway filter. Here’s an example of a custom filter
configuration with YAML:
yaml
| 
   spring:   cloud:     gateway:       routes:         - id: throttled_route           uri: http://localhost:8083           predicates:             - Path=/service/throttle/**           filters:             -
  RewritePath=/service/throttle(?<segment>/?.*), $\{segment}             - name: ThrottlingFilter   # Custom filter registered in your code               args:                 maxRequests: 5        # Maximum allowed requests per time
  window                 timeWindow: 10s       # Time window in seconds  | 
 
Custom Filter Implementation (Throttling Filter):
To enable this, you would need to define the custom filter
in your code:
java
| 
   @Component public class
  ThrottlingFilter implements
  GatewayFilterFactory<ThrottlingFilter.Config> {     public static class Config {         private int maxRequests;         private Duration timeWindow;         // Getters and Setters     }     private final Map<String, Integer>
  requestCounts = new ConcurrentHashMap<>();     private final Map<String, Long>
  timeWindowStart = new ConcurrentHashMap<>();     @Override     public GatewayFilter apply(Config config)
  {         return (exchange, chain) -> {             String clientId =
  exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();             long currentTime =
  System.currentTimeMillis();             requestCounts.compute(clientId,
  (key, count) -> {                 long windowStart =
  timeWindowStart.getOrDefault(key, currentTime);                 if (currentTime - windowStart
  > config.timeWindow.toMillis()) {                     timeWindowStart.put(key,
  currentTime);                     return 1;                 }                 return count + 1;             });             if (requestCounts.get(clientId)
  > config.maxRequests) {                
  exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);                 return
  exchange.getResponse().setComplete();             }             return chain.filter(exchange);         };     }     @Override     public Config newConfig() {         return new Config();     } }  | 
 
Then, in your configuration file:
yaml
| 
   spring:   cloud:     gateway:       default-filters:         - ThrottlingFilter:             maxRequests: 5             timeWindow: 10s  | 
 
Conclusion:
By combining these filters, you can create sophisticated
traffic control mechanisms in Spring Cloud Gateway:
- RequestRateLimiter
     for limiting the number of requests.
 - Retry
     for automatically retrying failed requests.
 - Custom
     filters like throttling for specialized request control.
 
| Sequence Diagram Spring Cloud Gateway uses a RewritePath filter | 
| Flowchart Diagram Spring Cloud Gateway uses a RewritePath filter  | 
For more information, visit 
Ø    Microservices:
Custom Filters for Debouncing, Throttling, Rate Limits & Backoff
Ø   Mastering Debouncing, Throttling, Rate Limiting, and Exponential
Backoff.
Ø  Custom
Filters in Microservices
0 Comments