Backend Development 5 min read

How to Use Spring Cloud Gateway’s ProxyExchange for MVC and WebFlux Proxies

This guide demonstrates how to leverage Spring Cloud Gateway's ProxyExchange utility in both Spring MVC and WebFlux applications, showing code examples for proxying requests, extracting path variables, adding headers, handling responses, and configuring sensitive headers.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Use Spring Cloud Gateway’s ProxyExchange for MVC and WebFlux Proxies

Environment: SpringBoot 2.5.13.

Spring Cloud Gateway provides a utility object called ProxyExchange that can be used as a method parameter in regular Spring web handlers. It mirrors HTTP verbs for downstream exchanges and, in MVC, also supports forwarding to local handlers via forward() . To use ProxyExchange , include the appropriate module on the classpath: spring-cloud-gateway-mvc (3.1.5) or spring-cloud-gateway-webflux .

MVC Example

<code>@RestController
@SpringBootApplication
public class GatewaySampleApplication {

    @Value("${remote.home}")
    private URI home;

    @GetMapping("/test")
    public ResponseEntity<?> proxy(ProxyExchange<byte[]> proxy) throws Exception {
        return proxy.uri(home.toString() + "/image/png").get();
    }
}
</code>

WebFlux Example

<code>@RestController
@SpringBootApplication
public class GatewaySampleApplication {

    @Value("${remote.home}")
    private URI home;

    @GetMapping("/test")
    public Mono<ResponseEntity<?>> proxy(ProxyExchange<byte[]> proxy) throws Exception {
        return proxy.uri(home.toString() + "/image/png").get();
    }
}
</code>

The convenience methods on ProxyExchange let handler methods discover and enhance the incoming request URI path. For example, you can extract the tail of a path and forward it downstream:

<code>@GetMapping("/proxy/path/**")
public ResponseEntity<?> proxyPath(ProxyExchange<byte[]> proxy) throws Exception {
    // If the request is /proxy/path/666, then path = 666
    String path = proxy.path("/proxy/path/");
    return proxy.uri(home.toString() + "/foos/" + path).get();
}
</code>

Target Service Interface

<code>@RestController
@RequestMapping("/business")
public class BusinessController {

    @PostMapping("/index")
    public Object index(@RequestBody Map<String, Object> body) {
        System.out.println("Received payload: " + body);
        Map<String, Object> result = new HashMap<>();
        result.put("code", 0);
        result.put("data", "Business processed - " + LocalDateTime.now().getNano());
        result.put("message", "success");
        return result;
    }
}
</code>

Gateway Service Interface

<code>@RestController
@RequestMapping("/proxy/api")
public class GatewayController {

    @GetMapping("")
    public Object order(@RequestHeader("token") String token,
                        Integer id,
                        ProxyExchange<Map<String, Object>> exchange) {
        System.out.println("token = " + token + ", id = " + id);
        Map<String, Object> body = new HashMap<>();
        body.put("id", id);
        body.put("token", token);
        return exchange.uri("http://localhost:9000/business/index").body(body).post();
    }
}
</code>

You can also add headers to the downstream request using the header() method:

<code>exchange.uri("http://localhost:9000/business/index")
        .header("key", "123123")
        .body(body)
        .post();
</code>

To manipulate the response, provide a mapper function to post() (or other HTTP methods). The mapper receives the inbound ResponseEntity and returns a new one:

<code>exchange.uri("http://localhost:9000/business/index")
        .header("key", "123123")
        .body(body)
        .post(result -> {
            System.out.println("Response Header: " + result.getHeaders());
            return ResponseEntity.ok("success");
        });
</code>

Sensitive headers such as cookie and authorization , as well as proxy headers (e.g., x-forward-* ), are not forwarded downstream by default. This behavior can be overridden in the configuration:

<code>spring:
  cloud:
    gateway:
      proxy:
        sensitive:
          - ''
</code>

Result screenshots:

Postman request

Console output

End of tutorial.

backendJavaSpring BootSpring Cloud Gatewayproxyexchange
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.