要很好地領會AJax技術的關鍵是了解超文本傳輸協議(HTTP),該協議用來傳輸網頁、圖像以及因特網上在浏覽器與服務器間傳輸的其他類型文件。只要你在浏覽器上輸入一個URL,最前面的http://就表示使用HTTP來訪問指定位置的信息。 (大部分浏覽器還支持其他一些不同的協議,其中FTP就是一個典型例子。)
注意:本文中只涉及HTTP協議,這是AJax開發人員關心的方面,它可作為HTTP的參考手冊或指南。
HTTP由兩部分組成:請求和響應。當你在Web浏覽器中輸入一個URL時,浏覽器將根據你的要求創建並發送請求,該請求包含所輸入的URL以及一些與浏覽器本身相關的信息。當服務器收到這個請求時將返回一個響應,該響應包括與該請求相關的信息以及位於指定URL(如果有的話)的數據。直到浏覽器解析該響應並顯示出網頁(或其他資源)為止。
HTTP請求
HTTP請求的格式如下所示:
<request-line>
<headers>
<blank line>
[<request-body>]
在HTTP請求中,第一行必須是一個請求行(request line),用來說明請求類型、要訪問的資源以及使用的HTTP版本。緊接著是一個首部(header)小節,用來說明服務器要使用的附加信息。在首部之後是一個空行,再此之後可以添加任意的其他數據[稱之為主體(body)]。
在HTTP中,定義了大量的請求類型,不過AJax開發人員關心的只有GET請求和POST請求。只要在Web浏覽器上輸入一個URL,浏覽器就將基於該URL向服務器發送一個GET請求,以告訴服務器獲取並返回什麼資源。對於www.wrox.com的GET請求如下所示:
GET / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
請求行的第一部分說明了該請求是GET請求。該行的第二部分是一個斜槓(/),用來說明請求的是該域名的根目錄。該行的最後一部分說明使用的是HTTP 1.1版本(另一個可選項是1.0)。那麼請求發到哪裡去呢?這就是第二行的內容。
第2行是請求的第一個首部,HOST。首部HOST將指出請求的目的地。結合HOST和上一行中的斜槓(/),可以通知服務器請求的是www.wrox.com/(HTTP 1.1才需要使用首部HOST,而原來的1.0版本則不需要使用)。第三行中包含的是首部User-Agent,服務器端和客戶端腳本都能夠訪問它,它是浏覽器類型檢測邏輯的重要基礎。該信息由你使用的浏覽器來定義(在本例中是Firefox 1.0.1),並且在每個請求中將自動發送。最後一行是首部Connection,通常將浏覽器操作設置為Keep-Alive(當然也可以設置為其他值,但這已經超出了本書討論的范圍)。注意,在最後一個首部之後有一個空行。即使不存在請求主體,這個空行也是必需的。
如果要獲取一個諸如http://www.wrox.com/books的www.wrox.com域內的頁面,那麼該請求可能類似於:
GET /books/ HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意只有第一行的內容發生了變化,它只包含URL中www.wrox.com後面的部分。
要發送GET請求的參數,則必須將這些額外的信息附在URL本身的後面。其格式類似於:
URL ? name1=value1&name2=value2&..&nameN=valueN
該信息稱之為查詢字符串(query string),它將會復制在HTTP請求的請求行中,如下所示:
GET /books/?name=Professional%20AJax HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
注意,為了將文本“Professional AJax”作為URL的參數,需要編碼處理其內容,將空格替換成%20,這稱為URL編碼(URL encoding),常用於HTTP的許多地方(JavaScript提供了內建的函數來處理URL編碼和解碼,這些將在本章中的後續部分中說明)。“名稱—值”(name—value)對用 & 隔開。絕大部分的服務器端技術能夠自動對請求主體進行解碼,並為這些值的訪問提供一些邏輯方式。當然,如何使用這些數據還是由服務器決定的。
浏覽器發送的首部,通常比本文中所討論的要多得多。為了簡單起見,這裡的例子盡可能簡短。
另一方面,POST請求在請求主體中為服務器提供了一些附加的信息。通常,當填寫一個在線表單並提交它時,這些填入的數據將以POST請求的方式發送給服務器。
以下就是一個典型的POST請求:
POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20AJax&publisher=Wiley
從上面可以發現, POST請求和GET請求之間有一些區別。首先,請求行開始處的GET改為了POST,以表示不同的請求類型。你會發現首部Host和User-Agent仍然存在,在後面有兩個新行。其中首部Content-Type說明了請求主體的內容是如何編碼的。浏覽器始終以application/ x-www-form- urlencoded的格式編碼來傳送數據,這是針對簡單URL編碼的MIME類型。首部Content-Length說明了請求主體的字節數。在首部Connection後是一個空行,再後面就是請求主體。與大多數浏覽器的POST請求一樣,這是以簡單的“名稱—值”對的形式給出的,其中name是Professional AJax,publisher是Wiley。你可以以同樣的格式來組織URL的查詢字符串參數。
正如前面所提到的,還有其他的HTTP請求類型,它們遵從的基本格式與GET請求和POST請求相同。下一步我們來看看服務器將對HTTP請求發送什麼響應。
HTTP響應
如下所示,HTTP響應的格式與請求的格式十分類似:
<status-line>
<headers>
<blank line>
[<response-body>]
正如你所見,在響應中唯一真正的區別在於第一行中用狀態信息代替了請求信息。狀態行(status line)通過提供一個狀態碼來說明所請求的資源情況。以下就是一個HTTP響應的例子:
HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/Html;charset=ISO-8859-1
Content-Length: 122
<Html>
<head>
<title>Wrox Homepage</title>
</head>
<body>
<!-- body goes here -->
</body>
</Html>
在本例中,狀態行給出的HTTP狀態代碼是200,以及消息OK。狀態行始終包含的是狀態碼和相應的簡短消息,以避免混亂。最常用的狀態碼有:
◆200 (OK): 找到了該資源,並且一切正常。
◆304 (NOT MODIFIED): 該資源在上次請求之後沒有任何修改。這通常用於浏覽器的緩存機制。
◆ 401 (UNAUTHORIZED): 客戶端無權訪問該資源。這通常會使得浏覽器要求用戶輸入用戶名和密碼,以登錄到服務器。
◆403 (FORBIDDEN): 客戶端未能獲得授權。這通常是在401之後輸入了不正確的用戶名或密碼。
◆404 (NOT FOUND): 在指定的位置不存在所申請的資源。
在狀態行之後是一些首部。通常,服務器會返回一個名為Data的首部,用來說明響應生成的日期和時間(服務器通常還會返回一些關於其自身的信息,盡管並非是必需的)。接下來的兩個首部大家應該熟悉,就是與POST請求中一樣的Content-Type和Content-Length。在本例中,首部Content-Type指定了MIME類型HTML(text/html),其編碼類型是ISO-8859-1(這是針對美國英語資源的編碼標准)。響應主體所包含的就是所請求資源的Html源文件(盡管還可能包含純文本或其他資源類型的二進制數據)。浏覽器將把這些數據顯示給用戶。
注意,這裡並沒有指明針對該響應的請求類型,不過這對於服務器並不重要。客戶端知道每種類型的請求將返回什麼類型的數據,並決定如何使用這些數據。