在HTTP GET请求中,参数作为查询字符串发送:

http://example.com/page?parameter=value&also=another

在HTTP POST请求中,参数不会与URI一起发送。

价值观在哪里?在请求标头中?在请求主体中?它看起来像什么?


当前回答

简短回答:在POST请求中,值在请求的“正文”中发送。对于web表单,它们很可能与媒体类型的应用程序/x-www-form-urlencoded或多部分/form数据一起发送。设计用于处理web请求的编程语言或框架通常会做“正确的事情”™“使用此类请求,并为您提供对容易解码的值的轻松访问(如PHP中的$_REQUEST或$_POST,或Python中的cgi.FieldStorage()、flask.REQUEST.form)。


现在让我们离题一点,这可能有助于理解区别;)

GET和POST请求之间的区别主要是语义上的。它们的“使用”方式也不同,这解释了传递值的方式不同。

GET(相关RFC部分)

当执行GET请求时,您向服务器请求一个或一组实体。为了允许客户端过滤结果,它可以使用URL的所谓“查询字符串”。查询字符串是?之后的部分?。这是URI语法的一部分。

因此,从应用程序代码(接收请求的部分)的角度来看,您需要检查URI查询部分以获得对这些值的访问。

注意,键和值是URI的一部分。浏览器可能会对URI长度施加限制。HTTP标准规定没有限制。但在撰写本文时,大多数浏览器都会限制URI(我没有具体的值)。GET请求不应用于向服务器提交新信息。尤其是大型文档。这就是您应该使用POST或PUT的地方。

POST(相关RFC部分)

当执行POST请求时,客户端实际上正在向远程主机提交一个新文档。因此,查询字符串(语义上)没有意义。这就是为什么在应用程序代码中不能访问它们的原因。

POST有点复杂(而且更灵活):

当接收POST请求时,您应该始终期待一个“有效负载”,或者,用HTTP术语来说:一个消息体。消息体本身是非常无用的,因为没有标准(据我所知,可能是应用程序/八位字节流?)格式。正文格式由Content-Type标头定义。当使用带有method=“POST”的HTML FORM元素时,这通常是application/x-wwww-FORM-urlencoded。如果使用文件上载,另一种非常常见的类型是multipart/form数据。但它可以是任何东西,从文本/纯文本,到application/json,甚至是自定义的application/octet流。

在任何情况下,如果使用应用程序无法处理的内容类型发出POST请求,则应返回415状态代码。

大多数编程语言(和/或web框架)提供了一种将消息体从最常见的类型(如application/x-www-form-urlencoded、multipart/form-data或application/json)进行编码的方法。所以这很简单。自定义类型可能需要更多的工作。

以标准HTML表单编码文档为例,应用程序应执行以下步骤:

读取“内容类型”字段如果该值不是支持的媒体类型之一,则返回具有415状态代码的响应否则,解码消息体中的值。

同样,像PHP这样的语言或其他流行语言的web框架可能会为您处理这一问题。例外情况是415错误。没有框架可以预测应用程序选择支持和/或不支持哪些内容类型。这取决于你。

PUT(相关RFC部分)

PUT请求的处理方式与POST请求完全相同。最大的区别是POST请求应该让服务器决定如何(如果有的话)创建新资源。历史上(从现在过时的RFC2616开始,它是创建一个新资源作为请求发送到的URI的“从属”(子))。

与此相反,PUT请求应该将资源“存放”在该URI处,并且内容与该URI完全相同。没有更多,没有更少。其思想是,客户端负责在“PUT”之前制作完整的资源。服务器应按给定URL的原样接受它。

因此,POST请求通常不用于替换现有资源。PUT请求既可以创建也可以替换。

旁注

还有一些“路径参数”可以用来向远程设备发送额外的数据,但它们非常罕见,因此我在这里不再赘述。但是,作为参考,这里是RFC的摘录:

除了分层路径中的点段外,还考虑路径段一般语法是不透明的。生成URI的应用程序通常使用段中允许使用保留字符来分隔特定于方案的或解引用处理程序特定的子组件。例如,分号(“;”)和equals(“=”)保留字符通常用于分隔参数和适用于该段的参数值。保留逗号(“,”)字符通常用于类似的目的。例如,一个URI生产者可以使用诸如“name;v=1.1”之类的段来表示对版本的引用1.1的“名称”,而另一个可能使用“名称,1.1”这样的段表示相同。参数类型可由特定方案定义语义,但在大多数情况下,参数的语法是特定的涉及URI解引用算法的实现。

其他回答

不能直接在浏览器URL栏上键入。

例如,您可以看到POST数据是如何通过Live HTTP Headers在Internet上发送的。结果会是这样的

http://127.0.0.1/pass.php
POST /pass.php HTTP/1.1

Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://127.0.0.1/pass.php
Cookie: passx=87e8af376bc9d9bfec2c7c0193e6af70; PHPSESSID=l9hk7mfh0ppqecg8gialak6gt5
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 30
username=zurfyx&pass=password

上面写着

Content-Length: 30
    username=zurfyx&pass=password

将是后值。

POST请求中的默认媒体类型是application/x-wwww-form-urlencoded。这是一种对键值对进行编码的格式。密钥可以重复。每个键值对用&字符分隔,每个键值用=字符与其值分隔。

例如:

Name: John Smith
Grade: 19

编码为:

Name=John+Smith&Grade=19

这被放置在HTTP头之后的请求体中。

简短回答:在POST请求中,值在请求的“正文”中发送。对于web表单,它们很可能与媒体类型的应用程序/x-www-form-urlencoded或多部分/form数据一起发送。设计用于处理web请求的编程语言或框架通常会做“正确的事情”™“使用此类请求,并为您提供对容易解码的值的轻松访问(如PHP中的$_REQUEST或$_POST,或Python中的cgi.FieldStorage()、flask.REQUEST.form)。


现在让我们离题一点,这可能有助于理解区别;)

GET和POST请求之间的区别主要是语义上的。它们的“使用”方式也不同,这解释了传递值的方式不同。

GET(相关RFC部分)

当执行GET请求时,您向服务器请求一个或一组实体。为了允许客户端过滤结果,它可以使用URL的所谓“查询字符串”。查询字符串是?之后的部分?。这是URI语法的一部分。

因此,从应用程序代码(接收请求的部分)的角度来看,您需要检查URI查询部分以获得对这些值的访问。

注意,键和值是URI的一部分。浏览器可能会对URI长度施加限制。HTTP标准规定没有限制。但在撰写本文时,大多数浏览器都会限制URI(我没有具体的值)。GET请求不应用于向服务器提交新信息。尤其是大型文档。这就是您应该使用POST或PUT的地方。

POST(相关RFC部分)

当执行POST请求时,客户端实际上正在向远程主机提交一个新文档。因此,查询字符串(语义上)没有意义。这就是为什么在应用程序代码中不能访问它们的原因。

POST有点复杂(而且更灵活):

当接收POST请求时,您应该始终期待一个“有效负载”,或者,用HTTP术语来说:一个消息体。消息体本身是非常无用的,因为没有标准(据我所知,可能是应用程序/八位字节流?)格式。正文格式由Content-Type标头定义。当使用带有method=“POST”的HTML FORM元素时,这通常是application/x-wwww-FORM-urlencoded。如果使用文件上载,另一种非常常见的类型是multipart/form数据。但它可以是任何东西,从文本/纯文本,到application/json,甚至是自定义的application/octet流。

在任何情况下,如果使用应用程序无法处理的内容类型发出POST请求,则应返回415状态代码。

大多数编程语言(和/或web框架)提供了一种将消息体从最常见的类型(如application/x-www-form-urlencoded、multipart/form-data或application/json)进行编码的方法。所以这很简单。自定义类型可能需要更多的工作。

以标准HTML表单编码文档为例,应用程序应执行以下步骤:

读取“内容类型”字段如果该值不是支持的媒体类型之一,则返回具有415状态代码的响应否则,解码消息体中的值。

同样,像PHP这样的语言或其他流行语言的web框架可能会为您处理这一问题。例外情况是415错误。没有框架可以预测应用程序选择支持和/或不支持哪些内容类型。这取决于你。

PUT(相关RFC部分)

PUT请求的处理方式与POST请求完全相同。最大的区别是POST请求应该让服务器决定如何(如果有的话)创建新资源。历史上(从现在过时的RFC2616开始,它是创建一个新资源作为请求发送到的URI的“从属”(子))。

与此相反,PUT请求应该将资源“存放”在该URI处,并且内容与该URI完全相同。没有更多,没有更少。其思想是,客户端负责在“PUT”之前制作完整的资源。服务器应按给定URL的原样接受它。

因此,POST请求通常不用于替换现有资源。PUT请求既可以创建也可以替换。

旁注

还有一些“路径参数”可以用来向远程设备发送额外的数据,但它们非常罕见,因此我在这里不再赘述。但是,作为参考,这里是RFC的摘录:

除了分层路径中的点段外,还考虑路径段一般语法是不透明的。生成URI的应用程序通常使用段中允许使用保留字符来分隔特定于方案的或解引用处理程序特定的子组件。例如,分号(“;”)和equals(“=”)保留字符通常用于分隔参数和适用于该段的参数值。保留逗号(“,”)字符通常用于类似的目的。例如,一个URI生产者可以使用诸如“name;v=1.1”之类的段来表示对版本的引用1.1的“名称”,而另一个可能使用“名称,1.1”这样的段表示相同。参数类型可由特定方案定义语义,但在大多数情况下,参数的语法是特定的涉及URI解引用算法的实现。

后置参数有多种方式/格式

表单数据原始数据json文件编码数据文件xml格式

它们由Header中表示为mime类型的内容类型控制。

在万维网上的CGI编程中,作者说:

使用POST方法,服务器将数据作为输入流发送到程序。。。。。因为服务器将信息传递给该程序作为输入流,它将环境变量CONTENT_LENGTH设置为以字节(或字符)为单位的数据大小。我们可以使用这可以从标准输入中准确读取那么多数据。