HTTP的GET/POST方式有何区别?这是一个老生常谈的问题,但老生常谈的问题往往有一些让人误解的结论。本文将带您浅尝HTTP协议,在了 解HTTP协议的同时将会展示许多被人们忽视的内容。在掌握了HTTP协议的过程中我们将自然而然地了解到GET与POST的本质区别。

HTTP请求

从使用者的角度看,一个HTTP请求起始于用户端浏览器上输入的一个URL地址、网页中的一个超链接或提交一个HTML表单等等。但本质上说,一个HTTP请求起始于用户端向HTTP服务器发送的一个URL请求。

一个标准的HTTP请求由以下几个部分组成:

1 <request-line>
2 <headers>
3 <CRLF>
4 [<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/nowamagic/index.html

HTTP请求的头部信息如下:

1 GET /nowamagic/index.html HTTP/1.1
2 Accept: */*
3 Accept-Language: zh-cn
4 Accept-Encoding: gzip, deflate
5 Host: localhost:8000
6 Connection: Keep-Alive
7 Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6

上述信息没有request-body部分,这是以GET方式发送的HTTP请求。如果请求中需要附加主体数据,即增加request- body部分,则必须使用POST方式发送HTTP请求。HTML超链接(<a></a>)只能用GET方式提交HTTP请 求,HTML表单(<form></form>)则可以使用两种方式提交HTTP请求。

HTML表单

HTML表单的使用方法如下:

1 <form action="目标地址" method="发送方式" enctype="数据主体的编码方式"> 
2     <!-- 各类型的表单域 --> 
3     <input name="NAME" value="VALUE"/> 
4     <textarea name="NAME">VALUE</textarea> 
5     <select name="NAME"> 
6         <option value="VALUE" selected="selected"/> 
7     </select> 
8 </form> 

表单中存在各种类型的表单域标签,如<input />、<textarea />及<select />。每一种表单域标签均有NAME与VALUE两种标签属性。这两个标签属性决定了表单提交时传送的属性名及相应的值。

action标签属性指定了表单提交的目标地址,其值可以是完整的URL。如:<form action="http://localhost:8000/hello/checkUser.html"></form>

如果放置表单的网页与表单提交的目标地址在同一个HTTP服务器上,则目标地址可以用绝对路径表示(绝对路径相对于HTTP服务器)。绝对 路径以“/”开头,包括WEB应用上下文及请求。如:<form action="/hello/checkUser.html"></form>

如果放置表单的网页与表单提交的目标地址在同一个WEB应用上下文上,则目标地址可以用相对路径表示(相对路径相对于放置表单的网页)。相对 路径不以“/”开头,不包括WEB应用上下文。如:<form action="checkUser.html"></form>

需要注意的是,action标签属性的值必须符合URL的要求,其编码必须符合application/x-www-form-urlencoded编码规则。如下面的表单:

1 <!-- 不符合要求的表单 --> 
2 <form action="checkUser.html?opt=中文" method="POST"> 
3 </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”。所以正确的表单应该是:

1 <!-- 符合要求的表单 --> 
2 <form action="checkUser.html?opt=%E4%B8%AD%E6%96%87" method="POST"> 
3 </form> 

method标签属性指定了表单的发送方式,发送方式只有两种:GET及POST。当以GET方式发送表单时,发送的HTTP请求没有 request-body部分,所以不需要指定enctype标签属性。GET方式只提交表单域中的数据,action标签属性中如果存在?子句,GET 方式将不予处理。如下面的表单:

1 <form action="checkUser.html?opt=xxx" method="GET"> 
2     <input type="text" name="username" value="yyy"/> 
3     <input type="text" name="age" value="zzz"/> 
4     <input type="submit" value="submit"/> 
5 </form> 

表单提交时没有包括opt属性,HTTP头部信息如下:

1 GET /hello/checkUser.html?username=yyy&age=zzz HTTP/1.1
3 Accept: */*
4 Accept-Language: zh-cn
5 Accept-Encoding: gzip, deflate
6 Host: localhost:8000
7 Connection: Keep-Alive
8 Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6

需要注意的是,以GET方式提交表单时,每个表单域的NAME与VALUE要以URL的方式提交,所以每个表单域的NAME与VALUE均要进行URL Encoding处理。这个操作通常是由用户端浏览器完成的。如下面的表单:

1 <form action="checkUser.html" method="GET"> 
2     <input type="hidden" name="opt" value="中文"/> 
3     <input type="text" name="username" value="yyy"/> 
4     <input type="text" name="age" value="zzz"/> 
5     <input type="submit" value="submit"/> 
6 </form> 

其中表单域opt的VALUE是中文字符“中文”,在表单提交时,用户端浏览器会自动将其进行URL Encoding。HTTP头部信息如下:

1 GET /hello/checkUser.html?opt=%E4%B8%AD%E6%96%87&username=yyy&age=zzz HTTP/1.1
3 Accept: */*
4 Accept-Language: zh-cn
5 Accept-Encoding: gzip, deflate
6 Host: localhost:8000
7 Connection: Keep-Alive
8 Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6

当以POST方式发送表单时,表单域中的数据将作为request-body提交,action标签属性中的?子句将在request-line中得以保留。如下面的表单:

1 <form action="checkUser.html?opt=xxx" method="POST"> 
2     <input type="text" name="username" value="yyy"/> 
3     <input type="text" name="age" value="zzz"/> 
4     <input type="submit" value="submit"/> 
5 </form> 

表单提交时,HTTP头部信息如下:

01 POST /hello/checkUser.html?opt=xxx HTTP/1.1
03 Accept: */*
04 Accept-Language: zh-cn
05 Content-Type: application/x-www-form-urlencoded
06 Accept-Encoding: gzip, deflate
07 Host: localhost:8000
08 Content-Length: 20
09 Connection: Keep-Alive
10 Cache-Control: no-cache
11 Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6
12 username=yyy&age=zzz

需要注意的是,以POST方式提交表单时,action标签属性的值必须是已经进行了URL Encoding处理之后的值,用户端浏览器不会自动处理URL中的非法字符。如下面的表单是不符合要求的:

1 <!-- 不符合要求的表单 --> 
2 <form action="checkUser.html?opt=中文" method="POST"> 
3     <input type="text" name="username" value="yyy"/> 
4     <input type="text" name="age" value="zzz"/> 
5     <input type="submit" value="submit"/> 
6 </form> 

正确的表单应该是:

1 <form action="checkUser.html?opt=%E4%B8%AD%E6%96%87" method="POST"> 
2     <input type="text" name="username" value="yyy"/> 
3     <input type="text" name="age" value="zzz"/> 
4     <input type="submit" value="submit"/> 
5 </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处理。如下面的表单:

1 <form action="checkUser.html" method="POST"> 
2     <input type="hidden" name="opt" value="中文"/> 
3     <input type="text" name="username" value="yyy"/> 
4     <input type="text" name="age" value="zzz"/> 
5     <inupt type="submit" value="submit"/> 
6 </form> 

表单提交时,HTTP头部信息如下:

01 POST /hello/checkUser.html HTTP/1.1
02 Accept: */*
04 Accept-Language: zh-cn
05 Content-Type: application/x-www-form-urlencoded
06 Accept-Encoding: gzip, deflate
07 Host: localhost:8000
08 Content-Length: 43
09 Connection: Keep-Alive
10 Cache-Control: no-cache
11 Cookie: JSESSIONID=4EF9C5B81356481F470F3C60D9E77D94
12 opt=%E4%B8%AD%E6%96%87&username=yyy&age=zzz

如果表单中包含需要上传的文件数据,则在指定method="POST"的同时还要指定enctype="multipart/form-data"。如下面的表单:

1 <form action="checkUser.html?opt=xxx" method="POST"  
2         enctype="multipart/form-data"> 
3     <input type="text" name="username" value="yyy"/> 
4     <input type="text" name="age" value="zzz"/> 
5     <input type="file" name="file" /> 
6     <inupt type="submit" value="submit"/> 
7 </form> 

表单提交时HTTP头部信息如下:

01 POST /hello/checkUser.html?opt=xxx HTTP/1.1
02 Accept: */*
04 Accept-Language: zh-cn
05 Content-Type: multipart/form-data; boundary=---------------------------7d931c5d043e
06 Accept-Encoding: gzip, deflate
07 Host: localhost:8000
08 Content-Length: 382
09 Connection: Keep-Alive
10 Cache-Control: no-cache
11 Cookie: JSESSIONID=6FE3D8E365DF9FE26221A32624470D24
12 -----------------------------7d931c5d043e
13 Content-Disposition: form-data; name="username"
14 yyy
15 -----------------------------7d931c5d043e
16 Content-Disposition: form-data; name="age"
17 zzz
18 -----------------------------7d931c5d043e
19 Content-Disposition: form-data; name="file"; filename="C:\1.txt"
20 Content-Type: text/plain
21 hello
22 -----------------------------7d931c5d043e--

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的GET/POST细节的更多相关文章

  1. Vue.js 和 MVVM 小细节

    MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...

  2. vue2.0实践的一些细节

    最近用vue2.0做了个活动.做完了回头发现,好像并没有太多的技术难点,而自己好像又做了比较久...只能说效率有待提升啊...简单总结了一些比较细节的点. 1.对于一些已知肯定会有数据的模块,先用一个 ...

  3. 深入理解JS 执行细节

    javascript从定义到执行,JS引擎在实现层做了很多初始化工作,因此在学习JS引擎工作机制之前,我们需要引入几个相关的概念:执行环境栈.全局对象.执行环境.变量对象.活动对象.作用域和作用域链等 ...

  4. javaScript中的小细节-script标签中的预解析

    首先介绍预解析,虽然预解析字面意思很好理解,但是却是出坑出的最多的地方,也是bug经常会有的地方,利用好预解析的特性可以解决很多问题,并且提高代码的质量及数量,浏览器在解析代码前会把变量的声明和函数( ...

  5. 分享MSSQL、MySql、Oracle的大数据批量导入方法及编程手法细节

    1:MSSQL SQL语法篇: BULK INSERT [ database_name . [ schema_name ] . | schema_name . ] [ table_name | vie ...

  6. Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)

    Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...

  7. [更新设计]跨平台物联网通讯框架ServerSuperIO 2.0 ,功能、BUG、细节说明,以及升级思考过程!

    注:ServerSuperIO 2.0 还没有提交到开源社区,在内部测试!!! 1. ServerSuperIO(SSIO)说明 SSIO是基于早期工业现场300波特率通讯传输应用场景发展.演化而来. ...

  8. Oracle Sales Cloud:管理沙盒(定制化)小细节2——使用对象触发器更新数字字段

    在上一篇 "管理沙盒(定制化)小细节1" 的随笔中,我们使用公式法在 "业务机会" 对象(单头)上建立了 "利润合计" 字段,并将它等于 & ...

  9. Oracle Sales Cloud:管理沙盒(定制化)小细节1——利用公式创建字段并显示在前端页面

    Oracle Sales Cloud(Oracle 销售云)是一套基于Oracle云端的CRM管理系统.由于 Oracle 销售云是基于 Oracle 云环境的,它与传统的管理系统相比,显著特点之一便 ...

  10. Oracle Sales Cloud:报告和分析(BIEE)小细节2——利用变量和过滤器传参(例如,根据提示展示不同部门的数据)

    在上一篇随笔中,我们建立了部门和子部门的双提示,并将部门和子部门做了关联.那么,本篇随笔我们重点介绍利用建好的双提示进行传参. 在操作之前,我们来看一个报告和分析的具体需求: [1] 两个有关联的提示 ...

随机推荐

  1. 对HTML+CSS+JavaScript的个人理解

    HTML就像人的骨头架子,是人的根基,要有个人样呀,一个网站,一个WebApp要是缺根儿骨头,那就像人少个胳膊少个腿儿的,行动不方便啊:CSS就像人穿得衣服.鞋子,男人的纹身,女人擦得粉儿,好看呀,一 ...

  2. 实验三 java敏捷开发与XP

    一.实验内容 (一)敏捷开发与XP 软件开发流程的目的是为了提高软件开发.运营.维护的效率,并提高软件的质量.用户满意度.可靠性和软件的可维护性. 光有各种流程的思想是不够的,我们还要有一系列的工具来 ...

  3. O_NONBLOCK on regular file

    It seems that writes/reads to regular files can't not be made non-blocking. I found the following re ...

  4. windows在当前位置打开终端

    1) 在此文件夹窗口内空白区域右键单击(需要同时按住Shift),从菜单中选择"在此处打开命令行窗口"的项:2) 在此窗口地址栏里直接输入cmd,回车即可.

  5. 进监狱全攻略之 Mifare1 Card 破解

    补充新闻:程序员黑餐馆系统 给自己饭卡里充钱 ,技术是双刃剑,小心,小心! 前言 从M1卡的验证漏洞被发现到现今,破解设备层出不穷,所以快速傻瓜式一键破解不是本文的重点,年轻司机将从本文中获得如下技能 ...

  6. hasLayout与BFC的触发条件

    hasLayout与BFC是分别在IE和其他浏览器上的两个作用很相近的概念,在很多时候,我们需要触发它们去实现有些效果.例如清除浮动时需要触发hasLayout与BFC:很多自适应的两栏和三栏布局(两 ...

  7. 公测后,微信小程序应用可能被拒原因.

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 34.0px "PingFang SC Semibold"; color: #23232 ...

  8. html table动态合并单元格 js方法

    <script> $(document).ready(function(){ function mc(tableId, startRow, endRow, col) { var tb = ...

  9. 【转载】张逸--ThoughtWorks(中国)程序员读书雷达

    原文地址:ThoughtWorks(中国)程序员读书雷达 软件业的特点是变化.若要提高软件开发的技能,就必须跟上技术发展的步伐.埋首醉心于项目开发与实战,固然能够锤炼自己的开发技巧,却难免受限于经验与 ...

  10. Directory的GetFiles方法

    想实现一个功能 :比如多个业务审批流程公用一个审批表的时候,有一个提示审批信息的页面 ,点击该页面不同的业务审批流程记录的时候,跳转到不同业务流程的详细显示界面 额 这样说 貌似以后我自己也看不明白 ...