如何在 HTTP POST 请求中发送参数?

在 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 请求中,值在请求的 “正文” 中发送。对于网络表单,它们很可能以application/x-www-form-urlencodedmultipart/form-data的媒体类型发送。设计用于处理 Web 请求的编程语言或框架通常会对此类请求执行 “The Right Thing™”,并为您提供对易于解码的值(例如 PHP 中的$_REQUEST$_POSTcgi.FieldStorage() ,Python 中的flask.request.form )。


现在让我们讨论一下,这可能有助于理解差异;)

GETPOST请求之间的区别在很大程度上是语义上的。它们也以不同的方式 “使用”,这解释了如何传递值。

GET( 相关的 RFC 部分

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

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

请注意,键和值是 URI 的一部分。浏览器可能会对 URI 长度施加限制。 HTTP 标准规定没有限制。但是在撰写本文时,大多数浏览器的确会限制 URI(我没有具体值)。 绝对不要使用GET请求向服务器提交新信息。特别是没有较大的文档。那是您应该使用POSTPUT

POST( 相关的 RFC 部分

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

POST是更复杂的(和方式更灵活)一点点:

收到 POST 请求时,您应该始终期望 “有效载荷”,或者用 HTTP 术语来说: 消息正文 。消息主体本身是没有用的,因为没有标准的格式 (据我所知。也许是 application / octet-stream?)。正文格式由Content-Type标头定义。当将 HTML FORM元素与method="POST" ,通常是application/x-www-form-urlencoded 。如果使用文件上传,则另一种非常常见的类型是multipart / form-data 。但是可以是任何东西 ,范围从text/plainapplication/json甚至是自定义application/octet-stream

在任何情况下,如果使用Content-Type发出POST请求,但应用程序无法处理该请求,则它应返回415状态码

大多数编程语言(和 / 或 Web 框架)都提供了一种将消息正文从 / 转换为最常见的类型(例如application/x-www-form-urlencodedmultipart/form-dataapplication/json )的方法。 。这很容易。自定义类型可能需要更多的工作。

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

  1. 阅读Content-Type字段
  2. 如果该值不是受支持的媒体类型之一,则返回带有415状态代码的响应
  3. 否则,对消息正文中的值进行解码。

同样,PHP 之类的语言或其他流行语言的网络框架可能会为您解决这个问题。例外是415错误。没有框架可以预测您的应用选择支持和 / 或不支持的内容类型。这取决于你。

PUT( 相关的 RFC 部分

PUT请求的处理方式几乎与POST请求相同。最大的不同是, POST请求应该让服务器决定如何(如果有的话)创建新资源。从历史上看(从现在已过时的 RFC2616 开始,它是将新资源创建为发送请求的 URI 的 “下级”(子级))。

PUT相反请求应该恰好该 URI“存款” 的资源,并与完全相同的内容。不多不少。想法是, 客户端负责在 “放入” 之前制作完整的资源。服务器应在给定 URL 上原样接受它。

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

边注

还有一些 “ 路径参数 ” 可用于将其他数据发送到远程,但是它们很少见,因此在此不再赘述。但是,作为参考,以下是 RFC 的摘录:

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

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

例如,您可以查看如何使用实时 HTTP 标头在 Internet 上发送 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 标头之后的请求正文中。

某些 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 (换行)在右侧。

HTTP POST 中的表单值以与查询字符串相同的格式在请求正文中发送。

有关更多信息,请参见规范

首先,让我们区分GETPOST

Get:这是对服务器的默认HTTP请求,用于从服务器检索数据和查询后面的字符串? URI中的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 上,这使您的数据能够被黑客入侵(对于过去暴露了您的凭据的 Facebook 来说,这是一个问题),这就是POST原因用于将数据发送到服务器,该服务器使用 “ Request Body将数据发送到服务器,这是更安全的,因为它隐藏了您的数据,并且从字段中获取了数据,然后计算字段的长度并将其添加到content-lengthheader中并且没有重要数据直接附加到URL

现在,确保您的请求是安全的,发送到服务器的任何值都可以在Request Body发送,正如其名称所暗示的那样,它将包含用户想要发送的数据(并以URL Encoded格式发送),并且Request Headers将保持请求安全由值比较Request BodyRequest Headers

现在,关于安全性的问题并不仅仅适用于 HTTP,除非使用 HTTPs 协议对其进行加密,否则正文中的数据不一定非常安全。

您可以使用 Google Developer Tools 的网络部分来查看有关如何向服务器发出请求的基本信息。

并且您始终可以在Request Headers添加更多值,例如Cache-ControlOriginAccept