javaspringspring-bootspring-cloud-gateway

Modifying RequestBody in spring gateway


I want to modify the requestBody before routing it to given URI . Based on docs i am using

org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory to modify the body . On starting my server , server failed to start with below error Reason: The elements [spring.cloud.gateway.routes[0].filters[0].modifyrequestbody.class] were left unbound.\n\nAction:\n\nUpdate your application's configuration\n","context":"default"}

Below is the sample filter and Rewrite function

@Slf4j
public class SomeFilter implements GatewayFilter {

    private final ModifyRequestBodyGatewayFilterFactory factory;

    public RedirectionFilter(ModifyRequestBodyGatewayFilterFactory factory) {
        this.factory = factory;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        
        ModifyRequestBodyGatewayFilterFactory.Config cfg = new ModifyRequestBodyGatewayFilterFactory.Config();
        cfg.setContentType("application/json");
        cfg.setRewriteFunction(String.class, String.class, new MyRewriteFunction());


        factory.apply(cfg).filter(exchange, chain);

        // Continue the filter chain
        return chain.filter(exchange);
    }
}

Below is rewrite function

@Slf4j
public class MyRewriteFunction implements RewriteFunction<String, String> {

    @Override
    public Publisher<String> apply(ServerWebExchange exchange, String s) {
        
        
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                HelloObject obj = objectMapper.readValue(s, HelloObject.class);
                String newBody = new ObjectMapper().writeValueAsString(obj.getData());
                return Mono.just(newBody);
            } catch (Exception e) {
                /* error parsing values to json, do something else */
                log.error("Error while parsing body", e);
            }
        }
        return Mono.just(s);
    }
}

Below is yaml

      routes:
        - id: order-route-1
          uri: http://localhost:8999/
          predicates:
            - Path=/some/path1
            - Method=POST
          filters:
            - ModifyRequestBody:
                class: com.xyz.filters.SomeFilter
                value: application/json, application/xml
                enabled: true


Solution

  • there are few things with your code:

    1. SomeFilter class is not needed, just use the ModifyRequestBody directly from your route configuration. If you really need it to achieve something that can't be done with ModifyRequestBody, you have to make it a bean by adding @Component.
    2. The syntax for your YAML configuration is incorrect. Please refer the following revised version:
          routes:
            - id: order-route-1
              uri: http://localhost:8999/
              predicates:
                - Path=/some/path1
                - Method=POST
              filters:
                - name: ModifyRequestBody
                  args:
                    inClass: com.xyz.filters.OldType
                    outClass: com.xyz.filters.NewType
                    rewriteFunction: com.xyz.filters.MyRewriteFunction
                    contentType: application/json
    

    Let's assume that you're converting OldType to NewType, below would be the implementation for RewriteFunction:

    public class MyRewriteFunction implements RewriteFunction<OldType, NewType> {
    
        @Override
        public Publisher<NewType> apply(ServerWebExchange exchange, OldType originalRequest) {
         
            NewType modifiedRequest = modifyRequest(originalRequest);
            return Mono.just(modifiedRequest);
        }
    }