使用 Spring MVC 或 Webflux 的代理交换网关

以下描述了一种替代风格的网关。接下来的内容不适用于 Spring Cloud Gateway Server 文档中的任何部分。

如何引入 Spring Cloud Gateway Proxy Exchange

要在项目中引入 Spring Cloud Gateway Proxy Exchange,对于 MVC 代理交换,请使用 group ID 为 org.springframework.cloud、artifact ID 为 spring-cloud-gateway-mvc 的依赖。对于 WebFlux 代理交换,请使用 group ID 为 org.springframework.cloud、artifact ID 为 spring-cloud-gateway-webflux 的依赖。

有关使用当前 Spring Cloud Release Train 设置构建系统的详细信息,请参阅 Spring Cloud 项目页面

使用 Proxy Exchange

Spring Cloud Gateway 提供了一个名为 ProxyExchange 的工具对象。您可以在常规 Spring web 处理器中将其用作方法参数。它通过镜像 HTTP 动词的方法支持基本的下游 HTTP 交换。对于 MVC,它还通过 forward() 方法支持转发到本地处理器。要使用 ProxyExchange,请在您的 classpath 中包含正确的模块(spring-cloud-gateway-mvcspring-cloud-gateway-webflux)。

以下 MVC 示例将发往 /test 的请求代理到下游的远程服务器

@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();
	}

}

以下示例使用 Webflux 实现相同的功能

@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();
	}

}

ProxyExchange 上的便利方法使处理器方法能够发现和增强传入请求的 URI 路径。例如,您可能需要提取路径的尾部元素以便向下游传递

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

Spring MVC 和 Webflux 的所有功能都可供网关处理器方法使用。因此,您可以注入请求头和查询参数等,并且可以通过映射注解中的声明来限制传入请求。有关这些功能的更多详细信息,请参阅 Spring MVC 中关于 @RequestMapping 的文档。

您可以使用 ProxyExchange 上的 header() 方法向下游响应添加头。

您还可以通过向 get() 方法(以及其他方法)添加映射器来操作响应头(以及响应中您喜欢的任何其他内容)。映射器是一个 Function,它接收传入的 ResponseEntity 并将其转换为传出的响应。

对“敏感”头(默认为 cookieauthorization)和“跳过”头(默认为 content-lengthhost)提供了一流的支持,这些头不会向下游传递;对于“代理”头(x-forwarded-*)也提供了支持。“跳过”头的理念是,当它们被复制到下游请求时可能会导致问题。例如:由于 ProxyExchange 调用下游端点的方式,内容的长度可能已经改变,甚至可能使用 Transfer-Encoding: chunked 而不是 Content-Length 头。