Mastering Spring Cloud Gateway ProxyExchange for MVC and WebFlux
This guide demonstrates how to use Spring Cloud Gateway's ProxyExchange utility in both Spring MVC and WebFlux applications, showing code examples for request forwarding, path extraction, header manipulation, and configuring sensitive headers.
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 supports basic downstream HTTP exchanges by mirroring HTTP verbs and, in MVC, also supports forwarding to local handlers via the forward() method. 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 trailing element 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>All MVC and WebFlux features can be used in gateway handler methods, including injecting request headers and query parameters.
Target Service Interface
<code>@RestController
@RequestMapping("/business")
public class BusinessController {
@PostMapping("/index")
public Object index(@RequestBody Map<String, Object> body) {
System.out.println("业务接口接收到的内容:" + body);
Map<String, Object> result = new HashMap<>();
result.put("code", 0);
result.put("data", "业务处理成功 - " + 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 the HTTP method call. The mapper receives the incoming ResponseEntity and returns a new one:
<code>exchange.uri("http://localhost:9000/business/index").header("key", "123123").body(body).post(result -> {
System.out.println("Resposne Header: " + result.getHeaders());
return ResponseEntity.ok("success");
});
</code>Sensitive headers (by default cookie and authorization ) and proxy headers ( x-forward-* ) are not forwarded downstream. You can override this behavior in the configuration:
<code>spring:
cloud:
gateway:
proxy:
sensitive:
- ''
</code>Result screenshots:
You can also use header() to add custom headers to the downstream response.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.