http://example.com/page?parameter=value&also=another在HTTP的POST请求中,参数不会随着URI一起发送。值在哪里?在请求头中吗?在请求体中吗?它是什么样子的?
http://example.com/page?parameter=value&also=another在HTTP的POST请求中,参数不会随着URI一起发送。值在哪里?在请求头中吗?在请求体中吗?它是什么样子的?
值以请求主体的形式发送,格式与内容类型规定的格式相同。
通常情况下,内容类型为application/x-www-form-urlencoded
,因此请求主体使用与查询字符串相同的格式:
parameter=value&also=another
当您在表单中使用文件上传时,需要使用multipart/form-data
编码,它具有不同的格式。这更加复杂,但通常您不需要关心它的外观,因此我不会展示一个例子,但知道它存在可能会很有用。
multipart/form-data
上提供更多信息就更好了。对于那些感兴趣的人,这里有一个关于它的问题。 - Camilo Martinmultipart/form-data
格式在表单中上传一个JSON文件,或者如果你控制请求的构建,可以将内容类型更改为application/json
,并直接将JSON文本粘贴到HTTP正文中。 - Cholthi Paul Ttiopic简短回答:在POST请求中,值是发送在请求的“主体”中的。对于Web表单,它们最可能使用application/x-www-form-urlencoded
或multipart/form-data
媒体类型发送。设计用于处理Web请求的编程语言或框架通常会对这些请求进行正确处理,并为您提供轻松访问已解码值的方式(例如,在PHP中的$_REQUEST
或$_POST
,或在Python中的cgi.FieldStorage()
,flask.request.form
)。
现在我们稍微偏离一下话题,这可能有助于理解它们之间的差异 ;)
GET
和 POST
请求之间的差别主要是语义上的。它们也被“使用”方式不同,这解释了传递值方式的差异。
执行 GET
请求时,您向服务器请求一个或一组实体。为了允许客户端过滤结果,它可以使用 URL 的所谓“查询字符串”。查询字符串是 ?
后面的部分。这是 URI语法 的一部分。
因此,从您应用程序代码的角度来看(接收请求的部分),您需要检查 URI 查询部分以访问这些值。
请注意,键和值是URI的一部分。 浏览器可能会对URI长度施加限制。 HTTP标准规定没有限制。 但在撰写本文时,大多数浏览器确实限制了URI(我没有具体值)。 GET
请求不应用于向服务器提交新信息。 特别是不要使用较大的文档。 这就是您应该使用POST
或PUT
的地方。
执行POST
请求时,客户端实际上正在向远程主机提交一个新的文档。 因此,查询字符串在语义上没有意义。 这就是为什么您无法在应用程序代码中访问它们的原因。
POST
有点复杂(并且更加灵活):
Content-Type
头部定义。当使用HTML FORM
元素并设置method="POST"
时,通常为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表单编码文档为例,应用程序应执行以下步骤:
Content-Type
字段415
状态代码的响应再次强调,像PHP这样的语言或其他流行语言的web框架可能会为您处理此问题。唯一的例外是415
错误。没有一个框架可以预测您的应用程序选择支持或不支持哪些内容类型。这取决于您自己。
PUT
请求的处理方式与POST
请求基本相同。最大的区别在于,POST
请求应该让服务器决定如何(如果有必要)创建新资源。历史上(来自现已过时的RFC2616),它是将新资源创建为URI的“下级”(子级)。
PUT
请求与之相反,它应该将一个资源“存储”在那个URI上,并且使用恰好那个内容。不多也不少。这个想法是客户端负责在“PUTting”之前制作完整的资源。服务器应该接受给定URL上的原样内容。POST
请求通常不用于替换现有资源。一个PUT
请求既可以创建也可以替换。
POST
将始终创建一个新资源。 如果已经存在一个完全相同的资源,则PUT
将替换它。因此,如果调用 POST
10次,则会创建10个资源。如果调用PUT
10次,则只会(也许)创建一个。 这回答了您的问题吗? - exhumaHTTP头部之后是内容。 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请求和响应负载数据在网络上发送的过程。application/x-www-form-urlencoded
时才成立,而这并非总是如此。 - GuffaFrom
头信息。在我看来,它与HTTP 418状态码一样重要。 - Tom Howard你不能直接在浏览器的URL栏中输入它。
例如,使用Live HTTP Headers,您可以查看POST数据如何通过互联网发送。结果可能是这样的:
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-www-form-urlencoded
,这是一种用于编码键-值对的格式。键可以重复。每个键-值对由&
字符分隔,每个键与其值之间由=
字符分隔。
例如:
Name: John Smith
Grade: 19
被编码为:
Name=John+Smith&Grade=19
这是放置在HTTP头之后的请求主体。
HTTP POSTs中的表单值被发送到请求正文中,格式与查询字符串相同。
更多信息请参见规范。
?
开头? - Camilo Martin有些网络服务要求您将请求中的数据和元数据分开放置。例如,远程函数可能希望在URI中包含已签名的元数据字符串,而数据则通过HTTP正文进行发布。
POST请求在语义上可能类似于:
POST /?AuthId=YOURKEY&Action=WebServiceAction&Signature=rcLXfkPldrYm04 HTTP/1.1
Content-Type: text/tab-separated-values; charset=iso-8859-1
Content-Length: []
Host: webservices.domain.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: identity
User-Agent: Mozilla/3.0 (compatible; Indy Library)
name id
John G12N
Sarah J87M
Bob N33Y
这种方法通过使用单个Content-Type逻辑地将QueryString和Body-Post结合在一起,Content-Type是Web服务器的“解析指令”。
请注意: HTTP/1.1左侧被#32(空格)包裹,右侧被#10(换行符)包裹。
/user/john
和 /?user=john
之间的区别仅仅是语义上的不同(HTTP 并没有对查询字符串进行特殊处理),所以我认为这是可以理解的。但是您所说的“左侧被空格包裹”是什么意思?在 HTTP 方法前面并没有空格。您是说用于 POST 请求正文的空行吗? - Camilo Martin...Ym04
和HTTP/1.1
之间有一个空格(ASCII#32)。因此,查询字符串只是位于动词和协议版本之间。 - Interface Unknown首先,让我们区分 GET
和 POST
GET:它是向服务器发出的默认的 HTTP
请求,用于从服务器检索数据,并使用跟随在 URI
中 ?
后面的查询字符串来检索唯一的资源。
这是格式。
GET /someweb.asp?data=value HTTP/1.0
在这里,data=value
是传递的查询字符串值。
POST:它用于安全地向服务器发送数据,因此任何需要的内容都可以使用这种格式的POST
请求。
POST /somweb.aspHTTP/1.0
Host: localhost
Content-Type: application/x-www-form-urlencoded //you can put any format here
Content-Length: 11 //it depends
Name= somename
为什么要使用POST而不是GET?
在 GET
中,值通常会附加到基本URL的查询字符串中发送到服务器,这会产生两个后果:
GET
请求会保存在浏览器历史记录中,并带有参数。因此,您的密码将在浏览器历史记录中保持未加密状态。这是 Facebook 在过去真正面临的问题。URI
的长度有限制。如果发送太多参数,则可能会收到 414错误 - URI过长
。在进行 POST 请求时,表单数据将添加到请求的主体中。请求参数的长度计算并添加到标头中作为内容长度,没有重要数据直接附加到 URL 中。
您可以使用 Google 开发者工具的网络部分查看关于如何向服务器发出请求的基本信息。
您始终可以在请求标头
中增加更多值,例如Cache-Control
,Origin
,Accept
。
HTTPS
连接的情况下才是正确的,而不是HTTP
。
当HTTP
既不加密也不保护时,HTTPS
会同时加密URL
(包括查询参数)和请求体
。
所描述的问题源于许多浏览器将URI
(包括URL
)存储在其历史数据库中(通常不加密)。
因此,在处理任何敏感信息时,请仅使用请求体
+HTTPS
。 - Petru Zaharia有许多种/格式的提交参数
它们由Header中的content-type控制,表示为mime类型。
使用POST方法,服务器将数据作为输入流发送到程序中。......由于服务器将信息作为输入流传递给该程序,因此它设置环境变量CONTENT_LENGTH以字节(或字符)的数量表示数据的大小。我们可以使用这个值从标准输入中精确地读取相应数量的数据。