在HTTP GET请求中,参数作为查询字符串发送:
http://example.com/page?parameter=value&also=another
在HTTP POST请求中,参数不会与URI一起发送。
价值观在哪里?在请求标题中?在请求正文中?它看起来像什么?
这些值以内容类型指定的格式在请求正文中发送。
通常内容类型是application/x-www-form-urlencoded
,因此请求体使用与查询字符串相同的格式:
parameter=value&also=another
当您在表单中使用文件上载时,您将改用multipart/form-data
编码,它具有不同的格式。它比较复杂,但是您通常不需要关心它看起来是什么样子,所以我不会展示一个例子,但是知道它存在可能会很好。
内容放在HTTP头之后。HTTP POST的格式是HTTP头,后跟空行,后跟请求正文。POST变量作为键值对存储在正文中。
您可以在HTTP Post的原始内容中看到这一点,如下所示:
POST /path/script.cgi HTTP/1.0
From: frog@jmarshall.com
User-Agent: HTTPTool/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 32
home=Cosby&favorite+flavor=flies
您可以使用像Fiddler这样的工具来看到这一点,您可以使用它来观察通过网络发送的原始HTTP请求和响应有效负载。
简短回答:在POST请求中,值是在请求的“正文”中发送的。对于Web表单,它们很可能以application/x-www-form-urlencoded
或multipart/form-data
的媒体类型发送。设计用于处理Web请求的编程语言或框架通常对此类请求进行“正确的™”,并为您提供对易于解码的值的轻松访问(如PHP中的$_request
或$_poster
,或者Python中的CGI.FieldStorage()
,Flask.request.form
)。
现在让我们离题一点,这可能有助于理解其中的区别;)
GET
和POST
请求之间的区别主要是语义上的。它们的“使用”方式也不同,这就解释了值传递方式的差异。
当执行get
请求时,您向服务器请求一个或一组实体。为了允许客户机过滤结果,它可以使用URL的所谓“查询字符串”。查询字符串是?
后面的部分。这是URI语法的一部分。
因此,从应用程序代码(接收请求的部分)的角度来看,您将需要检查URI查询部分以获得对这些值的访问。
请注意,键和值是URI的一部分。浏览器可能会对URI长度施加限制。HTTP标准规定没有限制。但在撰写本文时,大多数浏览器都限制了URI(我没有具体的值)。绝不应使用get
请求向服务器提交新信息。尤其是较大的文档。这就是您应该使用POST
或PUT
的地方。
当执行POST
请求时,客户端实际上是在向远程主机提交新文档。因此,查询字符串(在语义上)没有意义。这就是为什么您不能在应用程序代码中访问它们。
post
稍微复杂一点(也更加灵活):
当接收到POST请求时,您应该始终期待一个“有效负载”,或者,用HTTP术语来说:一个消息体。消息主体本身是非常无用的,因为没有标准(据我所知,可能是application/octet-stream?)格式。正文格式由content-type
头定义。当使用带有method=“post”
的HTMLform
元素时,这通常是application/x-www-form-urlencoded
。如果使用文件上传,另一种非常常见的类型是multipart/form-data。但是它可以是任何东西,从text/plain
到application/json
,甚至是自定义的application/octet-stream
。
在任何情况下,如果使用应用程序无法处理的Content-Type
发出POST
请求,它应该返回415
状态代码。
大多数编程语言(和/或Web框架)都提供了一种从最常见类型(如application/x-www-form-urlencoded
,multipart/form-data
或application/json
)对消息体进行反编码的方法。所以这很容易。自定义类型可能需要更多的工作。
使用标准HTML表单编码文档作为示例,应用程序应执行以下步骤:
内容类型
字段415
状态代码的响应同样,PHP等语言或其他流行语言的Web框架可能会为您处理这一问题。此错误的例外是415
错误。任何框架都无法预测应用程序选择支持和/或不支持哪些内容类型。这取决于你。
处理PUT
请求的方式与处理POST
请求的方式完全相同。最大的区别在于,POST
请求应该让服务器决定如何(如果有的话)创建新资源。从历史上(从现在已经过时的RFC2616开始,它将创建一个新资源作为发送请求的URI的“从属”(子))。
与此相反,PUT
请求应该将一个资源精确地“存放”在该URI处,并带有该内容。不多不少。其思想是,客户机负责在“投放”它之前制作完整的资源。服务器应该在给定的URL上按原样接受它。
因此,POST
请求通常不会用于替换现有资源。一个put
请求可以同时进行创建和替换。
还有一些“路径参数”可以用来向远程发送额外的数据,但是它们是如此的不常见,所以我在这里就不做太多的详细介绍了。但是,为了供参考,这里摘录了RFC:
除了分层路径中的点段,一般语法认为路径段是不透明的。产生URI的应用程序通常使用段中允许的保留字符来分隔特定于方案或特定于取消引用处理程序的子组件。例如,分号(“;”)和equals(“=”)保留字符通常用于分隔适用于该段的参数和参数值。逗号(“,”)保留字符经常用于类似的目的。例如,一个URI生产者可能使用诸如“name;v=1.1”之类的段来指示对“name”版本1.1的引用,而另一个生产者可能使用诸如“name,1.1”之类的段来指示相同的引用。参数类型可以通过特定于方案的语义来定义,但是在大多数情况下,参数的语法是特定于URI取消引用算法的实现的。