Vert.x Http Proxy
Vert.x Http Proxy 是一个基于 Vert.x 的反向代理服务器,其目的是实现可重用的反向代理逻辑, 这样,使用者就可以关注更高层面的问题了
警告
|
这个模块处于 Tech Preview 阶段,这意味着在不同版本之间 API 可能会不太一样 |
使用 Vert.x Http Proxy
使用 Vert.x Http Proxy 之前,请把以下的依赖放到您的构建描述文件的 依赖 部分中
-
Maven (在您的
pom.xml
文件中):
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-http-proxy</artifactId>
<version>4.3.8</version>
</dependency>
-
Gradle (在您的
build.gradle
文件中):
dependencies {
compile 'io.vertx:vertx-http-proxy:4.3.8'
}
反向代理服务器
为了使用 Vert.x Http Proxy 实现一个反向代理,您需要了解这些名词:
-
Proxy Server 处理用户代理请求并将它们转发到 origin server
-
Origin Server 处理来自 proxy server 的请求并做出相应响应
您可以创建一个 proxy server,监听 8080
端口并实现反向代理逻辑
HttpClient proxyClient = vertx.createHttpClient();
HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
proxy.origin(7070, "origin");
HttpServer proxyServer = vertx.createHttpServer();
proxyServer.requestHandler(proxy).listen(8080);
所有的(user-agent)用户代理请求都方便地转发到 origin server 。
源服务器(Origin Server)路由
您可以创建一个代理,将所有流量转发到单个服务器,如前所述。
您可以设置源选择器(Origin Selector)以将流量路由到指定的服务器。
proxy.originSelector(request -> Future.succeededFuture(resolveOriginAddress(request)));
您可以设置一个函数来创建对源服务器的客户端请求,以实现最大的灵活性。
proxy.originRequestProvider((request, client) -> client.request(resolveOriginOptions(request)));
头部转发
端到端的头部会被代理转发,而逐跳(hop-by-hop)头部会被忽略。
请求校验
作为一种透明代理,请求中的请求权限信息 (HTTP/1.1 协议的 {@code Host} 标头,HTTP/2 协议的 {@code :authority} 伪标头),会被代理保留。
您也可以重写请求权限信息。
proxy.addInterceptor(new ProxyInterceptor() {
@Override
public Future<ProxyResponse> handleProxyRequest(ProxyContext context) {
ProxyRequest proxyRequest = context.request();
proxyRequest.setAuthority("example.com:80");
return ProxyInterceptor.super.handleProxyRequest(context);
}
});
当请求权限信息被重写时,在对源服务器的请求上会设置 {@code x-forwarded-host} 头部,其值为 原始的权限信息。
警告
|
更改请求权限信息可能会产生不良的副作用,并可能影响代理的 Web 服务器,因为其可能 依赖原始的请求权限信息来处理 Cookie、URL 重定向等操作。 |
WebSockets
该 HTTP 代理默认支持 WebSocket 协议。
WebSocket 的握手请求会被转发到源服务器 (包含 connection
头部) ,并且用户端
和源服务器间会发生握手。
您可以通过 setSupportWebSocket
方法来设置其是否支持 WebSocket 协议。
代理缓存
大部分情况下,代理不会缓存响应内容,并且会忽视大部分的缓存指令,您也可以使用缓存选项来开启缓存。
HttpProxy proxy = HttpProxy.reverseProxy(new ProxyOptions().setCacheOptions(new CacheOptions()), proxyClient);
代理拦截
拦截是使用新功能扩展代理的强大方法。
您可以实现 handleProxyRequest
对代理请求执行的任何操作
proxy.addInterceptor(new ProxyInterceptor() {
@Override
public Future<ProxyResponse> handleProxyRequest(ProxyContext context) {
ProxyRequest proxyRequest = context.request();
filter(proxyRequest.headers());
// 继续拦截链
return context.sendRequest();
}
});
代理响应也是如此
proxy.addInterceptor(new ProxyInterceptor() {
@Override
public Future<Void> handleProxyResponse(ProxyContext context) {
ProxyResponse proxyResponse = context.response();
filter(proxyResponse.headers());
// 继续拦截链
return context.sendResponse();
}
});
Body 过滤
您可以简单地用一个新的 Body 替换原来的 Body
来过滤body
proxy.addInterceptor(new ProxyInterceptor() {
@Override
public Future<Void> handleProxyResponse(ProxyContext context) {
ProxyResponse proxyResponse = context.response();
// 创建一个Body
Body filteredBody = filter(proxyResponse.getBody());
// 然后使用它
proxyResponse.setBody(filteredBody);
// 继续拦截链
return context.sendResponse();
}
});
拦截控制
sendRequest
和 sendResponse
继续当前拦截链,然后将结果发到(origin server)源服务器或者(user-agent)用户代理。
您可以更改控制器, 例如, 您可以立即向用户代理(user-agent)发送响应,而无需请求源服务器(origin server)
proxy.addInterceptor(new ProxyInterceptor() {
@Override
public Future<ProxyResponse> handleProxyRequest(ProxyContext context) {
ProxyRequest proxyRequest = context.request();
// 释放资源
proxyRequest.release();
// 创建一个响应并设置参数
ProxyResponse proxyResponse = proxyRequest.response()
.setStatusCode(200)
.putHeader("content-type", "text/plain")
.setBody(Body.body(Buffer.buffer("Hello World")));
return Future.succeededFuture(proxyResponse);
}
});