上一篇实现了中间人代理Http服务,接下来完成隧道方式代理Https请求。
写在前面
- HTTP 代理原理及实现
- 目标是通过中间人代理的方式代理普通Http请求, 使用隧道代理方式代理Https请求。
思考
- 本文考虑隧道代理方式
- 明白了原理,隧道代理方式其实比前者更加简单。
- 通俗来说,我收到了connect连接请求,根据这个请求建立对服务器的TCP连接,然后回复客户端OK。
- 然后啥事不用管,客户端数据来了转发服务器,服务器数据来了转发客户端。
实现
其实明白了原理,似乎也没啥好bb的。。
创建到服务器的TCP连接,打开面向服务器的监听线程,专用于转发数据给客户端
private void connecToServer(HttpRequest httpRequest) throws IOException {
//默认ip:port参数
String dstIp = httpRequest.host;
int dstPort = 80;
// connect方法, 从首行url获取目的参数
if (httpRequest.method.toLowerCase().equals("connect")) {
dstPort = 443;
dstIp = httpRequest.url;
}
// dstIp 若为ip:port形式,更新参数
Matcher matcher = HttpResource.patternHost.matcher(dstIp);
if (matcher.find()) {
dstIp = matcher.group(1);
dstPort = Integer.parseInt(matcher.group(2));
}
if (socketServer == null) {
socketServer = new Socket();
socketServer.connect(new InetSocketAddress(dstIp, dstPort));
// 获取服务器之间的输入输出流
inFromSever = new StreamReader(monitor, socketServer,
new BufferedInputStream(socketServer.getInputStream()));
outToServer = new BufferedOutputStream(socketServer.getOutputStream());
// 打开面向服务器的监听线程,专用于转发数据给客户端
ProxyDealer proxyDealer = new ProxyDealer(this);
SocketServer.httpProxyThreadPool.execute(proxyDealer);
}
}
处理客户端的消息,构造Http请求发送给服务器
private void doProxyConnect(HttpRequest httpRequest) throws IOException {
// System.out.println("调用的是connect 方法");
connecToServer(httpRequest);
out.write("HTTP/1.1 200 Connection Established\r\n\r\n".getBytes());
out.flush();
}