2010年5月28日 星期五

HTTP GET and POST basic

HTTP(Hypertext Transfer Protocol)是網路上最普遍的一種訊息交換協定,基本上它就是用來向服務主機發出要求的基本通訊方式,當然網路上也有其他衍生模式,如HTTPS、FTP等等。本篇僅簡述HTTP項服務主機發出的兩種方式,與實際產生的格式。

如果你需要撰寫SERVER端的服務,就必須稍微了解HTTP發出的請求訊息會長什麼樣子。

GET
get是屬於比較基礎的請求方式,例如網頁連結
<a href="http://www.site.com/hello.html"></a>
產生的訊息就會如下
GET /hello.html HTTP/1.1
Host: www.site.com
User-Agent: Mozilla/4.0

如果是帶有參數的請求,例如利用連結或是表單
<a href="http://www.site.com/login.html?id=john&pwd=9982"></a>
<form action="http://www.site.com/login.html" method="GET">
  user ID:<input name="id" type="text" /><br />
  password:<input name="pwd" type="password" /><br />
  <input type="submit" value="login">
</form>

產生的結果就會如下
GET /login.html?id=john&pwd=9982 HTTP/1.1
Host: www.site.com
User-Agent: Mozilla/4.0

在 submit 後瀏覽器上面的URL字串就會出現
http://www.site.com/login.html?id=john&pwd=9982
GET雖然好用,但也有一些問題,例如GET字串長度不可以太長,目前多數瀏覽器多定義在256個字元以內,隱密性不足,遇到非英數字的字元會無法傳送(通常瀏覽器會將其字元解析成HEX如%65),參數名稱與內容不可以使用關鍵字等等問題存在。



POST
post是屬於進階的請求方式,它彌補了GET的不足性,但是操作起來會多些手續。好處是可以隱匿傳遞參數以及傳遞較多的資料。當然在server端要解析這樣的資料就得分析更多的資訊了。
常用的方式有分兩種,一種是表單參數傳遞,另一種就是檔案傳遞(或是複雜格式傳遞)

表單參數傳遞(application/x-www-form-urlencoded):
改寫上一段表單傳遞方式
<form action="http://www.site.com/login.html" method="POST" encttype="application/x-www-form-urlencoded">
  user ID:<input name="id" type="text" /><br />
  password:<input name="pwd" type="password" /><br />
  <input type="submit" value="login">
</form>

產生的結果就會如下
POSt /login.html HTTP/1.1
Host: www.site.com
User-Agent: Mozilla/4.0
Content-Length: 16
Content-Type: application/x-www-form-urlencoded

id=john&pwd=9982

可以看得出來參數的部份被放到下面去了,所以在 submit 後瀏覽器的URL字串僅會出現如下的訊息而已
http://www.site.com/login.html


檔案參數傳遞(multipart/form-data):
<form action="http://www.site.com/login.html" method="POST" encttype="multipart/form-data">
  user ID:<input name="id" type="text" /><br />
  password:<input name="pwd" type="password" /><br />
  file:<input name="myfile" type="file" /><br />
  <input type="submit" value="login">
</form>

如果myfile是給一個GIF圖檔,則產生的結果就會如下
POSt /login.html HTTP/1.1
Host: www.site.com
User-Agent: Mozilla/4.0
Content-Length: 16
Content-Type: multipart/form-data; boundary=0De5Ax9

--0De5Ax9
content-disposition: form-data; name="id"


john
--0De5Ax9
content-disposition: form-data; name="pwd"


9982
--0De5Ax9
content-disposition: form-data; name="myfile"
Content-type: image/gif
Content-Transfer-Encoding: binary


..圖片資料..
--0De5Ax9



如果傳送的是文字檔,則橘色部份會變成
--0De5Ax9
content-disposition: form-data; name="myfile"
Content-type: text/plain


..文字檔案資料..
--0De5Ax9


在上面的表單範例中你可以看到淺灰的 encttype 指令,這個指令一般而言可有可無,因為瀏覽器會判斷若表單中 input 項目type 屬性為 file 或是 textarea項目是否存在,如果存在則不管 encttype 是否有設定,都會自動將 encttype 強制為 multipart/form-data ,以符合傳輸特性。

但若是自己撰寫發送請求的程式則必須自行判斷並決定好POST的格式,以免server端不接受請求指令。

3 個回應:

匿名 提到...

好東西,謝謝您的心得整理。

提到...

RE: GET雖然好用,但也有一些問題,例如GET字串長度不可以太長,目前多數瀏覽器多定義在256個字元以內,隱密性不足,遇到非英數字的字元會無法傳送

這一點Coldfusion可以用urlencodedformat 和urldecode來傳URL的非英數的字串

WILDOX 提到...

TO 楊:
是的,可以這樣用。
我之所以會寫這一篇主要是因為我用的client端不是brower,所以不會使用server端的Form指令;甚至server端的服務也是自己撰寫的(不是使用IIS或是類似其他的http服務器)
因此,了解Http基本結構是非常必要的,傳輸過程的編解碼就得自己完成。
當然有人說server端既然不是標準http服務器,也就不一定要照標準的http header來做,但是我為將來考量,有一天,自製的服務器不再維護而轉成CF、ASP、JSP的話是否還能夠正常溝通就是很重要的。