HTTP代理实现请求报文的拦截与篡改7--将接收到的响应报文返回给客户端

返回目录  

  将从服务器端接收的响应报文返回给客户端    

  OKAY,到此,从服务端接收响应报文,算是全部讲完了,那么下一步,自然就是大结局:将从服务端接收到的响应报文包装后再发给客户端了。万里长征终于快到头了,东方姑娘也快要掏心救人了, 是不是有点小兴奋,当然兴奋归兴奋,最后这几里路还是要坚持走完的 。

 

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,其它的也不罗嗦了,这章到此结束,不过整个系列可还没完。  

  现在只能算拦截完了,篡改还没开始呢。 虽然东方姑娘已经死了,但任大小姐还得继续笑傲江湖呢。                

posted @ 2013-03-12 15:07  乔伟2024  阅读(3458)  评论(6编辑  收藏  举报