在 W3C RFC 2616 中說明 HTTP/1.1規範中共有8種方法來以不同方式操作指定的資源。
- GET
- POST
- PUT
- DELETE
- HEAD
- OPTIONS
- TRACE
- CONNECT
- PATCH
1. 根據HTTP/1.1規範,Get用於資訊獲取,而且應該是安全的、冪等的。
- 所謂安全的意味著該操作用於獲取資訊而非修改資訊。換句話說,Get請求一般不應產生副作用。就是說,它僅僅是獲取資源資訊,就像資料庫查詢一樣,不會修改或增加資料,不會影響資源的狀態。(注意:這裡安全的含義僅僅是指是非修改資訊。)
- 冪等(idempotent)的意味著對同一URL的多個請求應該返回同樣的結果。根據 HTTP 規格,Gst、Head、Put 和 Delete 是 idempotent,相同的 Request 再執行一次,結果還是一樣。
- 這裡說的改變,包括增加、修改和刪除。
- Post不是冪等。
以下將以 HTTP/1.1規範內容、收集資料, 將Get與Post做比較列表,讓大家比較有感覺:
項目
|
Get
|
Post
|
主要用途
|
用於與伺服器獲取/查詢資源資訊
|
用於向伺服器傳送、變更資源資訊
|
資料傳送量
|
數據傳輸量小
由於數據放在URL裡傳遞給服務器處理,資料傳送長度受限於URL。註1 |
傳送大量資料
由於不透過 URL帶參數,所以不受限於URL長度。 |
支援字元集與編碼註2
|
使用7位元的ASCII註3
|
支援ISO10646字元集
預設使用ISO 8859-1編碼(ISO 8859-1包括了ASCII) |
傳送安全性
|
低
表單參數與寫內容可在URL看到。 |
高
透過 HTTP Request 方式,參數與填寫內容不會顯示於URL。 |
資料傳送前後網址變化
|
網址會帶有表單的參數與資料。
|
網址不會改變。
|
傳輸方式
|
在Request-URI中傳輸
(在URL中傳輸) |
在Request-URI傳輸
(為隱藏傳輸) |
傳送
|
用戶端用QueryString傳送數據註4
|
用戶端用Message-Body傳送Form的數據註5
|
冪等方法註6
|
是
|
否
|
是否被Cache註7
|
是
|
否
|
傳輸安全性
|
差
|
好
|
執行效率
|
好
|
差
|
其他
|
預設傳輸方法
|
註1. 各家瀏覽器URL使用長度限制如下。
瀏覽器
|
最大長度(字元數)
|
備註
|
Internet Explorer
|
2,083
|
如果超過這個數位,提交按鈕沒有任何反應
|
Firefox
|
65,536
|
|
chrome
|
8,182
|
|
Safari
|
80,000
|
|
Opera
|
190,000
|
|
curl(linux下指令)
|
8,167
|
註2. 請參考 關於URL編碼。
註3. 請參考 C/C++中文問題探討。
註4. Querystring(查詢字串)是附加在網頁URL結尾的資訊。主要是在Url上傳遞資料,可能是一個搜尋字串、頁碼、某項特定的指標…或類似的東西,在網址結尾加上一個問號 ( ? ) 開始,每一組參數都是用「&」區隔開來,是一種Key / Value的組合。
註5. 請參考 RFC 2188: Returning Values from Forms: multipart/form-data,這份文件說明了在 HTTP POST 訊息中使用多種格式訊息的作法。
註6. 冪等觀念延伸數學定義而來,有興趣可參考維基。簡單說就是使用相同方法、參數,對同一網址列進行多次資料存取,其伺服器接收與回傳的資料內容都不會新增改變。
註7. Cache為PC系統中用來紀錄被使用過或參考過的資源位置,當該資源需要再度被使用時,可直接透過Cache中的紀錄直接使用,主要是用來加速資料的存取,一般在CPU中都有Cache來做為系統存取加速使用。同樣觀念套用至瀏覽器上,只要透過URL存取過的網站,都會被記錄於瀏覽器的Cache上。
筆者這用以下段程式碼的執行結果來搭配說明Get的Post差異:
Test.php
<?php //以下php內容為Server端處理資料 header("Content-Type:text/html; charset=big5"); //從Server取得Get、Post或其他方法傳送進來的資料 $method = $_SERVER['REQUEST_METHOD']; //判別資料來源類型做轉換,確認是否有資料存在 switch ($method){ case 'GET': $parameters = $_GET; break; case 'POST': $parameters = $_POST; break; } //isset判別網頁剛開啟時,未傳進參數時會出現"Notice: Undefined index"這樣的警告 //處理方法 http://alfredwebdesign.blogspot.tw/2013/05/php-notice-undefined-index.html $acc = isset($parameters['Acc'])? $parameters['Acc'] : 0; //帳號 $pwd = isset($parameters['Pwd'])? $parameters['Pwd'] : 0; //密碼 $hid = isset($parameters['Hid'])? $parameters['Hid'] : 0; //隱藏內容,為網頁常見的使用方法 $isAllNull = empty($acc) && empty($pwd) && empty($test) ; ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <title>Form method : Get與Post測試</title> <meta http-equiv="Content-Type" content="text/html; charset=Big5"> <!--以下JavaScript內容為Client端處理--> <script language="JavaScript"> //設定表單使用Post傳送內容 function PostInfo(Formname, action, method) { var f = document.forms[Formname]; f.action = action; f.method = method; f.submit(); return true; } //寫入內容到DIV或SPAN function WriteOnScreen() { var info; info = "帳號 : " + document.getElementById("Acc").value + "<br/ >"; info = info + "密碼 : " + document.getElementById("Pwd").value + "<br/ >"; info = info + "隱藏 : " + document.getElementById("Hide").value; document.getElementById("screen").innerHTML = info; } </script> <body> <!--以下HTML內容為Client端處理--> <form id="Form01" name="myForm" action="Test.php" method=""> 帳號 : <input type="text" name="Acc" id="Acc" size="14" /> <br/ > 密碼 : <input type="password" name="Pwd" id="Pwd" size="14" /> <br/ > <input type="hidden" name="Hid" id="Hide" value='Test'/> <input type="submit" value="使用Get傳送表單資料" /><br/ > <input type="button" value="使用Post傳送表單資料" onclick="PostInfo('myForm', 'Test.php', 'POST');" /><br/ > <input type="button" value="直接抓取" onclick="WriteOnScreen();" /> </form> <?php //以下php內容為Server端處理資料 if(!$isAllNull){ echo $method; echo '<br/ >'; echo '================<br/ >'; echo '帳號 : '.$acc.' <br/ >'; echo '密碼 : '.$pwd.' <br/ >'; echo '隱藏 : '.$hid.' <br/ >'; echo '================<br/ >'; } ?> <div id ="screen" > </div> </body> </html>以上程式碼感謝Line群裡的清權大大協助完成。
執行以上程式碼需要php的環境,若是為了要執行以上程式碼要大家安裝去Apache 與php,將是一件大工程,筆者這裡推薦一個簡易版的伺服器系統:Usbwebserver,大家可以去官網下載無須安裝、操作簡易、容易擴充、方便使用、檔案大小約82 MB一個隨身碟即可帶著走,使用教學。
我們來看看程式碼執行Get與Post表單時,如何去傳送資料給Server,各位可以再對照上面列表的內容,就會看的出來兩者之間的差異。
Get傳送
如上圖,Get傳送資料從Client至Server
1. 透過瀏覽器的URL進行傳送。
2. 資料若為非ASCII,會將其編碼後再行傳送。
3. 將資料以Query String形式進行傳送。
Post傳送
如上圖,Post傳送資料從Client至Server
1. 不透過URL傳送,以Form Data形式進行傳送。
2. 資料若為非ASCII,會將其編碼後再行傳送。
3. Content-type若無指定,將以application/x-www-form-urlencoded為預設傳輸。
觀念糾正:
1. HTTP/1.1規範中,Method(Get、Post)和Data(URL, Body, Header)是正交(獨立)的兩個概念,也就是說,使用哪個Method與應用層的資料如何傳輸是沒有相互關係。
2. HTTP/1.1規範沒有要求,如果Method是Post資料就要放在Body中。也沒有要求,如果Method是Get,資料(參數)就一定要放在URL中而不能放在Cache中。
3. 由於Cache的基準是以URL為對象,如果傳遞的參數不同時,很難發現cache的存在,因為Cache內容沒有新紀錄。
4. HTTP/1.1規範,如果伺服端指定適當的Cache-Control或Expires標頭,仍可以對POST的回應進行快取。
5. HTTP/1.1規範 中並沒有特定限制Get或Post資料傳送的長度限制,但實際各個Web伺服器會規定對Post提交數據大小進行限制,Apache、IIS6都有各自的配置。
6. 大家誤解的資料傳輸的方法只有Get與Post,原因如下
- 現在對於表單傳送大多僅介紹Get與Post。
- 網頁工程師可能對於其他方法不熟悉。
- 對於網路資源的操作可透過Get、Post做 查、改、增、刪 的功能,不需用到Put和Delete。
其他補充內容:
1. Post:請求參數是在http標題的一個不同部分(名為entity body)傳輸的,這一部分用來傳輸表單信息,因此必須將Content-type設置為:application/x-www-form-urlencoded。Post設計用來支持web窗體上的用戶字段,其參數也是作為key/value對傳輸。
但是:它不支持複雜數據類型,因為Post沒有定義傳輸數據結構的語義和規則。
2. soap:是http post的一個專用版本,遵循一種特殊的xml消息格式
Content-type設置為: text/xml任何數據都可以xml化
如以上關於Get與Post內容敘述有錯,歡迎糾正,謝謝。
參考資料:
- 淺談HTTP中Get與Post的區別
- HTTP Verbs: 談 POST, PUT 和 PATCH 的應用
- GET、POST與cache的關係
- 網頁設計流程的GET和POST有何差別?
- HTTP POST GET 本質區別詳解 (轉載)
- HTTP GET and POST basic
- HTTP POST 使用的編碼格式
- 另一篇:用XMLHTTP Post/Get HTML頁面時的中文亂碼問題之完全Script解決方案
- 四种常见的 POST 提交数据方式
- PHP 使用 file_get_contents 接收 POST 的資料
- get和post的区别
- get和post請求的區別
- [.NET] QueryString 的那些事
- 網路爬蟲系列 (Crawler) (1) : 使用Chrome「檢查元素」找出 PChome購物網站 資料位置
- 網路爬蟲系列 (Crawler) (2) : 使用Chrome「檢查元素」找出「證交所」加權股價指數歷史資料下載的方法
- 網路爬蟲系列 (Crawler) (3) : 使用FireFox「檢測元素」、外掛Cookies Manager+、HackBar抓臺灣證交所買賣日報表資料