HTTP代理实现请求报文的拦截与篡改7--将接收到的响应报文返回给客户端
将从服务器端接收的响应报文返回给客户端
OKAY,到此,从服务端接收响应报文,算是全部讲完了,那么下一步,自然就是大结局:将从服务端接收到的响应报文包装后再发给客户端了。万里长征终于快到头了,东方姑娘也快要掏心救人了, 是不是有点小兴奋,当然兴奋归兴奋,最后这几里路还是要坚持走完的 。
- HTTP代理实现请求报文的拦截与篡改1--开篇
- HTTP代理实现请求报文的拦截与篡改2--功能介绍+源码下载
- HTTP代理实现请求报文的拦截与篡改3--代码分析开始
- HTTP代理实现请求报文的拦截与篡改4--从客户端读取请求报文并封装
- HTTP代理实现请求报文的拦截与篡改5--将请求报文转发至目标服务器
- HTTP代理实现请求报文的拦截与篡改6--从目标服务器接收响应报文并封装
- HTTP代理实现请求报文的拦截与篡改7--将接收到的响应报文返回给客户端
- HTTP代理实现请求报文的拦截与篡改8--自动设置及取消代理+源码下载
- HTTP代理实现请求报文的拦截与篡改8补--自动设置及取消ADSL拔号连接代理+源码下载
- HTTP代理实现请求报文的拦截与篡改9--实现篡改功能后的演示+源码下载
- HTTP代理实现请求报文的拦截与篡改10--大结局 篡改部分的代码分析
this.ObtainRequest() // 获取请求信息 this.Response.ResendRequest() // 将请求报文重新包装后转发给目标服务器 this.Response.ReadResponse() // 读取从目标服务器返回的信息 this.ReturnResponse() // 将从目标服务器读取的信息返回给客户端
Session类Execute方法的四大神器,前面三个已经搞定了,只剩下这最后一个 this.ReturnResponse()了。
既然是this。这个ReturnResponse自然在Session类里了 。
下面先一窥面目。
1 internal bool ReturnResponse() 2 { 3 bool flag = false; 4 this.Timers.ClientBeginResponse = this.Timers.ClientDoneResponse = DateTime.Now; 5 try 6 { 7 if ((this.Request.ClientPipe != null) && this.Request.ClientPipe.Connected) 8 { 9 this.Request.ClientPipe.Send(this.Response.Headers.ToByteArray(true, true)); 10 this.Request.ClientPipe.Send(this.ResponseBodyBytes); 11 this.Timers.ClientDoneResponse = DateTime.Now; 12 this.Request.ClientPipe.End(); 13 flag = true; 14 } 15 else 16 { 17 this.State = SessionStates.Done; 18 } 19 } 20 catch (Exception exception) 21 { 22 this.State = SessionStates.Aborted; 23 } 24 this.Request.ClientPipe = null; 25 try 26 { 27 // this.FinishUISession(false); 28 } 29 catch (Exception) 30 { 31 } 32 return flag ; 33 }
找主干,只有三句 (顺便啰嗦一HA,要想学好程序,阅读别人的代码是必不可少的,而阅读 别人代码的法门,就是学会找主干,学会了找主干,就好比练会了独狐九剑,任你纷繁芜杂,俺一眼切中要害)
this.Request.ClientPipe.Send(this.Response.Headers.ToByteArray(true, true)); this.Request.ClientPipe.Send(this.ResponseBodyBytes); this.Request.ClientPipe.End();
还记得封装请求转发给服务端吗
this.ServerPipe.Send( this.m_session.Request.Headers.ToByteArray( true, true, this._bWasForwarded && !this.m_session.IsHTTPS ) ); this.ServerPipe.Send(this.m_session.RequestBodyBytes);
两个是不是一样的,只是发送的方向和内容有所不同就是了。各位自行看看代码就明白了。
不过这里确实有一点让人 很费解,就是数据发送完成后又加了一句this.Request.ClientPipe.End(); 进去这个方法里看看,其实就是简单的调用Socket.Shutdown和Close把连接给关闭了。这就很奇怪了,前面不是讲,如果客户端,有connection:keep-alive报头,服务端要根据情况判断是否关闭连接吗?另外我们也没有把从服务端接收过来的响应报头里的connection:keep-alive变成connection:close的处理,这也就意味着,响应给客户端的报头里很有可能包含有connection:keep-alive,那不就意味着告诉客户端愿意保持持久连接吗,一方面告诉别人你同意了持久连接,另一方面,又直接把连接给关闭了 ? 这不属于违反协议吗? 当然,这种情况是不属于违反协议的。为什么呢 ? 这是因为,connection:keep-alive保持持久连接并不是承诺性的,双方可以随时在不通知对方的情况下,单方面,关闭连接。也就是说即使服务端的响应报文里包含connection:keep-alive首部或者客户端 的请求报文里含有 connection:keep-alive,这也不代表双方就要百分之百的保证一定会保持持久连接,原因很简单,因为任何情况都有可能会发生,双方也没办法保证,服务器突然当机了、机房突然断电了,客户端在请求过程中,浏览器被关闭了……等等。所以即使双方都认可了connection:keep-alive,并已通知了对方,同意了保持持久连接,这时候在未通知对方关闭的情况下,单方关闭了连接,在HTTP协议中也不算是违约的
当然,违不违约,和有没有意义是两回事,在这里,我们直接关闭连接是为了处理方便 , 代理服务器维持持久连接是件很麻烦的事……
终于完成了,额的个神呐,不容易啊。 但在终了,还是要再啰嗦一下,计算机这东西重在理解,上面的代码不要照抄,要在理解的基础上,用自己的方法去实现
OKAY,其它的也不罗嗦了,这章到此结束,不过整个系列可还没完。
现在只能算拦截完了,篡改还没开始呢。 虽然东方姑娘已经死了,但任大小姐还得继续笑傲江湖呢。