HTTP:Form表单的交互与抓包
HTTP協議的學習,我之前避開了最基礎最概念的東西,寫到現在,我發現若是以前從來沒接觸過服務端,沒了解過抓包,還不知道ABNF的一些核心規則。根本沒法繼續學下去
網絡協議的概念實在太多,不動手實操一下,不僅記不住還難以理解。今天我們就與HTTP協議,進行一次親密接觸~
今天我在這兒就借著Form表單提交發生的HTTP傳輸,來說下如何搭建Web服務器,以及如何抓包
關于ABNF的語法之后會結合實踐,專門寫一篇ABNF核心規則是如何描述HTTP的
今天我們就先來說一下Web服務的搭建吧,搭建服務器對應的代碼,我已經放到了GitHub倉庫上,文章中就僅截取片段代碼了。GitHub Repo地址點擊跳轉,也可以直接clone到你們自己本地
https://github.com/AdolphKevin/http-study-go.git
剛好我們大多數讀者也正在學習Golang,我們就用Golang來搭建一個我們自己的服務端,用來與客戶端交互,最后我們再用wireshark切身體會一下HTTP協議的傳輸過程
我在這選擇的框架是beego,原因就是搭建Web服務器快,而且文檔都是中文文檔,有興趣深入了解框架的可以更方便的學習,最最重要的一點,用go get命令安裝時不會被墻
我們就先把環境搭建起來,在這需要安裝的東西有
beego bee wireshark如果還沒有安裝過go的,可以看我之前的文章Vscode搭建go開發環境
beego以及bee的安裝
$ go get -u github.com/astaxie/beego $ go get -u github.com/beego/bee我在這唯一值得提一點的事情就是bee的環境配置,這點網上雖然有,但是一堆坑。文檔也沒明說,所以我在這說一下
Mac/Linux下的bee配置
不是把下面的內容全部放到Terminal里面執行的,具體的執行步驟寫在注釋里了
# 打開配置文件 Vim ~/.bash_profile ## 加入下面兩行 export GOPATH=/Users/naonao/go export PATH=${PATH}:${GOPATH}/bin ## 重啟配置文件 source ~/.bash_profile不知道GOPATH的路徑在哪里,可以執行下go env看看
在這我都說聲抱歉,因為在外面出差,Windows下我沒電腦搭建,所以沒法寫具體的操作步驟了,各位網上找找吧。思路就是將GOPATH下的bin文件夾,加入環境變量里
搭建Web服務器
配置好環境變量后,我們可以快速的搭建自己的Web服務器
Mac或者Linux直接在Terminal里在GOPATH/src目錄選執行bee new '項目名稱'即可
## 進入GOPATH/src目錄 cd ${GOPATH}/src ## 新建項目 bee new httpProject在Windows下就在GOPATH/src目錄下打開cmd執行bee new httpProject即可
執行完之后可以在GOPATH的src目錄下看到新建了一個非常標準的MVC項目
默認的新建項目肯定不能符合我們的需求,所以我們要稍加改進
我們先在router/router.go中的init方法里添加一個路由,用來處理請求
beego.Router("/sendhttp", &controllers.MainController{})再到controllers里的default.go文件中,添加如下代碼,熟悉MVC的讀者大人肯定知道控制器接受用戶的輸入并調用模型和視圖去完成用戶的需求
所以我們得完善一下控制器收到請求后的處理,在這里我加了一個GET請求與POST請求
// Get 請求方法 func (c *MainController) Get() {c.Data["Website"] = "beego.me"c.Data["Email"] = "NaoNao@gmail.com"c.TplName = "index.html" }// Post 請求方法 func (c *MainController) Post() {c.Data["Website"] = "NaoNao"c.Data["Email"] = "AdolfYin@gmail.com"c.TplName = "naonao.html" }代碼的意思就是GET請求返回index.html頁面,POST請求返回naonao.html頁面
所以我們還需要再到view里,添加index.html以及naonao.html文件
index.html文件里的完整內容大家去github上看好了,因為貼這種代碼極其影響閱讀體驗。index.html地址
html里的關鍵代碼如下,就是四種表單的提交
<p>GET方法默認提交</p><form action="/sendhttp" method="GET"> </form><p>POST方法默認提交</p><form action="/sendhttp" method="POST"></form><p>POST方法以application/x-www-form-urlencoded提交</p><form action="/sendhttp" method="POST" enctype="application/x-www-form-urlencoded"> </form><p>POST方法,以multipart/form-data提交</p><form action="/sendhttp" method="POST" enctype="multipart/form-data">待會我們再用wireshark抓包工具來看,這四種不同的提交方式到底有何不同
好啦,說到這,我們已經完成了環境的搭建,Web服務器的搭建以及請求和響應方式
不過在運行Web服務器和抓包之前,我得再說點HTTP里form表單的一些基礎知識,不然待會說抓包的時候,你可能會一臉懵逼
Form表單與HTTP的關系
關于form表單,它有三個核心的屬性,分別是action,method,enctype,這三個屬性,都是與發起HTTP協議時相關聯的
- action:提交表單時,發起一個HTTP請求,action用來表示請求的URI
- method:發起HTTP請求時,請求的方法是什么,比如是用GET還是POST
- enctype:在POST請求方法下,對表單內容在請求包體中的編碼格式,默認為application/x-www-form-urlencoded
action與method上面這樣簡單一提,我想大家心里都清楚怎么使用了,我就說下enctype的屬性好了
在application/x-www-form-urlencoded方式下,我們的數據會被編碼成以&分隔的鍵-值對,同時以=分隔鍵和值,也就是我們常說的key=value的形式
除了上面這種默認形式,還有multipart/form-data方式,這種方式提交的表單,我們的數據分隔之后,會以boundary開頭,最后以last boundary結尾。其中每一個部分的描述,皆有HTTP頭部描述子包體,比如Content-Type。主要應用一種比較復雜的結構體編碼
我們再重點看下multipart/form-data的提交方式
Content-Type來指明這是一個多表述包體,待會在wireshark中抓包我們就能看到
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryWiz1KWG5b5uvEUJR\r\n
這種提交方式下,每一個文本輸入,每一個單選框/復選框,每一個文件,都是作為一個獨立的資源表述的。如果不清楚HTTP的表述,可以看我之前分享的文章HTTP:資源是怎么協商、表述的?
而boundary分隔符的格式在ABNF語法中的定義為0*69<bchars> bcharsnospace
這是什么意思呢?這表示通過0~69(0*69)個字符(bchars)作為分隔符,也就是說最多不能超過70個字符
而這字符支持的格式(bcharsnospace),可以為DIGT/ALPHA/'/(/)/+/-/_/,/.///:/=/?
其中DIGT是數字的意思,ALPHA代表字母
所以各位自己抓包的時候,可以看看你們自己看到的分隔符是長啥樣的,偷懶的話,就回過頭去看看我抓的吧
開始抓包實踐
好啦,了解了form表單的HTTP關鍵屬性,熱身運動終于結束了。我們現在來運行我們的Web服務,來看一下我們的簡單演示
現在我們可以在${GOPATH}/src/http-study-go目錄下,使用go run main.go指令,即可運行我們剛剛搭建的Web服務器
用瀏覽器打開localhost:8080,即可訪問我們剛剛搭建的網站
接著我們打開wireshark,找到我們本機的局域網環境。如果不知道是哪一個,可以在打開wireshark后,打開我們自己剛剛搭建的網站localhost:8090,有網絡波動圖形的,就是我們需要監視的網絡
比如我下面截圖的這個,(注意:每臺電腦上的名稱不一樣,不要盲目抄作業)
想看看瀏覽器輸入URI后發生了什么事情的,可以在找我們的本機網絡后,用wireshark監視著,再打開瀏覽器輸入localhost:8080打開我們自己的Web服務器。這樣我們就能很清楚的看到TCP的三次握手(如下圖)
以后人家問你瀏覽器輸入URI按下回車后發生了什么事情,心里也有數了,看再多文章都不如自己動手試一試,當然了,這個不是今天的重點,今天就只提一下可以怎么看
繼續回到之前的內容,我們來看看form表單的提交是如何使用HTTP協議的
GET提交
我們先來看看GET提交是怎么一回事
我們先打開Chrome瀏覽器的開發者工具(F12),在使用GET方式提交表單,看看Network面板里是什么數據
我們可以看到發送了一個GET請求,將我們在表單中輸入的內容變成了QueryString的形式請求了URI
我們點擊一下旁邊的view Source,可以看到我們表單里填寫的數據,其實是以UTF-8的編碼格式進行的傳輸
我們再來看看wireshark中的抓包情況,看看是如何表現的,先找到我們剛剛發出的請求,點擊即可查看HTTP請求的內容
我們可以看到比Chrome中更詳細的信息,最下面的藍色區域,對應的是請求URI的Refere內容,左側的藍色區域是標準的ABNF語法,有興趣的可以去了解了解
POST提交
好了,我們再來看看不指定enctype的POST提交又發生了什么,
在這兒我就不貼Chrome里的Network面板內容了,直接展示wireshark中的內容了。需要注意的地方我都用紅線圈出來了
可以看到,跟GET提交相比,POST多了一個包體,點開Content-Length,我們可以看到請求的URI里已經沒有參數了,并且Content-Type里展示了我們的內容編碼方式
默認為application/x-www-form-urlencoded,后面的\r\n是換行符的意思
第三種POST提交并指定enctype=application/x-www-form-urlencoded的提交方式我在這就不多說了
我們重點來看看enctype=mulipart/form-data這種方式的提交
因為我們采用mulipart的方式請求,在請求中含有大量包體,在Chrome的Network面板中是看不到,所以我還是直接放wireshark抓取到的報文內容吧
在wireshark中找到我們請求的HTTP報文,我們可以看到,請求內容多了兩個
在Content-Type中,多了一個boundary,boundary后面的分隔符是以/r/n結尾的,并且在Content-Length中,最后我們可以看到分隔符是以--/r/n來結尾
多的另外一個東西,往下翻我們可以看到MIME multipart Media Encapsulation,這是包體中包含的資源文件
點開后我們可以發現,首先會有一個First boundary,里面的分隔符是以/r/n結尾,表示所有資源的開始。到最后會有一個Last boundary是以--/r/n結尾,表示所有資源的結束
其中每一個資源都有著一個分隔符,每一個在分隔符后面都是以\r\n結尾,直到最后一個資源,在\r\n的前面多了2個-,意味著整個請求包體的結束
點開其中的資源文件,會發現每一個資源文件都包含了Content-Disposition這個字段,因為這個是必須要有的,表示這個資源的name
如果是非文本框之類的東西,還會有一個Contenty-Type用于表示這個資源的類型
以我提交的文本文件來說一下,圖中我圈出來了
可以看到Content-Type告訴我,上傳的是一個text/plain的文件,點開下面的text data,可以看到里面傳輸的內容為NaoNaoChiYu
所有的資源文件傳輸完后,最后會以一個Last boundary的分隔符并加上--/r/n來結尾
這就是一個完整的表單提交發生的HTTP傳輸
寫在最后
最后給大家留一個問題。如果Form表單中的字段,沒有name,只有id,資源中的Content-Disposition內容是什么?是否還會有這個內容?如果沒有的話,服務器還能接收到這個資源文件么?
好了,今天借著說Form表單提交的方式,給大家說了下怎么搭建自己的Web服務,以及如何抓包
之后我會補一篇HTTP用ABNF語法表述的入門文章,因為我說過,我會以實踐的方式來寫HTTP協議的系列,所以后面的文章會有更多的內容牽扯抓包
如果看不懂ABNF語法,那看抓包的內容真的就是看天書了
馬上月底了,下一篇文章就不寫技術干貨了,分享點別的內容。
畢竟收租時間到了,要開贊賞了。寫技術干貨都沒人看,沒人看就沒人交租了…在外面出差過著9 11 7的日子,我還保持了穩定的每周二更新…這倆月我自己都佩服我自己了
總結
以上是生活随笔為你收集整理的HTTP:Form表单的交互与抓包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NFS共享储存
- 下一篇: js继承(ES5,ES6)