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


在HTTP中 得到 请求,参数作为一个发送 请求参数

http://example.com/pageα参数=值也=另一

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

价值在哪里? 在请求标题中?在请求正文中?它是什么样子的?


1164
2018-01-27 19:19


起源




答案:


值以请求正文中的内容类型指定的格式发送。

通常内容类型是 application/x-www-form-urlencoded,因此请求体使用与查询字符串相同的格式:

parameter=value&also=another

当您在表单中使用文件上载时,您使用 multipart/form-data 相反,编码具有不同的格式。它更复杂,但你通常不需要关心它的样子,所以我不会展示一个例子,但知道它存在可能会很好。


963
2018-01-27 19:32



我忘记了文件上传的不同(+ 1 /接受)。你的答案是充分的,如果它有更多的信息,这将是特别好的 multipart/form-data。对于那些感兴趣的人,这里是 关于它的问题。 - Camilo Martin
注意:身体与标题分开 一个空行。 - Gab是好人
您解释了我们在HTTPBody中的位置,但是我们在HTTPHeader中放置/写入了什么?它的用途是什么? - Honey
@Honey:帖子的HTTP标题看起来像一个get,但是使用动词POST而不是GET,以及内容类型值(和可选的内容长度值),因为请求具有内容(正文)。每种类型的请求都有一个标题,有些类型也有一个标题。 - Guffa
@KennethWorden不,没有方法会正确发送JSON。但是,您可以使用编码的表单上传json文件 multipart/form-data 或者,如果您负责请求构建,请将内容类型更改为 application/json 并直接在http体中粘贴json文本 - Cholthi Paul Ttiopic


内容放在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

你可以使用像这样的工具看到这个 提琴手,您可以使用它来查看通过网络发送的原始HTTP请求和响应有效负载。


350
2018-01-27 19:21



仅在内容类型为 application/x-www-form-urlencoded,情况并非总是如此。 - Guffa
@Camilo Martin .... [+1]提出了很棒的问题和@ Joe Alfano .... [+1]的好答案.......我现在对POST请求有了明确的想法....但是如果图像带有键,值对的数据信息...... POST的结构如何? - Devrath
@Joe,现在你为什么要这样做? From 头在那? - Pacerier
@Joe,我喜欢随意包含的 From 头。 IMO就是418 HTTP状态代码。 - Tom Howard


简短回答: 在POST请求中,值在请求的“正文”中发送。对于网络表单,他们很可能使用媒体类型发送 application/x-www-form-urlencoded 要么 multipart/form-data。设计用于处理Web请求的编程语言或框架通常会对此类请求执行“正确的事”,并使您可以轻松访问易于解码的值(如 $_REQUEST 要么 $_POST 在PHP中,或 cgi.FieldStorage()flask.request.form 在Python)。


现在让我们稍微离题,这可能有助于理解差异;)

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

GET(相关的RFC部分

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

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

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

POST(相关的RFC部分

执行时 POST 请求,客户端实际上是在提交新的 文件 到远程主机。所以,一个 询问 字符串不(语义上)有意义。这就是您无法在应用程序代码中访问它们的原因。

POST 有点复杂(和 办法 更灵活):

收到POST请求时,您应始终期望“有效负载”,或者在HTTP术语中:a 邮件正文。消息体本身就没用了,因为没有 标准 (据我所知。也许是application / octet-stream?)格式。正文格式由 Content-Type 头。使用HTML时 FORM 元素 method="POST"这通常是 application/x-www-form-urlencoded。另一种非常常见的类型是 多部分/格式数据 如果您使用文件上传。但是可能 什么,范围从 text/plain,结束 application/json 甚至是习俗 application/octet-stream

无论如何,如果是 POST 要求是用 Content-Type 应用程序无法处理的,应该返回一个 415 状态码

大多数编程语言(和/或Web框架)提供了一种从最常见的类型对消息体进行解码/编码的方法(如 application/x-www-form-urlencodedmultipart/form-data 要么 application/json)。这很容易。自定义类型可能需要更多工作。

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

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

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

PUT(相关的RFC部分

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

一个 PUT 相反,请求应该准确地“存入”资源  那个URI,还有 究竟 那个内容。不多也不少。这个想法是 客户 有责任制作 完成 资源“PUT”之前的资源。服务器应该接受它 按原样 在给定的URL上。

结果,一个 POST 请求通常不习惯 更换 现有资源。一个 PUT 请求可以同时创建  更换。

边注

还有“路径参数“这可以用来向遥控器发送额外的数据,但是它们非常罕见,我不会在这里详细介绍。但是,作为参考,这里是RFC的摘录:

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


287
2017-11-03 15:54



我的确可能会略微切线。我在答案的顶部添加了一个“tl; dr”,这应该让它更清晰。 - exhuma
我刚刚编辑它以引用RFC7231而不是RFC2616(已经过时了一段时间)。除了更新的链接之外,这个答案的主要区别在于“PUT”部分。 - exhuma
我认为PUT的处理方式与POST不同,因为它应该是幂等的? stackoverflow.com/questions/611906/... - rogerdpack
@rogerdpack你没错。如果你读了第二段 PUT 部分,你会看到它 是 幂等。 POST 相比之下,根据定义,不是。 POST 将始终创建一个新资源。 PUT如果存在相同的资源,则将替换它。所以,如果你打电话 POST 10次​​,您将创建10个资源。如果你打电话 PUT 10次​​,它(可能)只创建一个。这是否回答你的问题? - exhuma


您无法直接在浏览器URL栏上键入它。

您可以看到如何在Internet上发送POST数据 实时HTTP标头 例如。 结果将是这样的

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

将是岗位价值。


49
2018-01-27 19:29



Ty用于记住主机字段。 - Deanie
澄清:是 Content-Length 应该是 29 这里?那是字符串的实际长度 username=zurfyx&pass=password。 - Hippo
@Hippo是一个意味着在那里的换行角色? - vikingsteve
@vikingsteve我明白你的意思了。所以我想内容总是在它的末尾有一个换行符。 - Hippo


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

例如:

Name: John Smith
Grade: 19

编码为:

Name=John+Smith&Grade=19

它放在HTTP标头之后的请求正文中。


18
2018-06-16 05:33



您解释了我们在HTTPBody中的位置,但是我们在HTTPHeader中放置/写入了什么? - Honey
你提到密钥可以重复,那么这种重复的结果是什么?最后一个会自动覆盖之前的值吗?谢谢。 - Jinghui Niu


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

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


13
2018-01-27 19:20



“相同格式”有点含糊不清。他们从一开始就是 ? 例如? - Camilo Martin
@PeterWooster是的,但没有提供一个例子。在这方面,就像一个答案说“看,在应用程序的博客中有你的问题的答案 (链接)”。 - Camilo Martin
不需要这个例子,你可以自己生成。很少需要用超过几点代表的勺子喂食。 - Peter Wooster
@PeterWooster这是不需要的,但是当你忘记某些内容时,它非常好,google它,转到第一个链接,这是一个明确,简洁的例子,告诉你你需要什么,而不是让你去咀嚼过于详细的规格,即使是全面的,也可能不适合复习。想一想:这个网站上的大多数QA都可以归结为“去阅读规范/手册/ API /等等 (链接)“它会有用吗?不只是谷歌。 - Camilo Martin
仅在内容类型为 application/x-www-form-urlencoded,情况并非总是如此。 - Guffa


某些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

这种方法在逻辑上将QueryString和Body-Post结合使用 Content-Type 这是一个Web服务器的“解析指令”。

请注意: HTTP / 1.1是 包裹 随着 #32 (空间)在左边和 #10 (换行)在右侧。


13
2017-07-31 14:01



和...之间的不同 /user/john 和 /?user=john 仅仅是一个语义的(HTTP并没有真正对查询字符串给予特殊处理),所以我认为这是合理预期的。但你的意思是“被左边的空间包裹”? HTTP方法之前没有空格。你的意思是邮政体的空白行? - Camilo Martin
之间有一个空格(ASCII#32) ...Ym04 和 HTTP/1.1 在上面的代码中。所以QueryString只是位于动词和协议版本之间。 - Interface Unknown
你的笔记听起来像是意想不到的和版本特定的。坦率地说,那里似乎有一个空间。换行也适用于其他行,就像unix一样。 - Camilo Martin
我只是强调了我无法在代码中标出的内容。这似乎很明显,但有时却不是。 - Interface Unknown
确实,我们可以通过将URI和参数分隔开来将查询参数作为URL的一部分传递 ? 就像我们一样 GET 要求。 - asgs


首先,让我们区分 GET 和 POST 

得到: 这是默认值 HTTP 对服务器发出的请求,用于从服务器检索数据和查询之后的字符串 ? 在一个 URI 用于检索唯一资源。

这是格式

GET /someweb.asp?data=value HTTP/1.0

这里 data=value 是传递的查询字符串值。

POST: 它用于安全地将数据发送到服务器,因此需要任何东西,这是a的格式 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,这会使您的数据被黑客入​​侵(这是几天来Facebook出现凭据的问题)这就是为什么 POST用于将数据发送到使用的服务器 Request Body 将数据发送到更安全的服务器,因为它隐藏了您的数据,并从字段中获取数据,计算它们的长度并将它们添加到服务器中。 header 对于 content-length 没有重要数据直接附加到 URL

既然您的请求是安全的,那么发送到服务器的任何值都可以在 Request Body 顾名思义它将包含用户想要发送的数据(并在其中发送 URL Encoded 格式)和 Request Headers 通过比较中的值来保证请求的安全性 Request Body 随着 Request Headers

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

并且您始终可以在您的帐户中添加更多值 Request Headers 喜欢 Cache-Control , Origin , Accept


0
2017-07-19 07:04