HTTP协议与HTML表单(再谈GET与POST的区别)

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

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 plaincopy

  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两种标签属性。这两个标签属性决定了表单提交时传送的属性名及相应的值。

目标地址(URL)

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编码规则。如下面的表单:

[xhtml] view plaincopy

  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”。

所以正确的表单应该是:

[xhtml] view plaincopy

  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方式将不予处理。如下面的表单:

[xhtml] view plaincopy

  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头部信息如下:

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 plaincopy

  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头部信息如下:

GET /hello/checkUser.html?opt=%E4%B8%AD%E6%96%87&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]

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

[xhtml] view plaincopy

  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头部信息如下:

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 plaincopy

  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>

正确的表单应该是:

[xhtml] view plaincopy

  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处理。如下面的表单:

[xhtml] view plaincopy

  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头部信息如下:

POST /hello/checkUser.html HTTP/1.1
Accept: */*
Referer: http://localhost:8000/hello/index.jsp
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8000
Content-Length: 43
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=4EF9C5B81356481F470F3C60D9E77D94

opt=%E4%B8%AD%E6%96%87&username=yyy&age=zzz
[End]

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

[xhtml] view plaincopy

  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头部信息如下:

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了。

参考资料:

[1]. HTTP协议(http://www.ietf.org/rfc/rfc2616.txt
[2]. HTML协议官方说明(http://www.w3.org/TR/html4/
[3]. URL标准(http://www.ietf.org/rfc/rfc1738.txt
[4]. MIME标准(http://www.ietf.org/rfc/rfc2045.txt

HTTP协议与HTML表单(再谈GET与POST的区别)

时间: 2024-09-29 19:24:18

HTTP协议与HTML表单(再谈GET与POST的区别)的相关文章

HTTP协议与HTML表单(初探GET与POST的区别)

今天刚学(xiao)了一把GET与POST,在此做个总结,与大家分享. 1.根据HTTP规范,GET用于信息获取,而求是安全且幂等的. (1).

表单提交:button input submit 的区别

http://harttle.com/2015/08/03/form-submit.html 最近项目代码中的表单提交的方式已经百花齐放了,现在用这篇文章来整理一下不同表单提交方式的区别,给出最佳实践.先给结论: 建议使用button[type=submit]来提交表单,而不是input: 只有单行文本控件时,回车会引发表单提交: 通过onsubmit事件可阻止表单提交. input[type=submit] 这是最常见的提交方式.不多说了,看图: 图中可以看到点击提交按钮后的URL是/?key

表单_post提交方式和get的区别,元素集

提交方式及表单域的name属性 使用form表单一种是post提交方式,一种是get提交方式,它们以method属性来定义,如果没有指定method属性,默认get方式提交. 表单域必须配合name属性才可以将数据提交到服务器 post方式与get方式的区别: 一.安全性 get方式不安全,以URL方式进行提交.(密码会显示在地址栏) post以请求实体提交,不会显示地址栏,足够安全 二.提交大小限制 get方式提交的内容有限,一个地址栏放不了多少东西,1k左右 post大小无限制,可以放大文件

关于jQuery表单选择中prop和attr的区别。

今天用jQuery学习表单这一章节的内容,再次遇到表单全选时,不能进行第二次全选的情况.反复查看测试仍然找不到是什么原因.后来在网上查到原来是jQuery1.6以后的版本用到的是prop.用attr的话不会多次实现,因为attr不会记录当前checkbox的选中状态. 表单这一章节内容让我感觉到有点吃力,总之好好努力吧! 以下是代码说明: <!DOCTYPE html> <html lang="en"> <head> <meta charset

再谈notify和notifyAll的区别和相同

经常在往上逛,关于在java中notify和notifyAll,经常有人有以下的说法: 1 notify只会通知一个在等待的对象,而notifyAll会通知所有在等待的对象,并且所有对象都会继续运行 并且,好像都有例子可以证明.上面的说法,可以说对,也可以说不对.究其原因,在于其中有一点很关键,官方的说法如下所示: 1 2 3 4 5 6 7 8 wait,notify,notifyAll: 此方法只应由作为此对象监视器的所有者的线程来调用.通过以下三种方法之一,线程可以成为此对象监视器的所有者

前端内容之HTML:HTTP协议、HTML中重要的标签、表格、表单等

什么是前端: 与用户直接打交道的,例如:手机电脑的界面 什么是后端: 幕后操作者,不直接与用户打交道的 WEB服务的本质: 浏览器中输入网址回车发送了几件事? 1.浏览器朝服务端发送请求 2.服务端接收请求 3.服务端返回响应 4.浏览器接收响应            按照相应的规则渲染给用户看. HTTP协议: 超文本传输协议 规定了浏览器与服务端传输数据的格式 四大特性: 1.基于请求响应 2.基于TCP/IP之上的作用于应用层的协议 3.无状态(服务端不保存用户状态,即使同一用户每次来都当

activiti自己定义流程之整合(二):使用angular js整合ueditor创建表单

基础环境搭建完成,接下来就该正式着手代码编写了,在说代码之前.我认为有必要先说明一下activit自己定义流程的操作. 抛开自己定义的表单不谈.通过之前的了解,我们知道一个新的流程開始.是在启动流程实例(processIntence)的时候,而流程实例依赖于流程定义(processDefinition).流程定义又依赖于流程模型(model). 我们用到的自己定义表单须要在创建模型,画模型图的时候就指定表单的名称formKey.须要保证这个formKey和我们创建的表单名称一致. 表单并不在创建

连续12天的加班工作总结-根据客户选择来生成后续表单页面

今天终于不加班了!!!让我先撒花 高呼万岁!! 其实 这样的加班工作 有的时候真的挺没有效率的 有几次晚上 我是真的真的 感觉很累了 但是想到项目的进度 我还是默默的抓紧赶 由于有保密问题 没有代码 就谈谈遇到的问题 主要是两个需求的改变,为某行的app的 travel insurance 模块增加一个新功能 CR1 就是当用户购买保险的时候增加帮 friend or parent 购买  首先通过不同的customer 的类型 来显示是 是给 friend 购买还是 parent购买 然后出现

【Flask】 WTForm表单编程

WTForm表单编程 在网页中,为了和用户进行信息交互总是不得不出现一些表单.flask设计了WTForm表单库来使flask可以更加简便地管理操作表单数据.WTForm中最重要的几个概念如下: Form类,开发者自定义的表单必须继承自Form类或者其子类.Form类最主要的功能是通过其所包含的Field类提供对表单内数据的快捷访问方式. 各种Field类,即字段.一般而言每个Field类都对应一个input的HTML标签.比如WTForm自带的一些Field类比如BooleanField就对应