代码改变世界

http 的Get和 Post请求深入分析

2011-10-10 15:14  Shawn.Cheng  阅读(440)  评论(0编辑  收藏  举报

http Form表单的Get和 Post请求深入分析

个人博客地址 http://blog.csdn.net/nndtdx

这个话提已经开始了好久,一直没有写。今天提出来,就把这个问题给深入的分析一下。

这里,我使用Fiddler跟踪表单的提交过程。探究一下Get方式提交和Post方式提交的差别究竟在哪里。

首先建立一个页面,该页面实现表单的基本提交。在测试中使用GET方式提交。

该页面编码如下

<body>
<form method="get"action="target.html" name="form">
<inputtype="hidden" name="op" value="hello"/>
<inputtype="checkbox" name="chkName"value="chkValue">
<inputtype="txt" name="txtname">
<ahref="#" onclick="form.submit()">GET方式提交</a>
</form>
</body>



 

这里使用的是a标签的提交,调用了js方法进行表单提交。

我们先看一下请求该页面本身的情况。

使用Fiddler抓包得到的数据如下

GEThttp://218.196.204.43:8081/HttpStudy/httpstudy.html HTTP/1.1

Host:218.196.204.43:8081

Proxy-Connection:keep-alive

Cache-Control:max-age=0

Proxy-Authorization:Basic Y2p0OmNoZW5namluZ3RhbzEyMy0=

User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)Chrome/14.0.835.202 Safari/535.1

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Encoding:gzip,deflate,sdch

Accept-Language:zh-CN,zh;q=0.8

Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3

If-None-Match:"0e412bb787cc1:0"

If-Modified-Since:Mon, 10 Oct 2011 04:47:36 GMT

 

看得出来,这是http协议的请求头http reqest header,这里边包含里request header 的各种字段。不同的字段代表不同的含义。如果你要想深入理解各个字段的含义,你可以在这里http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html找到他。其实常用的不算多,等你需要了解某一个时再去查效果可能更好,因为看那些东西毕竟枯燥而空洞。这里,我是使用了代理上网的,所以会有Proxy 相关字段。

对于该次学习本身,客户端只是对http://218.196.204.43:8081/HttpStudy/httpstudy.html页面发出了 get 请求。ok,我们现在点击连接提交一下表单试一下。(我勾选上了chkbox在txt中填入中国)

 

GEThttp://218.196.204.43:8081/HttpStudy/target.html?op=hello&chkName=chkValue&txtname=%E4%B8%AD%E5%9B%BDHTTP/1.1

Host:218.196.204.43:8081

Proxy-Connection:keep-alive

Proxy-Authorization:Basic Y2p0OmNoZW5namluZ3RhbzEyMy0=

User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)Chrome/14.0.835.202 Safari/535.1

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Referer:http://218.196.204.43:8081/HttpStudy/httpstudy.html

Accept-Encoding:gzip,deflate,sdch

Accept-Language:zh-CN,zh;q=0.8

Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3

 

同样,第一个页面向服务端发起了get请求。请求的地址是http://218.196.204.43:8081/HttpStudy/target.html?op=hello&chkName=chkValue&txtname=%E4%B8%AD%E5%9B%BD 这个地址中含有请求的目标页面,以及请求时附带的信息。这些信息的组织是很有规律的。可以看出来,是以表单中的各个控件的name=value& 的格式组织的 。这样就将表单中的数据提交给服务器的某一个页面target.html,那么该目标页面就会进行相应的处理,返回一定的结果给客户端。在整个过程中请求实体都是空的。

上边,我们使用a标签进行的提交,此种情况下,并不会将a表签的信息提交进去。下边是我在a标签下加了一个submit类型的input ,点击后的提交url

http://218.196.204.43:8081/HttpStudy/target.html?op=hello&chkName=on&txtname=&btnName=submit

我把chkbox的value值也去掉了。

可以看出,chkbox的传递的值是on,按钮也将自己的value值传了进去。Txtbox为空,没有填写任何内容。

当我没有选择chkbox时,该url中并没有传递该参数。

到目前为止,我们已经基本能够确定了,Form表单的get提交,将会将表单内部的控件以name=value并且以&为连接形成数据信息放在url中,提交到服务器。

接下来,我们看一下Post方式的提交

同样是上述代码,将Get改为post

<body>
<form method="post"action="target.html" name="form">
<input type="hidden" name="op"value="hello"/>
<input type="checkbox"name="chkName">
<input type="txt"name="txtname">
<a href="#" onclick="form.submit()">Post方式提交</a>
<input type="submit"name="btnName" value="submit"/>
</form>
</body>



这样直接点击按钮会出现一个406错误,不允许用于访问此页的 HTTP 谓词。原因是html页面本身是 不可执行的(post方式提交本意是让服务器接受数据后,进行处理)所以,出先错误。我们在建立一个target.aspx页面,里边什么都不写,只用来接受数据。

Ok,修改后的代码如下。

<body>
<formmethod="post" action="target.aspx"name="form">
<input type="hidden"name="op" value="hello"/>
<input type="checkbox"name="chkName">
<input type="txt"name="txtname">
<a href="#" onclick="form.submit()">POST方式提交</a>
<input type="submit"name="btnName" value="submit"/>
</form>
</body>



点击提交按钮,查看fiddler捕捉到信息如下

POSThttp://218.196.204.43:8081/HttpStudy/target.aspx HTTP/1.1

Host:218.196.204.43:8081

Proxy-Connection:keep-alive

Content-Length:48

Cache-Control:max-age=0

Proxy-Authorization:Basic Y2p0OmNoZW5namluZ3RhbzEyMy0=

Origin:http://218.196.204.43:8081

User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)Chrome/14.0.835.202 Safari/535.1

Content-Type:application/x-www-form-urlencoded

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Referer:http://218.196.204.43:8081/HttpStudy/httpstudy.html

Accept-Encoding:gzip,deflate,sdch

Accept-Language:zh-CN,zh;q=0.8

Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3

 

op=hello&chkName=on&txtname=hahah&btnName=submit

 

可以看出,客户端向 http://218.196.204.43:8081/HttpStudy/target.aspx页面进行了数据提交。Content-length字段表明了提交内容的长度。request header 下空一行的部分是request entity。可以看出它的内容组织方式。

op=hello&chkName=on&txtname=hahah&btnName=submit和刚才的get方式提交的数据格式是一致的。

 

综上,get和post提交时数据存储的位置不相同,前者在url中,后者在请求的实体中保存。数据的组织格式相同,都是将当前form标签中的各个控件的状态传给服务器,即name=value的形式。

其实,就协议本身来讲,get方式的提交是安全的,他只是向服务器去获取数据,服务器并会由于该次请求而对服务器的数据产生具有影响性的操作。即get是只读的。而post 是客户端向服务器提交数据,服务器获取该数据后,要对服务器上的数据进行处理,进行一系列的操作,不是安全的。而二者提交时数据存放的位置不尽相同。前者,存放在url后者在entity中,协议本身并没有对该部分的数据量进行限制,但是大多数web服务器,浏览器,都对url的长度有限制,这样就导致了get方式提交数据时数据数据量有限的情况。或许,我们应该换一种说法,get方式是请求数据,post更像是提交数据。

你可能会想,如果这样的话,就目前的web设计来说,岂不是很多都违背了get的只读特性?。嗯,对没错,就是这样,至少我这么认为。当前的设计不符合协议设计者当初的意图。客户端提交的方式有很多种,这里不再依依列举,我也只是对当前的get和post做了研究,其他了解不多,很多web技术目前也仅是支持get和post两种提交。

下边附上向百度框输入hello word时的fiddler数据捕捉情况。

GEThttp://www.baidu.com/s?wd=helloworld&rsv_bp=0&rsv_spt=3&n=2&inputT=1314HTTP/1.1

Host:www.baidu.com

Proxy-Connection:keep-alive

Proxy-Authorization:Basic Y2p0OmNoZW5namluZ3RhbzEyMy0=

User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko)Chrome/14.0.835.202 Safari/535.1

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Referer:http://www.baidu.com/

Accept-Encoding:gzip,deflate,sdch

Accept-Language:zh-CN,zh;q=0.8

Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3

Cookie://很长不再粘贴

 

<!DOCTYPEhtml><!--STATUS OK--><html><head>

<metahttp-equiv="X-UA-Compatible" content="IE=7">

<metahttp-equiv="content-type"content="text/html;charset=gb2312">

<title>百度搜索_helloworld      </title>

//页面的html内容。。。

 

可以看出来entity中保存了该页面的响应内容,该响应内容返回给客户端,客户端接受解析,在浏览器中显示。

 

Ok,这个话题就暂时探究到这里,在接下来,会学习一下ASP.NET的数据提交。