Skip to content

Commit 6fb3617

Browse files
committedSep 26, 2018
[#1] Support websocket proxy
1 parent 650bb73 commit 6fb3617

18 files changed

+886
-243
lines changed
 

‎README.md

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
# ZeroProxy is a multi purpose http proxy.
2-
* Support http(https) proxy
3-
* Support websocket proxy (Not yet)
4-
* Support multiple targets
1+
# ZeroProxy is a multi target http/websocket proxy.
2+
* Support http/https proxy
3+
* Support ws/wss proxy
4+
* Response use json for multiple requests.
5+
* Used json for responding of multiple requests
56

6-
[![Build Status](https://travis-ci.org/code13k/zeroproxy.svg?branch=master)](https://travis-ci.org/code13k/zeroproxy)
77

8+
[![Build Status](https://travis-ci.org/code13k/zeroproxy.svg?branch=master)](https://travis-ci.org/code13k/zeroproxy)
89

9-
# Supported protocol
10-
* http / https
11-
* ws / wss (Not yet)
1210

1311

1412
# Configuration
@@ -23,43 +21,39 @@ port:
2321
api_http: 55552
2422
```
2523
26-
## proxy_config.yml
27-
It's proxy configuration file.
24+
## proxy_http_config.yml
25+
It's proxy http configuration file.
2826
```yaml
2927
# Example-1
30-
- location: /zeroproxy_example
31-
type: round-robin
28+
- location: /helios_pub
3229
connect_timeout: 3000
3330
idle_timeout: 3000
3431
targets:
35-
- http://1.1.1.1:3000
32+
- http://127.0.0.1:55402
3633

3734
# Example-2
38-
- location: /zeroproxy/example
39-
type: random
35+
- location: /helios_api
4036
connect_timeout: 3000
4137
idle_timeout: 3000
4238
targets:
43-
- http://1.1.1.1:3000
44-
- http://1.1.1.1:3001
39+
- http://127.0.0.1:55403
40+
- http://127.0.0.1:55403
4541

4642
# Example-3
47-
- location: /zeroproxy/example/1
48-
type: all
43+
- location: /thumbly_api
4944
connect_timeout: 3000
5045
idle_timeout: 3000
5146
targets:
52-
- http://1.1.1.1:3000
53-
- http://1.1.1.1:3001
54-
- http://1.1.1.1:3002
47+
- http://127.0.0.1:57911
48+
```
5549
56-
# Example-4
57-
- location: /
58-
type: round-robin
59-
connect_timeout: 3000
60-
idle_timeout: 3000
50+
## proxy_ws_config.yml
51+
It's proxy websocket configuration file.
52+
```yaml
53+
# Example-1
54+
- location: /helios_pub
6155
targets:
62-
- http://1.1.1.1:3000
56+
- ws://127.0.0.1:55401
6357
```
6458
6559
## logback.xml

‎src/main/java/org/code13k/zeroproxy/Main.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
import io.vertx.core.DeploymentOptions;
44
import io.vertx.core.Vertx;
55
import org.code13k.zeroproxy.business.proxy.http.ProxyHttpManager;
6+
import org.code13k.zeroproxy.business.proxy.ws.ProxyWsManager;
67
import org.code13k.zeroproxy.config.AppConfig;
78
import org.code13k.zeroproxy.config.LogConfig;
8-
import org.code13k.zeroproxy.config.ProxyConfig;
9+
import org.code13k.zeroproxy.config.ProxyHttpConfig;
910
import org.code13k.zeroproxy.app.Env;
1011
import org.code13k.zeroproxy.app.Status;
12+
import org.code13k.zeroproxy.config.ProxyWsConfig;
1113
import org.code13k.zeroproxy.service.api.ApiHttpServer;
1214
import org.code13k.zeroproxy.service.proxy.ProxyHttpServer;
15+
import org.code13k.zeroproxy.service.proxy.ProxyWsServer;
1316
import org.slf4j.Logger;
1417
import org.slf4j.LoggerFactory;
1518

@@ -69,13 +72,15 @@ public static void main(String[] args) {
6972
try {
7073
LogConfig.getInstance().init();
7174
AppConfig.getInstance().init();
72-
ProxyConfig.getInstance().init();
75+
ProxyHttpConfig.getInstance().init();
76+
ProxyWsConfig.getInstance().init();
7377
Env.getInstance().init();
7478
Status.getInstance().init();
7579
ProxyHttpManager.getInstance().init();
80+
ProxyWsManager.getInstance().init();
7681
} catch (Exception e) {
7782
mLogger.error("Failed to initialize", e);
78-
return;
83+
System.exit(1);
7984
}
8085

8186
// Deploy ProxyHttpServer
@@ -86,7 +91,18 @@ public static void main(String[] args) {
8691
Thread.sleep(1000);
8792
} catch (Exception e) {
8893
mLogger.error("Failed to deploy ProxyHttpServer", e);
89-
return;
94+
System.exit(2);
95+
}
96+
97+
// Deploy ProxyWsServer
98+
try {
99+
DeploymentOptions options = new DeploymentOptions();
100+
options.setInstances(Math.max(1, Env.getInstance().getProcessorCount() / 2));
101+
Vertx.vertx().deployVerticle(ProxyWsServer.class.getName(), options);
102+
Thread.sleep(1000);
103+
} catch (Exception e) {
104+
mLogger.error("Failed to deploy ProxyWsServer", e);
105+
System.exit(3);
90106
}
91107

92108
// Deploy APIHttpServer
@@ -97,7 +113,7 @@ public static void main(String[] args) {
97113
Thread.sleep(1000);
98114
} catch (Exception e) {
99115
mLogger.error("Failed to deploy ApiHttpServer", e);
100-
return;
116+
System.exit(4);
101117
}
102118

103119
// End

‎src/main/java/org/code13k/zeroproxy/app/Status.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.code13k.zeroproxy.app;
22

33
import org.code13k.zeroproxy.business.proxy.http.ProxyHttpManager;
4+
import org.code13k.zeroproxy.business.proxy.ws.ProxyWsManager;
45
import org.slf4j.Logger;
56
import org.slf4j.LoggerFactory;
67

@@ -42,7 +43,7 @@ private Status() {
4243
*/
4344
public void init() {
4445
// Timer
45-
Timer timer = new Timer("perri-status-logging");
46+
Timer timer = new Timer("zeroproxy-status");
4647
timer.schedule(new TimerTask() {
4748
@Override
4849
public void run() {
@@ -67,6 +68,12 @@ public void logging() {
6768
// Processed count (HTTP Proxy)
6869
sb.append(", ProxyHttpCount=" + ProxyHttpManager.getInstance().getProcessedCount());
6970

71+
// Connected count (WS Proxy)
72+
sb.append(", ProxyWsConnectedCount=" + ProxyWsManager.getInstance().getConnectedCount());
73+
74+
// Sent text count (WS Proxy)
75+
sb.append(", ProxyWsSentTextCount=" + ProxyWsManager.getInstance().getSentTextCount());
76+
7077
// End
7178
mLogger.info(sb.toString());
7279
}

‎src/main/java/org/code13k/zeroproxy/business/proxy/http/ProxyHttpClient.java

Lines changed: 35 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
import io.vertx.ext.web.client.WebClientOptions;
1212
import org.apache.commons.lang3.StringUtils;
1313
import org.code13k.zeroproxy.app.Env;
14-
import org.code13k.zeroproxy.config.ProxyConfig;
15-
import org.code13k.zeroproxy.model.ProxyResponse;
16-
import org.code13k.zeroproxy.model.config.proxy.ProxyInfo;
14+
import org.code13k.zeroproxy.model.ProxyHttpResponse;
15+
import org.code13k.zeroproxy.model.config.proxy.ProxyHttpInfo;
1716
import org.slf4j.Logger;
1817
import org.slf4j.LoggerFactory;
1918

@@ -30,15 +29,14 @@ public class ProxyHttpClient {
3029

3130
// Data
3231
private WebClient mWebClient;
33-
private ProxyInfo mProxyInfo;
34-
private int mRoundRobinIndex = 0;
32+
private ProxyHttpInfo mProxyHttpInfo;
3533

3634
/**
3735
* Constructor
3836
*/
39-
public ProxyHttpClient(ProxyInfo proxyInfo, int eventLoopPoolSize) {
40-
mProxyInfo = proxyInfo;
41-
mLogger.trace("ProxyHttpClient() # " + mProxyInfo);
37+
public ProxyHttpClient(ProxyHttpInfo proxyHttpInfo, int eventLoopPoolSize) {
38+
mProxyHttpInfo = proxyHttpInfo;
39+
mLogger.trace("ProxyHttpClient() # " + mProxyHttpInfo);
4240

4341
// Set user-agent
4442
String userAgent = "Code13k-ZeroProxy/" + Env.getInstance().getVersionString();
@@ -50,8 +48,8 @@ public ProxyHttpClient(ProxyInfo proxyInfo, int eventLoopPoolSize) {
5048
webClientOptions.setTrustAll(true);
5149
webClientOptions.setSsl(true);
5250
webClientOptions.setTryUseCompression(true);
53-
webClientOptions.setConnectTimeout(mProxyInfo.getConnectTimeout());
54-
webClientOptions.setIdleTimeout(mProxyInfo.getIdleTimeout());
51+
webClientOptions.setConnectTimeout(mProxyHttpInfo.getConnectTimeout());
52+
webClientOptions.setIdleTimeout(mProxyHttpInfo.getIdleTimeout());
5553

5654
// Init VertxOptions
5755
VertxOptions vertxOptions = new VertxOptions();
@@ -64,7 +62,7 @@ public ProxyHttpClient(ProxyInfo proxyInfo, int eventLoopPoolSize) {
6462
/**
6563
* Proxy
6664
*/
67-
public void proxy(String originPath, HttpMethod originMethod, MultiMap originHeaders, Buffer originBody, Consumer<ProxyResponse> consumer) {
65+
public void proxy(String originPath, HttpMethod originMethod, MultiMap originHeaders, Buffer originBody, Consumer<ProxyHttpResponse> consumer) {
6866
// Headers
6967
final MultiMap headers = MultiMap.caseInsensitiveMultiMap();
7068
headers.addAll(originHeaders);
@@ -87,55 +85,31 @@ public void proxy(String originPath, HttpMethod originMethod, MultiMap originHea
8785
requestTarget(uri, method, headers, body, new Consumer<HttpResponse<Buffer>>() {
8886
@Override
8987
public void accept(HttpResponse<Buffer> response) {
90-
/**
91-
* Multiple Request
92-
*/
93-
if (ProxyConfig.isMultipleRequest(mProxyInfo) == true) {
94-
Map<String, Object> resultItem = new HashMap<>();
95-
if (response == null) {
96-
resultItem.put("uri", uri);
97-
resultItem.put("statusCode", 504);
98-
resultItem.put("statusMessage", "Gateway Time-out");
99-
resultItem.put("headers", makeDefaultHeaders());
100-
resultItem.put("body", "");
101-
} else {
102-
resultItem.put("uri", uri);
103-
resultItem.put("statusCode", response.statusCode());
104-
resultItem.put("statusMessage", response.statusMessage());
105-
resultItem.put("headers", convertHeaders(response.headers()));
106-
resultItem.put("body", response.bodyAsString());
107-
}
108-
result.add(resultItem);
109-
110-
// END
111-
if (processingCount.decrementAndGet() == 0) {
112-
Buffer proxyBody = Buffer.buffer(new GsonBuilder().create().toJson(result));
113-
ProxyResponse proxyResponse = new ProxyResponse();
114-
proxyResponse.setStatusCode(200);
115-
proxyResponse.setStatusMessage("OK");
116-
proxyResponse.setHeaders(makeProxyResponseHeaders());
117-
proxyResponse.setBody(proxyBody);
118-
consumer.accept(proxyResponse);
119-
}
88+
Map<String, Object> resultItem = new HashMap<>();
89+
if (response == null) {
90+
resultItem.put("uri", uri);
91+
resultItem.put("statusCode", 504);
92+
resultItem.put("statusMessage", "Gateway Time-out");
93+
resultItem.put("headers", makeDefaultHeaders());
94+
resultItem.put("body", "");
95+
} else {
96+
resultItem.put("uri", uri);
97+
resultItem.put("statusCode", response.statusCode());
98+
resultItem.put("statusMessage", response.statusMessage());
99+
resultItem.put("headers", convertHeaders(response.headers()));
100+
resultItem.put("body", response.bodyAsString());
120101
}
121-
122-
/**
123-
* Single Request
124-
*/
125-
else {
126-
ProxyResponse proxyResponse = new ProxyResponse();
127-
if (response == null) {
128-
proxyResponse.setStatusCode(504);
129-
proxyResponse.setStatusMessage("Gateway Time-out");
130-
proxyResponse.setHeaders(makeDefaultHeaders());
131-
proxyResponse.setBody(null);
132-
} else {
133-
proxyResponse.setStatusCode(response.statusCode());
134-
proxyResponse.setStatusMessage(response.statusMessage());
135-
proxyResponse.setHeaders(response.headers());
136-
proxyResponse.setBody(response.body());
137-
}
138-
consumer.accept(proxyResponse);
102+
result.add(resultItem);
103+
104+
// END
105+
if (processingCount.decrementAndGet() == 0) {
106+
Buffer proxyBody = Buffer.buffer(new GsonBuilder().create().toJson(result));
107+
ProxyHttpResponse proxyHttpResponse = new ProxyHttpResponse();
108+
proxyHttpResponse.setStatusCode(200);
109+
proxyHttpResponse.setStatusMessage("OK");
110+
proxyHttpResponse.setHeaders(makeProxyResponseHeaders());
111+
proxyHttpResponse.setBody(proxyBody);
112+
consumer.accept(proxyHttpResponse);
139113
}
140114
}
141115
});
@@ -179,21 +153,11 @@ private MultiMap makeProxyResponseHeaders() {
179153
private ArrayList<String> getTargetURI(String originPath) {
180154
ArrayList<String> result = new ArrayList<>();
181155
ArrayList<String> uriList = new ArrayList<>();
182-
mProxyInfo.getTargets().forEach(targetBaseUri -> {
156+
mProxyHttpInfo.getTargets().forEach(targetBaseUri -> {
183157
String uri = targetBaseUri + "/" + originPath;
184158
uriList.add(uri);
185159
});
186-
if (mProxyInfo.getType().equalsIgnoreCase(ProxyConfig.ChannelType.ROUND_ROBIN)) {
187-
String uri = uriList.get(mRoundRobinIndex);
188-
mRoundRobinIndex = (mRoundRobinIndex + 1) % mProxyInfo.getTargets().size();
189-
result.add(uri);
190-
} else if (mProxyInfo.getType().equalsIgnoreCase(ProxyConfig.ChannelType.RANDOM)) {
191-
int index = (int) (System.nanoTime() % mProxyInfo.getTargets().size());
192-
mLogger.trace("index = " + index);
193-
result.add(mProxyInfo.getTargets().get(index));
194-
} else if (mProxyInfo.getType().equalsIgnoreCase(ProxyConfig.ChannelType.ALL)) {
195-
result.addAll(uriList);
196-
}
160+
result.addAll(uriList);
197161
return result;
198162
}
199163

‎src/main/java/org/code13k/zeroproxy/business/proxy/http/ProxyHttpManager.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import io.vertx.core.buffer.Buffer;
66
import io.vertx.core.http.HttpMethod;
77
import org.code13k.zeroproxy.app.Env;
8-
import org.code13k.zeroproxy.config.ProxyConfig;
9-
import org.code13k.zeroproxy.model.ProxyResponse;
10-
import org.code13k.zeroproxy.model.config.proxy.ProxyInfo;
8+
import org.code13k.zeroproxy.config.ProxyHttpConfig;
9+
import org.code13k.zeroproxy.model.ProxyHttpResponse;
10+
import org.code13k.zeroproxy.model.config.proxy.ProxyHttpInfo;
1111
import org.slf4j.Logger;
1212
import org.slf4j.LoggerFactory;
1313

@@ -50,7 +50,7 @@ synchronized public void init() {
5050

5151
// Data
5252
mData = new ArrayList<>();
53-
ArrayList<ProxyInfo> channelList = ProxyConfig.getInstance().getChannelList();
53+
ArrayList<ProxyHttpInfo> channelList = ProxyHttpConfig.getInstance().getChannelList();
5454
channelList.forEach(channel -> {
5555
ProxyHttpClient client = new ProxyHttpClient(channel, eventLoopPoolSize);
5656
mData.add(client);
@@ -63,13 +63,13 @@ synchronized public void init() {
6363
/**
6464
* Proxy
6565
*/
66-
public void proxy(int channelIndex, String originPath, HttpMethod originMethod, MultiMap originHeaders, Buffer originBody, Consumer<ProxyResponse> consumer) {
66+
public void proxy(int channelIndex, String originPath, HttpMethod originMethod, MultiMap originHeaders, Buffer originBody, Consumer<ProxyHttpResponse> consumer) {
6767
ProxyHttpClient client = mData.get(channelIndex);
68-
client.proxy(originPath, originMethod, originHeaders, originBody, new Consumer<ProxyResponse>() {
68+
client.proxy(originPath, originMethod, originHeaders, originBody, new Consumer<ProxyHttpResponse>() {
6969
@Override
70-
public void accept(ProxyResponse proxyResponse) {
70+
public void accept(ProxyHttpResponse proxyHttpResponse) {
7171
mLogger.trace("Proxy : OK");
72-
consumer.accept(proxyResponse);
72+
consumer.accept(proxyHttpResponse);
7373
mProcessedCount++;
7474
}
7575
});

0 commit comments

Comments
 (0)