Home Spring Framework Request Body Transformation in Spring Cloud Gateway

Request Body Transformation in Spring Cloud Gateway

524
0

Spring Cloud Gateway project, a new API based on Spring 5, Spring Boot 2, and Project Reactor. The tool provides out-of-the-box routing mechanisms often used in microservices applications as a way of hiding multiple services behind a single facade.

In this article, we will learn how to transform request body using the existing filter ModifyRequestBodyGatewayFilterFactory.

For easy understanding I’ll write the solution in easy steps

Step 1: Create a Custom Pre Filter

We will create a global filter as we want to apply it to all the requests.

In the below code, you can see we have used an existing filter ModifyRequestBodyGatewayFilterFactory and provided a rewrite class RequestBodyRewrite.

The setRewriteFunction function contains three parameters

  1. inClass: The type of input. In our case this will be String as JSON/XML are strings.
  2. outClass: The type of output. In our case this will also be String as we will modify and add new keys in JSON.
  3. rewriteFunction: The function which will contain the logic for transformation.
package com.scg.route.filter.pre;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;

/** User: Amit Khurana Date: 2021-05-16 */
@Component
public class RequestTransaformationFilter implements GlobalFilter, Ordered {

  @Autowired private ModifyRequestBodyGatewayFilterFactory modifyRequestBodyFilter;
  @Autowired private RequestBodyRewrite requestBodyRewrite;

  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    return modifyRequestBodyFilter
        .apply(
            new ModifyRequestBodyGatewayFilterFactory.Config()
                .setRewriteFunction(String.class, String.class, requestBodyRewrite))
        .filter(exchange, chain);
  }

  @Override
  public int getOrder() {
    return 20; // The order in which you want this filter to execute
  }
}

Step 2: Write rewrite function

In the below logic you can see we have implemented an interface RewriteFunction<String, String>, the interface provides a method apply in which we will write our logic.

Apply method has two parameter

  1. exchange: The web exchange object.
  2. body: The original request body
package com.scg.route.filter.pre;

import java.util.Map;

import org.reactivestreams.Publisher;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ServerWebExchange;

import com.google.gson.Gson;

import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

@Service
@Slf4j
public class RequestBodyRewrite implements RewriteFunction<String, String> {

  @Override
  public Publisher<String> apply(ServerWebExchange exchange, String body) {
    Gson gson = new Gson();
    try {

      Map<String, Object> map = gson.fromJson(body, Map.class);

      map.put("empId", "2345");
      map.put("department", "Engineering");

      return Mono.just(gson.toJson(map, Map.class));
    } catch (Exception ex) {
      log.error(
          "An error occured while transforming the request body in class RequestBodyRewrite. {}",
          ex);
      
      // Throw custom exception here
      throw new RuntimeException(
          "An error occured while transforming the request body in class RequestBodyRewrite.");
    }
  }
}

Let us take an example to understand above logic. Suppose the request body is:

{
  "name":"Amit",
  "empId":"1234567"
}

In request, I want to change to the empId and add another key department before forwarding it to the client. To do this we have first converted the JSON string to Java Map and then replaced empId with a new value and added department key.

After the transformation we are converting the Map back to JSON string using GSON library.

Transformed request will look like this

{
  "name": "Amit",
  "empId": "2345",
  "department": "Engineering"
}

This is how we can transform the request body using custom logic.

To learn how to create a Spring application click here.

This site uses Akismet to reduce spam. Learn how your comment data is processed.