highlight.js

星期三, 10月 03, 2007

GET、POST與cache的關係

在大部分的AJAX書籍裡頭,只要解說到XMLHttpRequest的open方法時,一定都會提到GET與POST的差異,不過大抵上講的都是GET會把參數直接加在URL上,使得一方面會在瀏覽器的網址列上洩漏傳遞的資料,另一方面則是會受限於URL長度的限制,而無法傳遞較大量的資料。但是GET與POST還有一個很關鍵的差異,在大部分的書上都沒有提到,就是GET的response會被cache下來,但是POST不會。

由於cache的基準是以URL為對象,如果傳遞的參數不同時,很難發現cache的存在。但如果URL相同時,就可能造成程式出現靈異現象。舉例來說,我的同事剛好在撰寫一個AJAX版本的聊天室範例,由於純屬示範性質,所以採取很簡單的作法(事實上有許多上線運作的聊天室也用同樣的方法),將參與聊天的發言不斷增補到一個文字檔尾端,而用戶端就透過AJAX機制,定時向伺服端取回儲存發言的文字檔,顯示在瀏覽器上的聊天區域。

假設這個文字檔就叫做chat.txt,你可以想像會發生甚麼事。由於我的同事使用GET方式叫用XMLHttpRequest的open方法,並且URL參數都指定為"chat.txt",所以每次取回的都是cache中的chat.txt,造成不論如何發言,瀏覽器上顯示的結果都沒有變化,好像剛剛的發言石沈大海一樣。

有些人為了解決這個問題,採用了一些小伎倆,例如將URL參數改為傳入"chat.txt?"再加上日期時間,強迫URL每次都不一樣,而使得瀏覽器不會傳回cache中的檔案。這樣的作法固然有效,不過最簡單的方法,就是將GET改成POST,就一切正常了。

GET與POST的這點差異,主要是因為GET原始設計的語意,就是單純的查詢,只要是相同的查詢條件(傳遞的參數內容),不論查詢幾次都應該傳回相同的結果。由於這樣的原因,瀏覽器端的實作就會把GET的response給cache下來。反觀POST,原本的語意就是將資料遞送回伺服端處理,所以瀏覽器就不應該自作聰明,不將資料傳回給伺服端而逕行取用cache。

GET與POST的這點差異雖然很不容易發現,但在除錯環境困難的AJAX程式開發中,卻很可能讓程式員耗費時間精力,找不出問題在哪裡。

延伸閱讀

19 則留言:

匿名 提到...

Cool! :-)

匿名 提到...

您這篇文章讓我解決了一個很討厭的鬼打牆問題,在此留下文章以感謝之,謝謝你。

meebox 提到...

能幫到忙我也很開心,當初也是跟同事弄了很久,才確定原因的哩!

charleenchiu 提到...

一大朵疑雲消散了!超級感謝!

meebox 提到...

高興能幫到忙!

匿名 提到...

您好,這篇文章對我很有用,我希望能轉貼到我的部落格...純屬自己蒐藏觀看用的。如有不妥,歡迎告知我,會立即刪除。http://www.wretch.cc/blog/abc30678

chunweiko 提到...
作者已經移除這則留言。
chunweiko 提到...

你好...我是上篇匿名留言的訪客,其實也不是"蒐藏觀看",是因為作業的關係,本身是資訊相關科系學生,所以想把一些有用的資訊轉貼蒐集起來,是怕以後該網站或資訊如果消失了,還可以看的到。上面網址是我的blog,如有不妥,歡迎告知我刪除,造成不便還請見諒。

meebox 提到...

只要註明原出處,轉載沒問題,雖然我比較鼓勵轉貼連結!

Unknown 提到...

您好,因為小弟有在寫Web Application,故借收錄到個人的Blog參考用,已註明出處,謝謝囉,如果有問題再麻煩回信或留言給我。

meebox 提到...

Wallace,沒問題的,能幫上忙我很開心啊!

匿名 提到...

讚!!感謝您~~

meebox 提到...

謝謝

匿名 提到...

very good sharing, thank you!

Cloud 提到...

請問是否只有使用 ajax 才會有"使用 GET 方法會 cache 的情況"?

我寫了一個單純的 test.aspx 測試頁, 在程式內回傳目前時間, 回傳時間是會變化的, 這跟文章內寫到用 GET 會 cache 的情況不同, 還請解惑, 謝謝.

meebox 提到...

這樣我無法判斷,可能要請您貼一下程式?

Cloud 提到...

測試程式, 於瀏覽器中開啟 default.aspx
GET /Default.aspx HTTP/1.1

default.cs 中的程式碼
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(" Time:" + DateTime.Now.ToString());
}

Boton 提到...
作者已經移除這則留言。
匿名 提到...

簡單清楚
水喔~!