Skip to content

Commit fb8287a

Browse files
committed
feat: 初步实现HTTP代理的方法定义
1 parent f6921cf commit fb8287a

File tree

3 files changed

+150
-10
lines changed

3 files changed

+150
-10
lines changed

src/main/java/top/meethigher/proxy/http/ProxyRoute.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package top.meethigher.proxy.http;
22

3+
import java.net.URL;
4+
35
/**
46
* 服务信息
57
*
@@ -157,11 +159,50 @@ public void setLog(LOG log) {
157159
this.log = log;
158160
}
159161

162+
public boolean isEnable() {
163+
return enable;
164+
}
165+
166+
public void setEnable(boolean enable) {
167+
this.enable = enable;
168+
}
169+
160170
public CORSControl getCorsControl() {
161171
return corsControl;
162172
}
163173

164174
public void setCorsControl(CORSControl corsControl) {
165175
this.corsControl = corsControl;
166176
}
177+
178+
public String[] formatTargetUrl() throws IllegalArgumentException {
179+
try {
180+
URL url = new URL(targetUrl);
181+
String protocol = url.getProtocol();
182+
if (protocol == null || protocol.isEmpty()) {
183+
throw new IllegalArgumentException("Invalid URL: Protocol is missing");
184+
}
185+
String host = url.getHost();
186+
if (host == null || host.isEmpty()) {
187+
throw new IllegalArgumentException("Invalid URL: Host is missing");
188+
}
189+
int port = url.getPort() != -1 ? url.getPort() : url.getDefaultPort();
190+
if (port == -1) { // 如果协议未提供默认端口,则认为无效
191+
throw new IllegalArgumentException("Invalid URL: Port is missing");
192+
}
193+
String requestURI = url.getPath();
194+
if (requestURI == null || requestURI.isEmpty()) {
195+
requestURI = "/";
196+
}
197+
return new String[]{
198+
protocol,
199+
host,
200+
String.valueOf(port),
201+
requestURI
202+
};
203+
} catch (Exception e) {
204+
throw new IllegalArgumentException("Invalid URL format: " + targetUrl, e);
205+
}
206+
}
207+
167208
}

src/main/java/top/meethigher/proxy/http/VertxHTTPReverseProxy.java

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
import io.vertx.core.http.HttpClient;
88
import io.vertx.core.http.HttpServer;
99
import io.vertx.core.http.HttpServerRequest;
10+
import io.vertx.core.http.RequestOptions;
1011
import io.vertx.ext.web.Route;
1112
import io.vertx.ext.web.Router;
1213
import io.vertx.ext.web.RoutingContext;
1314
import org.slf4j.Logger;
1415
import org.slf4j.LoggerFactory;
1516

17+
import java.util.ArrayList;
1618
import java.util.List;
1719
import java.util.concurrent.ThreadLocalRandom;
1820

@@ -94,25 +96,76 @@ public class VertxHTTPReverseProxy {
9496
private final HttpServer httpServer;
9597
private final HttpClient httpClient;
9698
private final String name;
99+
private final String P_METADATA_CONFIG = "cfg";
100+
private final String P_STATE = "state";
97101

98102
private VertxHTTPReverseProxy(Router router, HttpServer httpServer, HttpClient httpClient, String name) {
99103
this.router = router;
100104
this.httpServer = httpServer;
101105
this.httpClient = httpClient;
102106
this.name = name;
103107
this.routingContextHandler = ctx -> {
108+
Route route = ctx.currentRoute();
109+
ProxyRoute proxyRoute = getProxyRoute(route);
110+
String[] formatTargetUrl;
111+
try {
112+
formatTargetUrl = proxyRoute.formatTargetUrl();
113+
} catch (Exception e) {
114+
ctx.response().setStatusCode(400).end(e.getMessage());
115+
return;
116+
}
104117
HttpServerRequest request = ctx.request();
105118
String uri = request.uri();
106-
Route route = ctx.currentRoute();
107119
String path;
108120
if (route.getPath().endsWith("/")) {
109121
path = uri.substring(route.getPath().length() - 1);
110122
} else {
111123
path = uri.substring(route.getPath().length());
112124
}
125+
RequestOptions requestOptions = new RequestOptions()
126+
.setSsl("https".equalsIgnoreCase(formatTargetUrl[0]))
127+
.setHost(formatTargetUrl[1])
128+
.setPort(Integer.valueOf(formatTargetUrl[2]))
129+
.setURI(joinURI(formatTargetUrl[3], path));
130+
System.out.println(requestOptions.getURI());
131+
httpClient.request(requestOptions)
132+
.onFailure(e -> {
133+
ctx.response().setStatusCode(502).end(e.getMessage());
134+
})
135+
.onSuccess(r -> {
136+
r.headers().setAll(request.headers());
137+
r.putHeader("Host", "reqres.in");
138+
r.send()
139+
.onSuccess(r1 -> {
140+
ctx.response()
141+
.setStatusCode(r1.statusCode())
142+
.headers().setAll(r1.headers());
143+
r1.handler(data -> {
144+
ctx.response().write(data);
145+
});
146+
r1.endHandler(v -> ctx.response().end());
147+
148+
})
149+
.onFailure(e1 -> {
150+
ctx.response().setStatusCode(500).end(e1.getMessage());
151+
});
152+
});
113153
};
114154
}
115155

156+
private static String joinURI(String uri1, String uri2) {
157+
if (uri1.endsWith("/") && uri2.startsWith("/")) {
158+
// 两边都有 '/'
159+
return uri1 + uri2.substring(1);
160+
} else if (!uri1.endsWith("/") && !uri2.startsWith("/")) {
161+
// 两边都没有 '/'
162+
return uri1 + "/" + uri2;
163+
} else {
164+
// 只有一个有 '/'
165+
return uri1 + uri2;
166+
}
167+
}
168+
116169

117170
public static VertxHTTPReverseProxy create(Vertx vertx, String name) {
118171
return new VertxHTTPReverseProxy(Router.router(vertx), vertx.createHttpServer(), vertx.createHttpClient(), name);
@@ -150,40 +203,86 @@ private static String generateName() {
150203
}
151204
}
152205

206+
public boolean enabled(String name) {
207+
for (Route route : router.getRoutes()) {
208+
ProxyRoute proxyRoute = getProxyRoute(route);
209+
if (name.equals(proxyRoute.getName())) {
210+
return route.getMetadata(P_STATE);
211+
}
212+
}
213+
return false;
214+
}
215+
216+
private ProxyRoute getProxyRoute(Route route) {
217+
return route.getMetadata(P_METADATA_CONFIG);
218+
}
219+
153220

154221
/**
155222
* 添加ProxyRoute
156223
*/
157224
public void addRoute(ProxyRoute proxyRoute) {
158-
225+
router.route(proxyRoute.getSourceUrl())
226+
.putMetadata(P_STATE, true)
227+
.putMetadata(P_METADATA_CONFIG, proxyRoute)
228+
.handler(routingContextHandler);
159229
}
160230

161231
/**
162232
* 删除ProxyRout,并将删除后的ProxyRout返回
163233
*/
164234
public ProxyRoute removeRoute(String name) {
235+
for (Route route : router.getRoutes()) {
236+
ProxyRoute proxyRoute = getProxyRoute(route);
237+
if (name.equals(proxyRoute.getName())) {
238+
route.remove();
239+
return proxyRoute;
240+
}
241+
}
165242
return null;
166243
}
167244

168245
/**
169246
* 启用ProxyRout,并将启用后的ProxyRout返回
170247
*/
171248
public ProxyRoute enableRoute(String name) {
249+
for (Route route : router.getRoutes()) {
250+
ProxyRoute proxyRoute = getProxyRoute(route);
251+
if (name.equals(proxyRoute.getName())) {
252+
route.enable();
253+
route.putMetadata(P_STATE, true);
254+
return proxyRoute;
255+
}
256+
}
172257
return null;
173258
}
174259

175260
/**
176261
* 停用ProxyRout,并将停用后的ProxyRout返回
177262
*/
178263
public ProxyRoute disableRoute(String name) {
264+
for (Route route : router.getRoutes()) {
265+
ProxyRoute proxyRoute = getProxyRoute(route);
266+
if (name.equals(proxyRoute.getName())) {
267+
route.disable();
268+
route.putMetadata(P_STATE, false);
269+
return proxyRoute;
270+
}
271+
}
179272
return null;
180273
}
181274

182275
/**
183276
* 获取当前所有ProxyRout
184277
*/
185278
public List<ProxyRoute> getRoutes() {
186-
return null;
279+
List<ProxyRoute> proxyRoutes = new ArrayList<>();
280+
for (Route route : router.getRoutes()) {
281+
ProxyRoute proxyRoute = getProxyRoute(route);
282+
proxyRoute.setEnable(route.getMetadata(P_STATE));
283+
proxyRoutes.add(proxyRoute);
284+
}
285+
return proxyRoutes;
187286
}
188287

189288
public void start() {

src/test/java/top/meethigher/VertxHTTPReverseProxyTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.vertx.core.Vertx;
44
import org.junit.Test;
5+
import top.meethigher.proxy.http.ProxyRoute;
56
import top.meethigher.proxy.http.VertxHTTPReverseProxy;
67

78
import java.util.concurrent.TimeUnit;
@@ -11,14 +12,13 @@ public class VertxHTTPReverseProxyTest {
1112
@Test
1213
public void testVertxHTTPReverseProxyTest() throws Exception {
1314
VertxHTTPReverseProxy proxy = VertxHTTPReverseProxy.create(Vertx.vertx());
14-
proxy.addRoute(null);
15-
proxy.removeRoute(null);
16-
proxy.getRoutes();
17-
proxy.enableRoute(null);
18-
proxy.disableRoute(null);
19-
proxy.start();
2015

21-
TimeUnit.SECONDS.sleep(20);
16+
proxy.start();
17+
ProxyRoute proxyRoute = new ProxyRoute();
18+
proxyRoute.setSourceUrl("/api/*");
19+
proxyRoute.setTargetUrl("https://reqres.in/");
20+
proxy.addRoute(proxyRoute);
21+
TimeUnit.MINUTES.sleep(20);
2222
proxy.stop();
2323
}
2424

0 commit comments

Comments
 (0)