【发布时间】:2015-05-16 22:55:34
【问题描述】:
我们想创建一个简单的 JAVA 代理服务器,如果需要,它会从请求标头中收集信息。
我们已经实现了代理服务器,将浏览器指向主机和端口,我们能够毫无问题地浏览使用简单 HTTP 协议的网站。
我们支持 GET 和 HEAD HTTP 方法。
但是,使用 HTTPS 的站点会导致问题,因为这些站点会启动 CONNECT 方法,并且我们无法建立安全连接,因此我们不确定要在响应中发送什么。 (或者,如果我们能够从那时起监控更多的请求。)
有什么建议吗?任何第三方实施都可以。但我们希望在同一进程中支持 HTTP 和 HTTPS。
private void intercept() throws IOException {
final DataInputStream socketInput = new DataInputStream(this.socket.getInputStream());
final String httpMessage = RequestHeader.readHttpHeader(socketInput);
//Request header is our own convenience file with utility methods that parses the request header.
requestHeader = new RequestHeader(httpMessage);
try {
if ("GET".equals(requestHeader.getType()) || "HEAD".equals(requestHeader.getType())) {
final URL url = new URL(requestHeader.getUrl());
final HttpURLConnection connectionHttp = (HttpURLConnection) url.openConnection();
connectionHttp.setRequestMethod(requestHeader.getType());
// Send response back to client
final DataInputStream dis = new DataInputStream(connectionHttp.getInputStream());
// Add response header
final StringBuilder sb = new StringBuilder();
sb.append(requestHeader.getHttpVersion() + " " + connectionHttp.getResponseCode() + " "
+ connectionHttp.getResponseMessage() + "\r\n");
final Map<String, List<String>> map = connectionHttp.getHeaderFields();
for (final Map.Entry<String, List<String>> entry : map.entrySet()) {
final String key = entry.getKey();
sb.append(key + " : "
+ entry.getValue().toString().replace("[", "").replace("]", "").replace(",", " ") + "\r\n");
}
sb.append("\r\n");
// Add response content
final DataOutputStream socketOutput = new DataOutputStream(this.socket.getOutputStream());
socketOutput.write(sb.toString().getBytes(), 0, sb.toString().getBytes().length);
final byte[] data = new byte[(int) Short.MAX_VALUE];
int index = dis.read(data, 0, (int) Short.MAX_VALUE);
while (index != -1) {
socketOutput.write(data, 0, index);
index = dis.read(data, 0, (int) Short.MAX_VALUE);
}
socketOutput.flush();
// NOTE this works perfectly fine for HTTP sites. We can intercept the communication properly.
} else if ("CONNECT".equals(requestHeader.getType())) {
// TODO establish connection
// First line of header: CONNECT www.facebook.com:443 HTTP/1.1
// We have tried to send back 200 ok response, but no further requests were sent.
} else {
//Nothing else is supported
return;
}
} catch (final MalformedURLException e) {
System.out.print("MalformedURLException " + e.getMessage());
// return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (final IOException e) {
System.out.print("IOException " + e.getMessage());
// return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
} finally {
System.out.println("Finished.");
}
}
【问题讨论】: