HTTP协议与HTTP表单传输格式,再论get、post方法
2013-12-11 15:41
417 查看
HTTP的GET/POST方式有何区别?这是一个老生常谈的问题,但老生常谈的问题往往有一些让人误解的结论。本文将带您浅尝HTTP协议,在了解HTTP协议的同时将会展示许多被人们忽视的内容。在掌握了HTTP协议的过程中我们将自然而然地了解到GET与POST的本质区别。
用户端浏览器上输入的一个URL地址;
网页中的一个超链接;
提交一个HTML表单。
但本质上说,一个HTTP请求起始于用户端向HTTP服务器发送的一个URL请求。
一个标准的HTTP请求由以下几个部分组成
<request-line>
<headers>
<CRLF>
[<request-body><CRLF>]
在HTTP请求中,第一行是请求行(request-line),用来说明请求类型、要访问的资源(URL)以及使用的HTTP版本;
紧接着是多行头部(headers)信息,用来说明服务器要使用的附加信息;
头部信息之后是一个回车换行符(/r/n),用于标明头部信息的结束。
以上是必须内容,根据需要可在头部信息结束之后增加主体数据(request-body);
主体数据之后是一个回车换行符(/r/n),用于标明主体数据的结束。
需要注意的是
请求行(request-line)中的URL部分必须以application/x-www-form-urlencoded方式编码。
主体数据(request-body)的编码方式由头部(headers)信息中的Content-Type指定。
主体数据(request-body)的长度由头部(headers)信息中的Content-Length指定。
例如,我们可以在IE浏览器上输入下面的网址:
http://localhost:8000/hello/index.html
HTTP请求的头部信息如下:
GET /hello/index.html HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Host: localhost:8000
Connection: Keep-Alive
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6
[End]
上述信息没有request-body部分,这是以GET方式发送的HTTP请求。如果请求中需要附加主体数据,即增加request-body部分,则必须使用POST方式发送HTTP请求。HTML超链接(<a></a>)只能用GET方式提交HTTP请求,HTML表单(<form></form>)则可以使用两种方式提交HTTP请求。
[xhtml]
view plaincopyprint?
<form action="目标地址" method="发送方式" enctype="数据主体的编码方式">
<!-- 各类型的表单域 -->
<input name="NAME" value="VALUE"/>
<textarea name="NAME">VALUE</textarea>
<select name="NAME">
<option value="VALUE" selected="selected"/>
</select>
</form>
这样的表单是不符合要求的。如果其URL值存在非法字符(如中文字符),应将其进行URL Encoding处理。URL Encoding的处理方法如下:
字母数字字符 "a" 到 "z"、"A" 到 "Z" 和 "0" 到 "9" 保持不变。
特殊字符 "."、"-"、"*" 和 "_" 保持不变。
空格字符 " " 转换为一个加号 "+"。
所有其他字符都是不安全的,因此首先使用一种编码机制将它们转换为一个或多个字节。然后对每个字节用一个包含 3 个字符的字符串 "%xy" 表示,其中 xy 为该字节的两位十六进制表示形式。推荐的编码机制是 UTF-8。
将“中文”两个字符进行URL Encoding所得到的值就是“%E4%B8%AD%E6%96%87”。
所以正确的表单应该是:
[xhtml]
view plaincopyprint?
<!-- 符合要求的表单 -->
<form action="checkUser.html?opt=%E4%B8%AD%E6%96%87" method="POST">
</form>
表单提交时没有包括opt属性,HTTP头部信息如下:
GET /hello/checkUser.html?username=yyy&age=zzz HTTP/1.1
Referer: http://localhost:8000/hello/index.html
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Host: localhost:8000
Connection: Keep-Alive
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6
[End]
需要注意的是,以GET方式提交表单时,每个表单域的NAME与VALUE要以URL的方式提交,所以每个表单域的NAME与VALUE均要进行URL Encoding处理。这个操作通常是由用户端浏览器完成的。如下面的表单:
[xhtml]
view plaincopyprint?
<form action="checkUser.html" method="GET">
<input type="hidden" name="opt" value="中文"/>
<input type="text" name="username" value="yyy"/>
<input type="text" name="age" value="zzz"/>
<input type="submit" value="submit"/>
</form>
表单提交时,HTTP头部信息如下:
POST /hello/checkUser.html?opt=xxx HTTP/1.1
Referer: http://localhost:8000/hello/index.html
Accept: */*
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8000
Content-Length: 20
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6
username=yyy&age=zzz
[End]
需要注意的是,以POST方式提交表单时,action标签属性的值必须是已经进行了URL Encoding处理之后的值,用户端浏览器不会自动处理URL中的非法字符。如下面的表单是不符合要求的:
[xhtml]
view plaincopyprint?
<!-- 不符合要求的表单 -->
<form action="checkUser.html?opt=中文" method="POST">
<input type="text" name="username" value="yyy"/>
<input type="text" name="age" value="zzz"/>
<input type="submit" value="submit"/>
</form>
设置enctype标签属性后,在HTTP请求的头部(headers)信息中会多出一行Content-Type信息,并且request-body部分将会以Content-Type指定的MIME进行编码。这些操作都是由客户端浏览器自动完成的。
在没有指定enctype标签属性时,表单以默认的application/x-www-form-urlencoded方式对request-body进行编码。
如果表单域中的NAME或VALUE含有非法字符(如中文字符),客户端浏览器会自动对其进行URL Encoding处理。如下面的表单:
[xhtml]
view plaincopyprint?
<form action="checkUser.html" method="POST">
<input type="hidden" name="opt" value="中文"/>
<input type="text" name="username" value="yyy"/>
<input type="text" name="age" value="zzz"/>
<inupt type="submit" value="submit"/>
</form>
表单提交时HTTP头部信息如下:
POST /hello/checkUser.html?opt=xxx HTTP/1.1
Accept: */*
Referer: http://localhost:8000/hello/index.html
Accept-Language: zh-cn
Content-Type: multipart/form-data; boundary=---------------------------7d931c5d043e
Accept-Encoding: gzip, deflate
Host: localhost:8000
Content-Length: 382
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=6FE3D8E365DF9FE26221A32624470D24
-----------------------------7d931c5d043e
Content-Disposition: form-data; name="username"
yyy
-----------------------------7d931c5d043e
Content-Disposition: form-data; name="age"
zzz
-----------------------------7d931c5d043e
Content-Disposition: form-data; name="file"; filename="C:/1.txt"
Content-Type: text/plain
hello
-----------------------------7d931c5d043e--
[End]
GET方式在request-line中传送数据;POST方式在request-line及request-body中均可以传送数据。
回答:长度限制之说一方面是HTTP客户端(如IE限定URL长度为2083字节,opera 是4050, Netscape 是8192)的限制;另一方面服务器的实现也加入了限制(如果URL长度过长,HTTP服务器会报414错误)。但HTTP协议及URL官方说明均对长度限制则没有规定。
传言2:GET是从服务器上获取数据;POST是向服务器传送数据。
回答:GET方式就没有向服务器传送数据?那么URL中的?子句送的是什么?不论是GET还是POST,都可以向服务器传送数据,只不过传送数据的位置不同;不论是GET还是POST,都要从服务器上获取数据,否则IE浏览器拿什么东西给我们看呢?关键的问题是
GET的主要任务是获得数据,但在获得数据前也可以向服务器提交一些数据;
POST的主要任务是提交数据,但在提交数据之后服务器也会向用户端返回一些显示用的数据。
传言3:GET不安全,用户能从地址栏上看到传送的数据;POST安全,用户不能从地址栏上看到传送的数据。
回答:POST方式看不到传送的数据是因为IE浏览器做了限制。如果你通过第三方工具看到了POST方式传送的数据,你还能说POST方式是安全的吗?理论上说GET和POST方式都不安全,要不就用不着研究HTTPS了。
HTTP请求
从使用者的角度看,一个HTTP请求起始于用户端浏览器上输入的一个URL地址;
网页中的一个超链接;
提交一个HTML表单。
但本质上说,一个HTTP请求起始于用户端向HTTP服务器发送的一个URL请求。
一个标准的HTTP请求由以下几个部分组成
<request-line>
<headers>
<CRLF>
[<request-body><CRLF>]
在HTTP请求中,第一行是请求行(request-line),用来说明请求类型、要访问的资源(URL)以及使用的HTTP版本;
紧接着是多行头部(headers)信息,用来说明服务器要使用的附加信息;
头部信息之后是一个回车换行符(/r/n),用于标明头部信息的结束。
以上是必须内容,根据需要可在头部信息结束之后增加主体数据(request-body);
主体数据之后是一个回车换行符(/r/n),用于标明主体数据的结束。
需要注意的是
请求行(request-line)中的URL部分必须以application/x-www-form-urlencoded方式编码。
主体数据(request-body)的编码方式由头部(headers)信息中的Content-Type指定。
主体数据(request-body)的长度由头部(headers)信息中的Content-Length指定。
例如,我们可以在IE浏览器上输入下面的网址:
http://localhost:8000/hello/index.html
HTTP请求的头部信息如下:
GET /hello/index.html HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Host: localhost:8000
Connection: Keep-Alive
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6
[End]
上述信息没有request-body部分,这是以GET方式发送的HTTP请求。如果请求中需要附加主体数据,即增加request-body部分,则必须使用POST方式发送HTTP请求。HTML超链接(<a></a>)只能用GET方式提交HTTP请求,HTML表单(<form></form>)则可以使用两种方式提交HTTP请求。
HTML表单
HTML表单的使用方法如下:[xhtml]
view plaincopyprint?
<form action="目标地址" method="发送方式" enctype="数据主体的编码方式">
<!-- 各类型的表单域 -->
<input name="NAME" value="VALUE"/>
<textarea name="NAME">VALUE</textarea>
<select name="NAME">
<option value="VALUE" selected="selected"/>
</select>
</form>
[xhtml] view plaincopyprint? <!-- 不符合要求的表单 --> <form action="checkUser.html?opt=中文" method="POST"> </form> <!-- 不符合要求的表单 --> <form action="checkUser.html?opt=中文" method="POST"> </form>
这样的表单是不符合要求的。如果其URL值存在非法字符(如中文字符),应将其进行URL Encoding处理。URL Encoding的处理方法如下:
字母数字字符 "a" 到 "z"、"A" 到 "Z" 和 "0" 到 "9" 保持不变。
特殊字符 "."、"-"、"*" 和 "_" 保持不变。
空格字符 " " 转换为一个加号 "+"。
所有其他字符都是不安全的,因此首先使用一种编码机制将它们转换为一个或多个字节。然后对每个字节用一个包含 3 个字符的字符串 "%xy" 表示,其中 xy 为该字节的两位十六进制表示形式。推荐的编码机制是 UTF-8。
将“中文”两个字符进行URL Encoding所得到的值就是“%E4%B8%AD%E6%96%87”。
所以正确的表单应该是:
[xhtml]
view plaincopyprint?
<!-- 符合要求的表单 -->
<form action="checkUser.html?opt=%E4%B8%AD%E6%96%87" method="POST">
</form>
[xhtml] view plaincopyprint? <form action="checkUser.html?opt=xxx" method="GET"> <input type="text" name="username" value="yyy"/> <input type="text" name="age" value="zzz"/> <input type="submit" value="submit"/> </form> <form action="checkUser.html?opt=xxx" method="GET"> <input type="text" name="username" value="yyy"/> <input type="text" name="age" value="zzz"/> <input type="submit" value="submit"/> </form>
表单提交时没有包括opt属性,HTTP头部信息如下:
GET /hello/checkUser.html?username=yyy&age=zzz HTTP/1.1
Referer: http://localhost:8000/hello/index.html
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Host: localhost:8000
Connection: Keep-Alive
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6
[End]
需要注意的是,以GET方式提交表单时,每个表单域的NAME与VALUE要以URL的方式提交,所以每个表单域的NAME与VALUE均要进行URL Encoding处理。这个操作通常是由用户端浏览器完成的。如下面的表单:
[xhtml]
view plaincopyprint?
<form action="checkUser.html" method="GET">
<input type="hidden" name="opt" value="中文"/>
<input type="text" name="username" value="yyy"/>
<input type="text" name="age" value="zzz"/>
<input type="submit" value="submit"/>
</form>
[xhtml] view plaincopyprint? <form action="checkUser.html?opt=xxx" method="POST"> <input type="text" name="username" value="yyy"/> <input type="text" name="age" value="zzz"/> <input type="submit" value="submit"/> </form> <form action="checkUser.html?opt=xxx" method="POST"> <input type="text" name="username" value="yyy"/> <input type="text" name="age" value="zzz"/> <input type="submit" value="submit"/> </form>
表单提交时,HTTP头部信息如下:
POST /hello/checkUser.html?opt=xxx HTTP/1.1
Referer: http://localhost:8000/hello/index.html
Accept: */*
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8000
Content-Length: 20
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6
username=yyy&age=zzz
[End]
需要注意的是,以POST方式提交表单时,action标签属性的值必须是已经进行了URL Encoding处理之后的值,用户端浏览器不会自动处理URL中的非法字符。如下面的表单是不符合要求的:
[xhtml]
view plaincopyprint?
<!-- 不符合要求的表单 -->
<form action="checkUser.html?opt=中文" method="POST">
<input type="text" name="username" value="yyy"/>
<input type="text" name="age" value="zzz"/>
<input type="submit" value="submit"/>
</form>
[xhtml] view plaincopyprint? <form action="checkUser.html?opt=%E4%B8%AD%E6%96%87" method="POST"> <input type="text" name="username" value="yyy"/> <input type="text" name="age" value="zzz"/> <input type="submit" value="submit"/> </form> <form action="checkUser.html?opt=%E4%B8%AD%E6%96%87" method="POST"> <input type="text" name="username" value="yyy"/> <input type="text" name="age" value="zzz"/> <input type="submit" value="submit"/> </form>
数据主体的编码方式
在HTTP请求中,request-line总是以application/x-www-form-urlencoded方式编码。enctype标签属性只对request-body起作用。也就是说只有在method="POST"的情况下,设置enctype才起作用。设置enctype标签属性后,在HTTP请求的头部(headers)信息中会多出一行Content-Type信息,并且request-body部分将会以Content-Type指定的MIME进行编码。这些操作都是由客户端浏览器自动完成的。
在没有指定enctype标签属性时,表单以默认的application/x-www-form-urlencoded方式对request-body进行编码。
如果表单域中的NAME或VALUE含有非法字符(如中文字符),客户端浏览器会自动对其进行URL Encoding处理。如下面的表单:
[xhtml]
view plaincopyprint?
<form action="checkUser.html" method="POST">
<input type="hidden" name="opt" value="中文"/>
<input type="text" name="username" value="yyy"/>
<input type="text" name="age" value="zzz"/>
<inupt type="submit" value="submit"/>
</form>
[xhtml] view plaincopyprint? <form action="checkUser.html?opt=xxx" method="POST" enctype="multipart/form-data"> <input type="text" name="username" value="yyy"/> <input type="text" name="age" value="zzz"/> <input type="file" name="file" /> <inupt type="submit" value="submit"/> </form> <form action="checkUser.html?opt=xxx" method="POST" enctype="multipart/form-data"> <input type="text" name="username" value="yyy"/> <input type="text" name="age" value="zzz"/> <input type="file" name="file" /> <inupt type="submit" value="submit"/> </form>
表单提交时HTTP头部信息如下:
POST /hello/checkUser.html?opt=xxx HTTP/1.1
Accept: */*
Referer: http://localhost:8000/hello/index.html
Accept-Language: zh-cn
Content-Type: multipart/form-data; boundary=---------------------------7d931c5d043e
Accept-Encoding: gzip, deflate
Host: localhost:8000
Content-Length: 382
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=6FE3D8E365DF9FE26221A32624470D24
-----------------------------7d931c5d043e
Content-Disposition: form-data; name="username"
yyy
-----------------------------7d931c5d043e
Content-Disposition: form-data; name="age"
zzz
-----------------------------7d931c5d043e
Content-Disposition: form-data; name="file"; filename="C:/1.txt"
Content-Type: text/plain
hello
-----------------------------7d931c5d043e--
[End]
GET与POST的区别
HTTP请求的GET与POST方式的本质区别可以参考hyddd在《浅谈HTTP中Get与Post的区别》一文中的描述,本文讲述了其中比较重要的一条,那就是数据传输的位置不同。GET方式在request-line中传送数据;POST方式在request-line及request-body中均可以传送数据。
对网上传言的解释
传言1:GET方式对长度有限制;POST方式对长度没限制。回答:长度限制之说一方面是HTTP客户端(如IE限定URL长度为2083字节,opera 是4050, Netscape 是8192)的限制;另一方面服务器的实现也加入了限制(如果URL长度过长,HTTP服务器会报414错误)。但HTTP协议及URL官方说明均对长度限制则没有规定。
传言2:GET是从服务器上获取数据;POST是向服务器传送数据。
回答:GET方式就没有向服务器传送数据?那么URL中的?子句送的是什么?不论是GET还是POST,都可以向服务器传送数据,只不过传送数据的位置不同;不论是GET还是POST,都要从服务器上获取数据,否则IE浏览器拿什么东西给我们看呢?关键的问题是
GET的主要任务是获得数据,但在获得数据前也可以向服务器提交一些数据;
POST的主要任务是提交数据,但在提交数据之后服务器也会向用户端返回一些显示用的数据。
传言3:GET不安全,用户能从地址栏上看到传送的数据;POST安全,用户不能从地址栏上看到传送的数据。
回答:POST方式看不到传送的数据是因为IE浏览器做了限制。如果你通过第三方工具看到了POST方式传送的数据,你还能说POST方式是安全的吗?理论上说GET和POST方式都不安全,要不就用不着研究HTTPS了。
相关文章推荐
- HTTP协议与HTTP表单传输格式,再论get、post方法
- HTTP协议与HTTP表单传输格式,再论get、post方法
- 浅谈HTTP中Get与Post的区别/HTTP协议与HTML表单(再谈GET与POST的区别)
- 牛客网Java刷题知识点之什么是HTTP协议、什么是HTTP隧道、HTTP响应的结构是怎么样的、HTTP报头包含哪些、HTTP中GET与POST方法有什么区别
- Qt HTTP网络相关GET,POST(HTTP 模拟POST 表单(multipartform)最简单和正式的方法)
- 两种HTTP方法服务器传送表单数据:GET和POST的区别
- springmvc中前台页面form表单提交方法为post,但是报HTTP Status 405 - Request method 'GET' not supported
- 通过HttpClient调用WebApi的Get、Post方法(返回类型限定为json格式)
- asynchttpclient的post方法发送json格式参数和表单格式参数
- Android学习笔记---28_网络通信之通过HTTP协议实现文件上传,组拼http 的post方法,传输内容
- C# winform端 通过HttpWebRequest进行post和get请求,数据格式为json,后台java端接收,其中有关传输特殊字符(\t,\r,',\n,n)等处理
- Form表单中Post与Get方法的区别
- HTTP 协议请求方法GET 与POST 的区别?
- 关于C#提交表单post和get的实现 HttpWebRequest 和ttpebeponse
- Http的get和post方法比较
- js中XMLHttpRequest对象实现GET、POST异步传输
- 面试2-两种 HTTP 请求方法:GET 和 POST
- HttpWebRequest get/post方法实现
- Android HttpUrlConnection 的“POST”和"GET"方法学习心得
- Android HTTP实例 使用GET方法和POST方法发送请求