HTTP Get 與 Post Method
會寫這篇文章的原因為某位正在唸書的同學向我提出的疑問,讓我發現 HTTP Method 的觀念其實在現在的教育中相當缺乏。以往經驗,大部分的學校課程都會直接傳授網頁程式設計等課程,卻忽略這十年來最廣泛使用的 HTTP 協定。
GET 與 POST 有寫過網頁表單的人一定不陌生,但你了解什麼是 GET 與 POST 嗎!? 現今的網頁設計工具相當的發達,甚至不需要接觸 HTML 語法就能完成一個規模不小的網站,漸漸地很多人都忘記了 HTTP 底層的實作原理,造成在發生錯誤的情況下無法正確進行偵錯。
早期在撰寫 HTML 表單語法時,都會寫到以下的寫法,然而大部分的程式設計師都會採用 POST 進行表單傳送。
<form action="" method="POST/GET"> </form>
然而在我們的網頁程式中要獲取表單的變數只需要呼叫系統已經封裝好的方法即可,像是 PHP 使用 $_REQUEST、JAVA 使用 getParameter()、ASP 使用 Request.Form() 這些方法等等。
由上述的方法看來,似乎用 POST 或 GET 好像不是很重要。許多網頁程式設計師對於表單 method 用法的記憶為"POST可以傳送比較多的資料"、"表單傳送檔案的時候要使用 POST"、"POST比GET安全"等等奇怪的概念。
What’s HTTP Method ??
其實使用 POST 或 GET 其實是有差別的,我們先說明一下 HTTP Method,在 HTTP 1.1 的版本中定義了八種 Method (方法),如下所示:
- OPTIONS
- GET
- HEAD
- POST
- PUT
- DELETE
- TRACE
- CONNECT
天阿,這些方法看起來真是陌生。而我們使用的表單只用了其中兩個方法 (GET/POST),其他的方法確實很少用到,但是在 RESTful 的設計架構中就會使用到更多的 Method 來簡化設計,有機會再與大家介紹。
GET vs POST Method
先舉個例子,如果 HTTP 代表現在我們現實生活中寄信的機制,那麼信封的撰寫格式就是 HTTP。我們姑且將信封外的內容稱為 http-header,信封內的書信稱為 message-body,那麼 HTTP Method 就是你要告訴郵差的寄信規則。
假設 GET 表示信封內不得裝信件的寄送方式,如同是明信片一樣(感謝網友 Kevin 的建議,採用明信片來詮釋 GET),你可以把要傳遞的資訊寫在信封(http-header)上,寫滿為止,價格比較便宜。然而 POST 就是信封內有裝信件的寄送方式(信封有內容物),不但信封可以寫東西,信封內 (message-body) 還可以置入你想要寄送的資料或檔案,價格較貴。
使用 GET 的時候我們直接將要傳送的資料以 Query String(一種Key/Vaule的編碼方式)加在我們要寄送的地址(URL)後面,然後交給郵差傳送。使用 POST 的時候則是將寄送地址(URL)寫在信封上,另外將要傳送的資料寫在另一張信紙後,將信紙放到信封裡面,交給郵差傳送。
接著我來介紹一下實際的運作情況:
我們先來看看 GET 怎麼傳送資料的,當我們送出一個 GET 表單時,如下範例:
<form method="get" action=""> <input type="text" name="id" /> <input type="submit" /> </form>
當表單 Submit 之後瀏覽器的網址就變成 "http://xxx.toright.com/?id=010101",瀏覽器會自動將表單內容轉為 Query String 加在 URL 進行連線。
這時後來看一下 HTTP Request 封包的內容:
GET /?id=010101 HTTP/1.1 Host: xxx.toright.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 GTB7.1 ( .NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-tw,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: UTF-8,* Keep-Alive: 115 Connection: keep-alive
在 HTTP GET Method 中是不允許在 message-body 中傳遞資料的,因為是 GET 嘛,就是要取資料的意思。
從瀏覽器的網址列就可以看見我們表單要傳送的資料,若是要傳送密碼豈不是"一覽無遺".......這就是大家常提到安全性問題。
再來看看 POST 傳送資料
<form method="post" action=""> <input type="text" name="id" /> <input type="submit" /> </form>
網址列沒有變化,那我們來看一下 HTTP Request 封包的內容:
POST / HTTP/1.1 Host: xxx.toright.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-TW; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 GTB7.1 ( .NET CLR 3.5.30729) Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-tw,en-us;q=0.7,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: UTF-8,* Keep-Alive: 115 Connection: keep-alive Content-Type: application/x-www-form-urlencoded </code><code>Content-Length: 9 id=010101
看出個所以然了嗎?原來 POST 是將表單資料放在 message-body 進行傳送,在不偷看封包的情況下似乎安全一些些.......-_- 。此外在傳送檔案的時候會使用到 multi-part 編碼,將檔案與其他的表單欄位一併放在 message-body 中進行傳送。這就是 GET 與 POST 發送表單的差異囉。
關於 HTTP 更深入的介紹可以參考「淺談 REST 軟體架構風格 (Part.I) - 從了解 REST 到設計 RESTful!」系列文章。