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,其它的也不羅嗦了,這章到此結束,不過整個系列可還沒完。  

  現在只能算攔截完了,篡改還沒開始呢。 雖然東方姑娘已經死了,但任大小姐還得繼續笑傲江湖呢。                


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM