將從服務器端接收的響應報文返回給客戶端
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,其它的也不羅嗦了,這章到此結束,不過整個系列可還沒完。
現在只能算攔截完了,篡改還沒開始呢。 雖然東方姑娘已經死了,但任大小姐還得繼續笑傲江湖呢。
