前面的話
Web代理(proxy)服務器是網絡的中間實體,位於客戶端和服務器之間,扮演“中間人”的角色,在各端點之間來回傳送HTTP報文。本文將介紹HTTP代理服務器相關內容
中間實體
Web上的代理服務器是代表客戶端完成事務處理的中間人。如果沒有Web代理,HTTP客戶端就要直接與HTTP服務器進行對話。有了Web代理,客戶端就可以與代理進行對話,然后由代理代表客戶端與服務器進行交流。客戶端仍然會完成對事務的處理,但它是通過代理服務器提供的服務來實現的
HTTP的代理服務器既是Web服務器又是Web客戶端。HTTP客戶端會向代理發送請求報文,代理服務器必須像Web服務器一樣,正確地處理請求和連接,然后返回響應。同時,代理自身要向服務器發送請求,這樣,其行為就必須像正確的HTTP客戶端一樣,要發送清求並接收響應。如果要創建自己的HTTP代理,就要遵循為HTTP客戶端和HTTP服務器制定的規則

代理服務器可以是某個客戶端專用的,也可以是很多客戶端共享的。單個客戶端專用的代理被稱為私有代理。眾多客戶端共享的代理被稱為公共代理
大多數代理都是公共的共享代理。集中式代理的成本效率更高,更容易管理。某些代理應用,比如高速緩存代理服務器,會利用用戶間共同的請求,這樣的話,匯入同一個代理服務器的用戶越多,它就越有用
專用的私有代理並不常見,但它們確實存在,尤其是直接運行在客戶端計算機上的時候。有些瀏覽器輔助產品,以及一些ISP服務,會在用戶的PC上直接運行一些小型的代理,以便擴展瀏覽器特性,提髙性能,或為免費ISP服務提供主機廣告
嚴格來說,代理連接的是兩個或多個使用相同協議的應用程序,而網關連接的則是兩個或多個使用不同協議的端點。網關扮演的是“協議轉換器”的角色,即使客戶端和服務器使用的是不同的協議,客戶端也可以通過它完成與服務器之間的事務處理
下圖a中的中間設備是一個HTTP代理,因為代理與客戶端和服務器之間使用的都是HTTP協議。b中的中間設備是一個HTTP/POP網關,因為它把HTTP的前台與POP E-mail的后端連接了起來。網關將Web事務轉換成適當的POP事務,這樣用戶就可以通過HTTP讀取E-mail了。基於Web的E-mail程序,比如Yahoo!郵件和MSN Hotmail都是HTTP E-mail網關

實際上,代理和網關之間的區別很模糊。由於瀏覽器和服務器實現的是不同版本的HTTP,代理也經常要做一些協議轉換工作。而商業化的代理服務器也會實現網關的功能來支持SSL安全協議、SOCKS防火牆、FTP訪問,以及基干Web的應用程序
功能
代理服務器可以實現各種有用的功能。它們可以改善安全性,提高性能,節省費用。代理服務器可以看到並接觸到所有流過的HTTP流量,所以代理可以監視流量並對其進行修改,以實現很多有用的增值Web服務
【兒童過濾器】
小學在為教育站點提供無阻礙訪問的同時,可以利用過濾器代理來阻止學生訪問成人內容。代理應該允許學生無限制地訪問教育性內容,但對不適合兒童的站點要強行禁止訪問

【文檔訪問控制】
可以用代理服務器在大量Web服務器和Web資源之間實現統一的訪問控制策略,創建審核跟蹤機制。這在大型企業環境或其他分布式機構中是很有用的
在集中式代理服務器上可以對所有訪問控制功能進行配置,而無需在眾多由不同組織管理、不同廠商制造、使用不同模式的Web服務器上進行經常性的訪問控制升級
在下圖中,集中式訪問控制代理:允許客戶端1無限制地訪問服務器A的新聞頁面;客戶端2可以無限制地訪問因特網;在允許客戶端3訪問服務器B之前,要求其輸入口令

【安全防火牆】
網絡安全工程師通常會使用代理服務器來提高安全性。代理服務器會在網絡中的單一安全節點上限制哪些應用層協議的數據可以流入或流出一個組織。還可以提供用來消除病毒的Web和E-mail代理使用的那種掛鈎程序,以便對流量進行詳細的檢査

【Web緩存】
代理緩存維護了常用文檔的本地副本,並將它們按需提供,以減少緩慢且昂貴的因特網通信。在下圖中,客戶端1和客戶端2會去訪問附近Web緩存上的對象A,而客戶端3和客戶端4訪問的則是原始服務器上的文檔

【反向代理】
代理可以假扮Web服務器,這些被稱為替代物(surrogate)或反向代理(reverse proxy)的代理接收發給Web服務器的真實請求,但與Web服務器不同的是,它們可以發起與其他服務器的通信,以便按需定位所請求的內容
反向代理可以提高訪問慢速Web服務器上公共內容時的性能。在這種配置中,通常將這些反向代理稱為服務器加速器(server accelerator)。還可以將替代物與內容路由功能配合使用,以創建按需復制內容的分布式網絡

【內容路由器】
代理服務器可以作為“內容路由器”使用,根據因特網流量狀況以及內容類型將請求導向特定的Web服務器
內容路由器也可以用來實現各種服務級的請求。比如,如果用戶或內容提供者付費要求提供更髙的性能,內容路由器可以將請求轉發到附近的復制緩存,或者如果用戶申請了過濾服務,還可以通過過濾代理來轉發HTTP請求。可以用自適應內容路由代理來構建很多有趣的服務

【轉碼器】
代理服務器在將內容發送給客戶端之前,可以修改內容的主體格式。在這些數據表示法之間進行的透明轉換被稱為轉碼(transcoding)
轉碼代理可以在傳輸GIF圖片時,將其轉換成JPEG圖片,以減小尺寸。也可以對圖片進行壓縮,或降低顏色的色彩飽和度以便在電視上觀看。同樣,可以對文本文件進行壓縮,並為能夠使用因特網智能手機生成小型的文本摘要Web頁面。代理甚至可以在傳輸文檔的過程中將其轉換成外語
下圖顯示了一個轉碼代理,這個代理可以將英語文本轉換成西班牙語文本,將HTML頁面重新格式化為較簡單的文本,以便顯示在手機的小屏幕上

【匿名者】
匿名者代理會主動從HTTP報文中刪除身份特性(比如客戶端IP地址、From首部、Referer首部、cookie、URI的會話ID),從而提供高度的私密性和匿名性
在下圖中,匿名代理會對用戶報文進行下列修改以增加私密性:從User-Agent首部刪除用戶的計算機與OS類型;刪除From首部以保護用戶的E-mail地址;刪除Referer首部來掩蓋用戶訪問過的其他站點;刪除Cookie首部以剔除概要信息和身份的數據
部署
可以根據其目標用途,將代理放在任意位置
a、出口代理
可以將代理固定在本地網絡的出口點,以便控制本地網絡與大型因特網之間的流量。可以在公司網絡中使用出口代理,提供針對公司外部惡意黑客的防火牆保護,或降低帶寬費用,提高因特網流量的性能。小學可能會使用過濾出口代理來防止早熟的學生瀏覽不恰當的內容
b、訪問(入口)代理
代理常被放在ISP訪問點上,用以處理來自客戶的聚合請求。ISP使用緩存代理來存儲常用文檔的副本,以提高用戶(尤其是高速連接用戶)的下載速度,降低因特網帶寬耗費
c、反向代理
代理通常會被部署在網絡邊緣,在Web服務器之前,作為替代物(也常被稱為反向代理)使用,在那里它們可以處理所有傳送給Web服務器的請求,並只在必要時向Web服務器請求資源。替代物可以提高Web服務器的安全特性,或者將快速的Web服務器緩存放在較慢的服務器之前,以提高性能。反向代理通常會直接冒用Web服務器的名字和IP地址,這樣所有的請求就會被發送給代理而不是服務器了
d、網絡交換代理
可以將具有足夠處理能力的代理放在網絡之間的因特網對等交換點上,通過緩存來減輕因特網節點的擁塞,並對流量進行監視

【代理的層次結構】
可以通過代理層次結構(proxy hierarchy)將代理級聯起來。在代理的層次結構中,會將報文從一個代理傳給另一個代理,直到最終抵達原始服務器為止,然后通過代理傳回給客戶端
Proxy層次結構中的代理服務器被賦予了父(parent)和子(child)的關系。下一個入口(inbound)代理(靠近服務器)被稱為父代理,下一個出口(outbound)代理(靠近客戶端)被稱為子代理
下圖中,代理1是代理2的子代理。同樣,代理2是代理3的子代理,代理3是代理2的父代理

上圖中的代理層次結構是靜態的——代理1總是會將報文轉發給代理2,代理2 總是會將報文轉發給代理3。但是,層次不一定非得是靜態的。代理服務器可以根據眾多因素,將報文轉發給一個不斷變化的代理服務器和原始服務器集
比如,在下圖中,訪問代理會根據不同的情況將報文轉發給父代理或原始服務器:如果所請求的對象屬於一個付費使用內容分發服務的Web服務器,代理就會將請求發送給附近的一個緩存服務器,這個服務器會返回已緩存對象,或者如果它那兒沒有的話,它會去取回內容;如果請求的是特定類型的圖片,訪問代理會將請求轉發給一個特定的壓縮代理,這個代理會去獲取圖片,然后對其進行壓縮,這樣通過到客戶端的慢速Modem下載時,速度會更快一些

下面是幾個動態選擇父代理的例子
a、負載均衡
子代理可能會根據當前父代理上的工作負載級別來決定如何選擇一個父代理,以均衡負載
b、地理位置附近的路由
子代理可能會選擇負責原始服務器所在物理區域的父代理
c、協議/類型路由
子代理可能會根據URI將報文轉發到不同的父代理和原始服務器上去。某些特定類型的URI可能要通過一些特殊的代理服務器轉發請求,以便進行特殊的協議處理
d、基於訂購的路由
如果發布者為高性能服務額外付費了,它們的UR1就會被轉發到大型緩存或壓縮引擎上去,以提高性能
在不同的產品中,動態父路由邏輯的實現方式各有不同,包括使用配置文件、腳本語言和動態可執行插件等
【代理獲取流量】
客戶端通常會直接與Web服務器進行通信,所以要解釋清楚HTTP流量怎樣才能首先流向代理。有四種常見方式可以使客戶端流量流向代理
a、修改客戶端
很多Web客戶端都支持手工和自動的代理配置。如果將客戶端配置為使用代理服務器,客戶端就會將HTTP請求有意地直接發送給代理,而不是原始服務器
b、修改網絡
網絡基礎設施可以通過若干種技術手段,在客戶端不知道或沒有參與的情況下,攔截網絡流量並將其導入代理。這種攔截通常都依賴於監視HTTP流量的交換設備及路由設備,在客戶端毫不知情的情況下,對其進行攔截,並將流量導入一個代理。這種代理被稱為攔截(intercepting)代理
[注意]攔截代理通常被稱為“透明代理”,因為會在不知情的情況下連接到這些代理上去。但HTTP規范中已用“透明”來表示那些不會對語義進行修改的功能了,所以標准制定機構建議在流量捕獲中使用術語“攔截”
c、修改DNS的命名空間
放在Web服務器之前的代理服務器——替代物,會直接假扮Web服務器的名字和IP地址,這樣,所有的請求就會發送給這些替代物,而不是服務器。要實現這一點,可以手工編輯DNS名稱列表,或者用特殊的動態DNS服務器根據需要來確定適當的代理或服務器。有時在安裝過程中,真實服務器的IP地址和名稱被修改了,替代物得到的會是之前的地址和名稱
d、修改Web服務器
可以將某些Web服務器配置為向客戶端發送一條HTTP重定向命令(響應碼 305),將客戶端請求重定向到一個代理上去。收到重定向命令后,客戶端會與代理進行通信

設置
所有現代的Web瀏覽器都允仵用戶對代理的使用進行配置。實際上,很多瀏覽器都提供了多種配置代理的方式,其中包括以下幾種
a、手工設置
顯式地設置要使用的代理
很多Web客戶端都允許用戶手工配置代理。瀏覽器為代理配置提供了便捷的支持,為代理指定主機和端口。有些ISP會向客戶發送預先配置好的瀏覽器,或定制好的操作系統,使其將Web流量重定向到代理服務器上
手工代理配置很簡單但有些死板。只能為所有內容指定唯一的一個代理服務器,而且不支持故障轉移。手工代理配置還會給大型組織帶來管理問題。如果配置過的瀏覽器基數很大,那么需要進行修改的時候,重新配置每個瀏覽器是非常困難,甚至是不可能的
b、預先配置瀏覽器
瀏覽器廠商或發行商會在將瀏覽器發送給其客戶之前預先對瀏覽器(或所有其他Web客戶端)的代理設置進行手工配置
c、代理的自動配置(Proxy Auto-Configuration, PAC)
提供一個URI,指向一個用JavaScript語言編寫的代理自動配置文件,客戶端會取回這個JavaScript文件,並運行它以決定是否應該使用一個代理,如果是的話,應該使用哪個代理服務器
PAC文件是一些小型的JavaScript程序,可以在運行過程中計算代理設置。因此,是一種更動態的代理配置解決方案。訪問每個文檔時,JavaScript函數都會選擇恰當的代理服務器
要使用PAC文件,就要用JavaScript PAC文件的URI來配置瀏覽器,配置方式與手工配置類似,但要在“automatic configuration”(自動配置)框中提供一個URI。瀏覽器會從這個URI上獲取PAC文件,並用JavaScript邏輯為每次訪問計算恰當的代理服務器。PAC文件的后綴通常是.pac,MIME類型通常是application/x-ns-proxy-autoconfig
每個PAC文件都必須定義一個名為FindProxyForURL(url,host)的函數,用來計算訪問URI時使用的適當的代理服務器。函數的返回值可以是下表中列出的任意值
FindProxyForURL的返回值 描述
DIRECT 不經過任何代理,直接進行連接
PROXY host: port 應該使用指定的代理
SOCKS host:port 應該使用指定的SOCKS服務器
d、WPAD的代理發現
有些瀏覽器支持Web代理自動發現協議(Web Proxy Autodiscovery Protocol, WPAD),這個協議會自動檢測出瀏覽器可以從哪個“配置服務器”下載到一個自動配置文件
WPAD協議的算法會使用發現機制的逐級上升策略自動地為瀏覽器査找合適的PAC文件。實現WPAD協議的客戶端需要:用WPAD找到PAC的URI;從指定的URI獲取PAC文件;執行PAC文件來判定代理服務器;為請求使用代理服務器
WPAD會使用一系列的資源發現技術來判定適當的PAC文件。並不是所有組織都能夠使用所有的發現技術,所以WPAD使用了很多種發現技術。WPAD會一個接一個地對每種技術進行嘗試,直到成功為止
當前的WPAD協議規范按順序定義了下列技術:動態主機配置協議(Dynamic Host Configuration Protocol, DHCP);服務定位協議(Service Location Protocol, SLP);DNS知名主機名;DNSSRV 記錄;TXT記錄中的DNS服務URI
棘手問題
【URI】
除了一點之外,Web服務器報文和Web代理報文的語法是一樣的。客戶端向服務器而不是代理發送請求時,HTTP請求報文中的URI會有所不同
客戶端向Web服務器發送請求時,請求行中只包含部分URI(沒有方案、主機或端口),例如:
GET /index.html HTTP/1.0 User-Agent: SuperBrowser v1.3
但當客戶端向代理發送請求時,請求行中則包含完整的URI,例如:
GET http://www.marys-antiques.com/index.html HTTP/1.0 User-Agent: SuperBrowser v1.3
為什么會有兩種不同的請求格式,一種用於代理,另一種用於服務器呢?在原始的HTTP設計中,客戶端會直接與單個服務器進行對話。不存在虛擬主機,也沒有為代理制定什么規則。單個的服務器都知道自己的主機名和端口,所以,為了避免發送冗余信息,客戶端只需發送部分URI即可,無需發送方案和主機以及端口
代理出現之后,使用部分URI就有問題了。代理需要知道目標服務器的名稱,這樣它們才能建立自己與服務器的連接。基於代理的網關要知道URI的方案才能連接到FTP資源和其他方案上去。HTTP/1.0要求代理請求發送完整的URI,解決了這個問題,但它為服務器請求保留部分URI的形式(已經有相當多的服務器都改為支持完整URI了)
[注意]現在,HTTP/1.1要求服務器為代理請求和服務器請求都提供完整的URI處理,但實際上,很多已部署的服務器仍然只接受部分URL
因此,要將部分URI發送給服務器,將完整URI發送給代理。在顯式地配置客戶端代理設置的情況下,客戶端就知道要發布哪種類型的請求了
【虛擬主機】
代理“缺少方案/主機/端口”的問題與虛擬主機Web服務器面臨的問題相同。虛擬主機Web服務器會在很多Web站點間共享同一個物理Web服務器。包含部分URI(比如/index.html)的請求到達時,虛擬主機Web服務器需要知道目的Web站點的主機名
盡管它們出現的問題相似,但解決方法卻有所不同:顯式的代理要求在請求報文中使用完整URI來解決這個問題;虛擬主機Web服務器要求使用Host首部來承載主機和端口信息
【部分URI】
只要客戶端正確地實現了HTTP,它們就會在請求中包含完整的URI,發送給經過顯式配置的代理。這樣解決了部分問題,但還有一個問題:客戶端並不總是知道它是在和代理進行對話,因為有些代理對客戶端可能是不可見的。即使沒有將客戶端配置為使用代理,客戶端的流量也可能會經過替代物或攔截代理。在這兩種情況下,客戶端都會認為它在與Web服務器進行對話,不會發送完整的URI
反向代理是一個用來取代原始服務器的代理服務器,它通常會通過假扮服務器的主機名或IP地址來做到這一點。它會收到Web服務器請求,可能會向真正的服務器提供緩存的響應或者代理請求。客戶端無法區分反向代理和Web 服務器,因此它會發送部分URI
攔截代理是網絡流量中的代理服務器,它會攔截從客戶端發往服務器的請求,並提供一個緩存響應,或對其進行轉發。由於攔截代理攔截了從客戶端到服務器的流量,所以它會收到發送給Web服務器的部分URI

【處理請求】
由於將流量重定向到代理服務器的方式有所不同,通用的代理服務器既應該支持請求報文中的完整URI,也應該支持部分URI。如果是顯式的代理請求,代理就應該使用完整URI,如果是Web服務器請求,就應該使用部分URI和虛擬Host首部
使用完整和部分URI的規則如下所示:
a、如果提供的是完整URI,代理就應該使用這個完整URI
b、如果提供的是部分URI,而且有Host首部,就應該用Host首部來確定原始服務器的名字和端口號
c、如果提供的是部分URI,而且沒有Host首部,就要用其他方法來確定原始服務器:如果代理是代表原始服務器的替代物,可以用真實服務器的地址和端口號來配置代理;如果流量被攔截了,而且攔截者也可以提供原始的IP地址和端口,代理就可以使用攔截技術提供的IP地址和端口號;如果所有方法都失敗了,代理沒有足夠的信息來確定原始服務器,就必須返回一條錯誤報文,通常是建議用戶升級到支持Host首部的現代瀏覽器
【URI修改】
代理服務器要在轉發報文時修改請求URI的話,需要恃別小心。對URI的微小修改,甚至是看起來無害的修改,都可能給下游服務器帶來一些互操作性問題
尤其是,現在已知有些代理會在將URI轉發給下一跳節點之前將URI“規范”為標准格式。有些看起來無害的轉換行為,比如用顯式的“:80”來取代默認的HTTP端口,或者用適當的換碼轉義符來取代非法的保留字符以校正URI,就可能造成互操作性問題
總之,代理服務器要盡量寬容一些。它們的目標不是成為強制實現嚴格協議一致性的“協議警察”,因為這樣可能會嚴重破壞之前能正常工作的服務。特別是,HTTP規范禁止一般的攔截代理在轉發URI時重寫其絕對路徑部分。唯一的例外是可以用“/”來取代空路徑
【URI自動擴展】
根據是否有代理,瀏覽器對請求URI的解析會有所不同。沒有代理時,瀏覽器會獲取輸入的URI,嘗試着尋找相應的IP地址。如果找到了主機名,瀏覽器會嘗試相應的IP地址直到獲得成功的連接為止
但是,如果沒有找到主機,很多瀏覽器都會嘗試着提供某種主機名自動“擴展”機制,以防用戶輸入的是主機“簡短”的縮寫形式:很多瀏覽器會嘗試着加入前綴www.和后綴.com,以防用戶只輸入了常見Web站點名的中間部分(比如,人們可以輸入yahoo而不是www.yahoo.com);有些瀏覽器甚至會將未解析出來的URI傳遞給第三方站點,這個站點會嘗試着校正拼寫錯誤,並給出一些用戶可能希望訪問的URI建議;而且,大多數系統中的DNS配置允許用戶只輸入主機名的前綴,然后DNS會自動搜索域名。如果用戶位於域名oreilly.com的范圍之內,並輸入了主機名host7,DNS會自動嘗試將其與host7.oreilly.com進行匹配
【URI解析】
下圖顯示在沒有代理的情況下,瀏覽器進行主機名自動擴展的例子
用戶向瀏覽器的URI窗口輸入oreilly。瀏覽器用oreilly作為主機名,並假定默認方案為http://,默認端口為80,默認路徑為'/';瀏覽器查找主機oreilly,如果查找失敗,則對主機名進行自動擴展,將oreilly轉換成www.oreilly.com,解析成功;然后,瀏覽器成功地連接www.oreilly.com

【有顯式代理時URI的解析】
使用顯式代理時,用戶的URI會被直接發送給代理,所以瀏覽器就不再執行所有這些便捷的擴展功能了
有顯式代理時,瀏覽器沒有對不完整的主機名進行自動擴展。因此,當用戶在瀏覽器的地址窗口中輸入oreilly時,發送給代理的就是http://oreilly/(瀏覽器添加了默認方案和路徑,但主機名和輸入的一樣)
因此,有些代理會盡力嘗試着去模仿瀏覽器的便捷服務,包括www...com自動擴展,以及添加本地域名后綴。但對得到廣泛共享的代理來說,知道單個用戶的正確域名后綴基本上是不可能的

【有攔截代理時URI的解析】
使用不可見的攔截代理時,對主機名的解析會略有不同,因為對客戶端來說,是沒有代理的。這種情況下的行為與使用服務器的情形很類似,瀏覽器會自動擴展主機名,直到DNS成功為止。但建立到服務器的連接時,有一個很重要的區別
下圖顯示了下列事務處理過程:在第(1)步中,用戶在瀏覽器的URI地址窗口中輸入oreilly;在第(2a)步中,瀏覽器通過DNS査找主機oreilly,但DNS服務器失敗了,並回送響應說明主機未知;在第(3a)步中,瀏覽器進行了自動擴展,將oreilly轉換成www.oreilly.com。在第(3b)步中,瀏覽器通過DNS來査找主機www.oreilly.com。這一次,如第(3c)步所示,DNS服務器成功了,將IP地址返回給了瀏覽器;在第(4a)步中,客戶端已經成功解析了主機名,並有了一張IP地址列表。有些IP地址可能已經停用了。所以,通常客戶端會嘗試着連接每個IP地址,直到成功為止。但對攔截代理來說,第一次連接請求就會被代理服務器攔截成功,不會連接到原始服務器上去。客戶端認為它在與Web服務器進行成功的對話,但那個Web服務器可能甚至都不處於活躍狀態;當代理最終准備好與真正的原始服務器進行交互時[第(5b)步],代理可能會發現那個IP地址實際指向的是一個已停用的服務器。為了提供與瀏覽器相同級別的容錯機制,代理可以通過解析Host首部的主機名,也可以通過對IP地址的反向DNS査找來嘗試其他IP地址。將瀏覽器配置為使用顯式代理時,它們會依賴代理的容錯機制。所以對攔截和顯式的代理實現來說,在DNS解析到已停用服務器時,提供容錯機制是很重要的

追蹤報文
在將Web請求從客戶端傳送到服務器的路徑上,經過兩個或多個代理是很常見的。比如,出於安全和節省費用的考慮,很多公司都會用緩存代理服務器來訪問因特網,而且很多大型ISP都會使用代理緩存來提高性能並實現各種特性。現在,有相當比例的Web請求都是通過代理轉發的。同時,出於性能原因,把內容復制到遍布全球的替代物緩存庫中的情形也越來越常見了

代理是由不同廠商開發的。它們有不同的特性和缺陷,由各種不同的組織負責管理。隨着代理的逐漸流行,我們要能夠追蹤經過代理的報文流,以檢測出各種問題,其重要性就跟追蹤經過不同交換機和路由器傳輸的IP分組流一樣
【Via 首部】
Via首部字段列出了與報文途經的每個中間節點(代理或網關)有關的信息。報文每經過一個節點,都必須將這個中間節點添加到Via列表的末尾
下面的Via字符串告訴我們報文流經了兩個代理。這個字符串說明第一個代理名為proxy-62.irenes-isp.net,它實現了HTTP/1.1協議,第二個代理被稱為cache.joes-hardware.com,實現了HTTP/1.0
Via: 1.1 proxy-62.irenes-isp.net, 1.0 cache.joes-hardware.com

via首部字段用於記錄報文的轉發,診斷報文循環,標識請求/響應鏈上所有發送者的協議能力
代理也可以用via首部來檢測網絡中的路由循環。代理應該在發送一條請求之前,在Via首部插入一個與其自身有關的獨特字符串,並在輸入的請求中査找這個字符串,以檢測網絡中是否存在路由循環
Via首部字段包含一個由逗號分隔的路標(waypoint)。每個路標都表示一個獨立的代理服務器或網關,且包含與那個中間節點的協議和地址有關的信息。下面是一個帶有兩個路標的Via首部實例:
Via = 1.1 cache.joes-hardware.com, 1.1 proxy.irenes-isp.net
Via首部的正規語法如下所示:
Via ="Via" ":" 1#( waypoint ) waypoint =(received-protocol received-by [comment ]) received-protocol =[protocol-name "/"] protocol-version received-by =(host [ ":" port ] ) | pseudonym
[注意]每個Via路標中最多包含4個組件:一個可選的協議名(默認為HTTP)、一個必選的協議版本、一個必選的節點名和一個可選的描述性注釋
協議名指中間節點收到的協議。如果協議為HTTP的話,協議名就是可選的。否則,要在版本之前加上協議名,中間用“/”分隔。網關將HTTP請求連接到其他協議(HTTPS、FTP等)時,可能會使用非HTTP協議
協議版本指所收到的報文版本。版本的格式與協議有關。HTTP使用的是標准版本號(1.0、1.1等)。版本包含在Via字段中,這樣,之后的應用程序就會知道前面所有中間節點的協議能力了
節點名指中間節點的主機和可選端口號(如果沒有包含端口號,可以假定使用的是協議的默認端口號)。在某些情況下,出於隱私方面的考慮,某個組織可能不願意給出真實的主機名,在這種情況下可以用一個假名來代替
節點注釋是指進一步描述這個中間節點的可選注釋。通常會在這里包含廠商和版本信息,有些代理服務器還會在注釋字段中包含一些與此設備上所發生事件有關的診斷信息
請求和響應報文都會經過代理進行傳輸,因此,請求和響應報文中都要有Via首部。請求和響應通常都是通過同一條TCP連接傳送的,所以響應報文會沿着與請求報文相同的路徑回傳。如果一條請求報文經過了代理A、B和C,相應的響應報文就會通過代理C、B、A進行傳輸。因此,響應的Via首部基本上總是與請求的Via首部相反

有些代理會為使用非HTTP協議的服務器提供網關的功能。via首部記錄了這些協議轉換。這樣,HTTP應用程序就會了解代理鏈上各點的協議處理能力以及所做的協議轉換了
下圖中,客戶端向網關proxy.irenes-isp.net發送了一條對ftp://http-guide.com/pub/welcome.tst的HTTP請求。作為協議網關使用的代理會用FTP協議從FTP服務器獲取預期的對象。然后代理會用下面這個Via首部字段,在一條HTTP響應中將對象回送到客戶端上去
Via: FTP/1.0 proxy.irenes-isp.net(Traffic'Server/5.0.1-17882[cMs f ])

[注意]接收到的協議是FTP。可選注釋中包含有代理服務器的品牌和版本號,以及一些廠商的診斷信息
Server響應首部字段對原始服務器使用的軟件進行了描述,下面是幾個例子
Server: Apache/1.3.14 (Unix) PHP/4.0.4 Server: Netscape-Enterprise/4.1 Server: Microsoft-IIS/5.0
如果響應報文是通過代理轉發的,一定要確保代理沒有修改Server首部。Server首部是用於原始服務器的,代理應該添加的是Via條目
有時候,我們並不希望在Via字符串中使用確切的主機名。除非顯式地允許了這種行為,否則,當代理服務器作為網絡防火牆的一部分使用時,是不應該轉發防火牆后面那些主機的名字和端口號的,因為防火牆后面的網絡結構信息可能會被惡意群體利用
如果不允許進行Via節點名轉發,作為安全防線的一部分使用的代理就應該用適當的假名來取代那台主機的名字。一般來說,即使隱藏了真實名稱,代理也應該嘗試着為每台代理服務器保留一個Via路標條目
對那些有着非常強烈的隱私要求,需要隱藏內部網絡設計和拓撲結構的組織來說,代理應該將一個(接收協議值相同的)有序Via路標條目序列合並成一個聯合條目。比如,可以將:
Via: 1.0 foo, 1.1 devirus.company.com, 1.1 access -logger.company.com
壓縮成:
Via: 1.0 foo, 1.1 concealed-stuff
除非這些條目都在同一個組織的控制之下,而且已經用假名取代了主機名,否則就不能將其合並起來。同樣,接收協議值不同的條目也不能合並起來
【TRACE方法】
代理服務器可以在轉發報文時對其進行修改。可以添加、修改或刪除首部,也可以將主體部分轉換成不同的格式。代理變得越來越復雜,開發代理產品的廠商也越來越多,互操作性問題也開始逐漸顯現。為了便於對代理網絡進行診斷,我們需要有一種便捷的方式來觀察在通過HTTP代理網絡逐跳轉發報文的過程中,報文是怎樣變化的
通過HTTP/1.1的TRACE方法,用戶可以跟蹤經代理鏈傳輸的請求報文,觀察報文經過了哪些代理,以及每個代理是如何對請求報文進行修改的。TRACE對代理流的調試非常有用
當TRACE請求到達目的服務器時,整條請求報文都會被封裝在一條HTTP響應 的主體中回送給發送端。當TRACE響應到達時,客戶端可以檢査服務器收到的確切報文,以及它所經過的代理列表(在Via首部)。TRACE響應的Content-Type為message/http,狀態為200 OK

通常,不管中間插入了多少代理,TRACE報文都會沿着整條路徑傳到目的服務器。可以使用Max-Forwards(最大轉發次數)首部來限制TRACE和OPTIONS請求所經過的代理跳數,在測試代理鏈是否在無限循環中轉發報文,或者査看鏈中特定代理服務器效果時,是很有用的。Max-Forwards也可以限制OPTIONS報文的轉發
Max-Forwards請求首部字段包含了一個整數,用來說明這條請求報文還可以被轉發的次數。如果Max-Forwards的值為零(Max-Forwards:0),那么即使接收者不是原始服務器,它也必須將TRACE報文回送給客戶端,而不應該繼續轉發
如果收到的Max-Forwards值大於零,轉發的報文中就必須包含一個更新的Max-Forwards字段,其值被減一。所有的代理和網關都應該支持Max-Forwards。可以用Max-Forwards來査看在代理鏈的任意一跳上接收到的請求

代理認證
代理可以作為訪問控制設備使用。HTTP定義了一種名為代理認證(proxy authentication)的機制,這種機制可以阻止對內容的請求,直到用戶向代理提供了有效的訪問權限證書為止
對受限內容的請求到達一台代理服務器時,代理服務器可以返回一個要求使用訪問證書的407 Proxy Authorization Required狀態碼,以及一個用於描述怎樣提供這些證書的Proxy-Authenticate首部字段
客戶端收到407響應時,會嘗試着從本地數據庫中,或者通過提示用戶來搜集所需要的證書
只要獲得了證書,客戶端就會重新發送請求,在Proxy-Authorization首部 字段中提供所要求的證書
如果證書有效,代理就會將原始請求沿着傳輸鏈路向下傳送。否則,就發送另一條407應答
若傳輸鏈路中有多個代理,且每個代理都要進行認證時,代理認證通常無法很好地工作。人們建議,應該對HTTP進行升級,將認證證書與代理鏈中特定的路標聯系起來,但這些升級措施並沒有得到廣泛實現

互操作性
客戶端、服務器和代理是由不同廠商構建的,實現的是不同版本的HTTP規范。它們支持的特性各不相同,也存在着不同的問題。代理服務器位於客戶端和服務器設備之間,這些設備實現的協議可能有所不同,可能存在着很棘手的問題
代理服務器可能無法理解所有經其傳輸的首部字段。有些首部可能比代理自身還要新;其他首部可能是特定應用程序獨有的定制首部。代理必須對不認識的首部字段進行轉發,而且必須維持同名首部字段的相對順序。類似地,如果代理不熟悉某個方法,那么只要可能,就應該嘗試着將報文轉發到下一跳節點上去
在當今的大部分網絡中,如果代理不能轉發它不支持的方法,可能就無法生存下去了,因為通過微軟的Outlook進行Hotmail訪問就大量地使用了HTTP擴展方法
通過HTTP OPTIONS方法,客戶端(或代理)可以發現Web服務器或者其上某個特定資源所支持的功能(比如,它們所支持的方法)。通過使用OPTIONS,客戶端可以在與服務器進行交互之前,確定服務器的能力,這樣它就可以更方便地與具備不同特性的代理和服務器進行互操作了

如果OPTIONS請求的URI是個星號(*),請求的就是整個服務器所支持的功能。比如:
OPTIONS * HTTP/1.1
如果URI是個實際資源地址,OPTIONS請求就是在査詢那個特定資源的可用特性:
OPTIONS http://www.joes-hardware.com/index.html HTTP/1.1
如果成功,OPTIONS方法就會返回一個包含了各種首部字段的200 OK響應,這些字段描述了服務器所支持的,或資源可用的各種可選特性。HTTP/1.1在響應中唯一指定的首部字段是Allow首部,這個首部用於描述服務器所支持的各種方法(或者服務器上的特定資源)。OPTIONS允許在可選的響應主體中包含更多的信息,但並沒有對這種用法進行定義
Allow實體首部字段列出了請求URI標識的資源所支持的方法列表,如果請求URI為*的話,列出的就是整個服務器所支持的方法列表。例如:
Allow: GET, HEAD, PUT
可以將Allow首部作為請求首部,建議在新的資源上支持某些方法。並不要求服務器支持這些方法,但應該在相應的響應中包含一個Allow首部,列出它實際支持的方法。因為客戶端可能已經通過其他途徑與原始服務器進行了交流,所以即使代理無法理解指定的所有方法,也不能對Allow首部字段進行修改