在 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 请求和响应负载。
application/x-www-form-urlencoded
时,情况并非总是如此。
From
标题?
From
标头。 IMO 它带有 418 HTTP 状态代码。
简短回答: 在 POST 请求中,值在请求的“正文”中发送。对于网络表单,它们最有可能使用 application/x-www-form-urlencoded
或 multipart/form-data
的媒体类型发送。设计用于处理网络请求的编程语言或框架通常对此类请求执行“正确的事情™”,并为您提供对易于解码的值的轻松访问(如 PHP 中的 $_REQUEST
或 $_POST
,或 {5 },flask.request.form
在 Python 中)。
现在让我们离题一点,这可能有助于理解其中的区别;)
GET
和 POST
请求之间的区别主要是语义上的。它们也以不同的方式“使用”,这解释了值传递方式的差异。
GET(相关 RFC 部分)
执行 GET
请求时,您向服务器请求一个或一组实体。为了允许客户端过滤结果,它可以使用 URL 的所谓“查询字符串”。查询字符串是 ?
之后的部分。这是 URI syntax 的一部分。
因此,从您的应用程序代码(接收请求的部分)的角度来看,您将需要检查 URI 查询部分以访问这些值。
请注意,键和值是 URI 的一部分。浏览器可能对 URI 长度施加限制。 HTTP 标准声明没有限制。但在撰写本文时,大多数浏览器确实限制了 URI(我没有具体的值)。 GET
请求应该永远用于向服务器提交新信息。特别是不是更大的文件。这就是您应该使用 POST
或 PUT
的地方。
POST(相关 RFC 部分)
执行 POST
请求时,客户端实际上是在向远程主机提交一个新的文档。因此,query 字符串(在语义上)没有意义。这就是为什么您无法在应用程序代码中访问它们的原因。
POST
稍微复杂一些(方式更灵活):
接收 POST 请求时,您应该始终期待“有效负载”,或者用 HTTP 术语来说:message body。消息体本身没什么用,因为没有标准(据我所知。也许是application/octet-stream?)格式。正文格式由 Content-Type
标头定义。当使用带有 method="POST"
的 HTML FORM
元素时,这通常是 application/x-www-form-urlencoded
。如果您使用文件上传,另一种非常常见的类型是 multipart/form-data。但它可以是任何东西,范围从 text/plain
、超过 application/json
甚至是自定义 application/octet-stream
。
在任何情况下,如果使用应用程序无法处理的 Content-Type
发出 POST
请求,它应该返回 415
status-code。
大多数编程语言(和/或网络框架)都提供了一种将消息正文从/编码到最常见类型(如 application/x-www-form-urlencoded
、multipart/form-data
或 application/json
)的方法。所以这很容易。自定义类型可能需要更多的工作。
以标准 HTML 表单编码文档为例,应用程序应执行以下步骤:
读取 Content-Type 字段 如果该值不是支持的媒体类型之一,则返回带有 415 状态代码的响应,否则,解码消息正文中的值。
同样,PHP 之类的语言或其他流行语言的网络框架可能会为您处理这个问题。例外情况是 415
错误。没有框架可以预测您的应用程序选择支持和/或不支持哪些内容类型。这取决于你。
PUT(相关 RFC 部分)
PUT
请求的处理方式与 POST
请求完全相同。最大的区别在于 POST
请求应该让服务器决定如何(如果有的话)创建新资源。从历史上看(从现在已经过时的 RFC2616 开始,它是创建一个新资源作为请求发送到的 URI 的“下级”(子级))。
相比之下,PUT
请求应该将资源准确地“存放”在 那个 URI 上,并用 exactly 那个内容。不多也不少。这个想法是 client 负责在“PUT”之前制作 complete 资源。服务器应该在给定的 URL 上按原样接受它。
因此,POST
请求通常不用于替换现有资源。 PUT
请求可以创建 和 替换。
边注
还有“path parameters”可以用来向遥控器发送额外的数据,但它们太少见了,我不会在这里详细介绍。但是,作为参考,这里是 RFC 的摘录:
除了层次路径中的点段之外,路径段被通用语法认为是不透明的。生成 URI 的应用程序通常使用段中允许的保留字符来分隔特定于方案或特定于解引用处理程序的子组件。例如,分号 (";") 和等号 ("=") 保留字符通常用于分隔适用于该段的参数和参数值。逗号 (",") 保留字符通常用于类似目的。例如,一个 URI 生产者可能使用诸如“name;v=1.1”之类的段来指示对“name”版本 1.1 的引用,而另一个 URI 生产者可能使用诸如“name,1.1”之类的段来指示相同。参数类型可以由特定于方案的语义定义,但在大多数情况下,参数的语法特定于 URI 解引用算法的实现。
PUT
部分的第二段,您会发现它是 幂等的。 POST
相反可以——根据定义——不是。 POST
将始终创建新资源。如果存在相同的资源,PUT
将替换它。因此,如果您调用 POST
10 次,您将创建 10 个资源。如果您调用 PUT
10 次,它(可能)只会创建一个。这是否回答你的问题?
您不能直接在浏览器 URL 栏上键入它。
例如,您可以使用 Live HTTP Headers 查看 POST 数据是如何在 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
将是帖子值。
Content-Length
应该是 29
吗?这是字符串 username=zurfyx&pass=password
的实际长度。
POST 请求中的默认媒体类型是 application/x-www-form-urlencoded
。这是一种编码键值对的格式。密钥可以重复。每个键值对由 &
字符分隔,每个键与其值由 =
字符分隔。
例如:
Name: John Smith
Grade: 19
被编码为:
Name=John+Smith&Grade=19
这放置在 HTTP 标头之后的请求正文中。
HTTP POST 中的表单值在请求正文中发送,格式与查询字符串相同。
有关详细信息,请参阅 spec。
?
开头?
application/x-www-form-urlencoded
时,情况并非总是如此。
某些 Web 服务要求您分别放置请求数据和元数据。例如,远程函数可能期望已签名的元数据字符串包含在 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 方法之前没有空格。你的意思是帖子正文的空白行?
...Ym04
和 HTTP/1.1
之间有一个空格(ASCII #32)。所以 QueryString 只是驻留在动词和协议版本之间。
?
分隔 URI 和参数来将查询参数作为 URL 的一部分传递,就像我们对 GET
请求所做的那样。
首先,让我们区分 GET
和 POST
获取: 这是向服务器发出的默认 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
为什么要通过 GET 发布?
在 GET
中,发送到服务器的值通常附加到查询字符串中的基本 URL,现在有 2 个后果
GET 请求与参数一起保存在浏览器历史记录中。因此,您的密码在浏览器历史记录中保持未加密状态。这对当时的 Facebook 来说是一个真正的问题。
通常,服务器对 URI 的长度有限制。如果发送的参数过多,您可能会收到 414 错误 - URI 太长
在发布请求的情况下,您将字段中的数据添加到正文中。计算请求参数的长度,并将其添加到 content-length 的 header 中,并且没有重要数据直接附加到 URL。
您可以使用 Google Developer Tools 的网络部分来查看有关如何向服务器发出请求的基本信息。
您可以随时在 Request Headers
中添加更多值,例如 Cache-Control
、Origin
、Accept
。
HTTPS
连接的上下文中成立,而不是 HTTP
。 HTTPS
同时加密 URL
(包括查询参数)和 Request Body
,而 HTTP
既不加密/保护也不加密。所描述的问题来自这样一个事实,即许多浏览器将 URIs
(包括 URLs
)存储在其历史数据库中(通常未加密)。因此,对于任何敏感内容,请仅使用 Request Body
+HTTPS
。
post参数有多种方式/格式
表单数据
原始数据
json
编码数据
文件
xml
它们由表示为 mime 类型的 Header 中的内容类型控制。
在万维网上的 CGI 编程中,作者说:
使用 POST 方法,服务器将数据作为输入流发送到程序。 ..... 由于服务器将信息作为输入流传递给该程序,因此它将环境变量 CONTENT_LENGTH 设置为以字节数(或字符数)为单位的数据大小。我们可以使用它从标准输入中准确读取那么多数据。
multipart/form-data
的信息就更好了。不过,对于那些感兴趣的人,这里是 a question about it。multipart/form-data
编码的格式上传 json 文件,或者如果您负责请求构造,请将 content-type 更改为application/json
并将 json 文本直接粘贴到 http 正文中