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

Cam*_*tin 1396 parameters post uri http request

在HTTP GET请求中,参数作为查询字符串发送:

http://example.com/page?parameter=value&also=another

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

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

Guf*_*ffa 1178

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

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

parameter=value&also=another
Run Code Online (Sandbox Code Playgroud)

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

  • **注意**:身体与标题分开仅**一个空行**. (67认同)
  • 我忘记了文件上传的不同(+ 1 /接受).你的答案是充分的,如果它有更多关于`multipart/form-data`的信息会更好.对于那些感兴趣的人,这里是[关于它的问题](http://stackoverflow.com/questions/4526273/what-does-enctype-multipart-form-data-mean). (24认同)
  • @Honey:帖子的HTTP标题看起来像一个get,但是使用动词POST而不是GET,以及内容类型值(和可选的内容长度值),因为请求具有内容(正文).每种类型的请求都有一个标题,有些类型也有一个标题. (4认同)
  • @KennethWorden不,没有方法会正确发送JSON.然而,您可以使用`multipart/form-data`编码的表单上传一个json文件,或者如果您负责请求构建,将内容类型更改为`application/json`并直接在http body中粘贴json文本 (4认同)
  • 您解释了我们在HTTPBody中的位置,但是我们在HTTPHeader中放置/写入了什么?它有什么用途? (2认同)
  • 就编码而言,MDN文档将可能的值声明为“ application / x-www-form-urlencoded”(默认),“ multipart / form-data”或“ text / plain”(仅HTML5)。来源: https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/form#attr-enctype (2认同)

Joe*_*ano 414

内容放在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
Run Code Online (Sandbox Code Playgroud)

您可以使用像Fiddler这样的工具来查看它,您可以使用它来查看通过网络发送的原始HTTP请求和响应有效负载.

  • 仅当内容类型为"application/x-www-form-urlencoded"时,情况并非总是如此. (37认同)
  • @Joe,现在为什么你会有一个'From`标题? (9认同)
  • @Joe,我喜欢随机包含 `From` 标题。IMO 上面有 418 HTTP 状态代码。 (2认同)

exh*_*uma 355

简答:在POST请求中,值在请求的"正文"中发送.对于网络表单,他们很可能使用application/x-www-form-urlencoded或的媒体类型发送multipart/form-data.已被设计用于处理网络请求的编程语言或框架通常做"正确的事情™"这样的请求,并为您提供轻松前往容易解码值(如$_REQUEST$_POST在PHP中,或者cgi.FieldStorage(),flask.request.form在Python).


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

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/plain,application/json甚至是习俗application/octet-stream.

在任何情况下,如果POST请求是由Content-Type应用程序无法处理的,则应返回415状态代码.

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

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

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

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

PUT(相关RFC部分)

一个PUT请求在完全相同的方式作为一个非常处理POST请求.最大的区别在于,POST请求应该让服务器决定如何创建新资源(如果有的话).从历史上看(从现在过时的RFC2616开始,创建一个新资源作为发送请求的URI的"从属"(子)).

PUT相反请求应该"存款"的资源恰好该URI,并用确切该内容.不多也不少.这个想法是客户负责在"PUT"之前制作完整的资源.服务器应该在给定的URL上按原样接受它.

因此,POST通常不会使用请求来替换现有资源.一个PUT请求可以做到既创造更换.

边注

还有" 路径参数 "可用于向遥控器发送附加数据,但它们非常罕见,我不会在这里详细介绍.但是,作为参考,这里是RFC的摘录:

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

  • @rogerdpack你没有错。如果您阅读“PUT”部分中的第二段,您将看到它*是*幂等的。相比之下,根据定义,“POST”可以不是。`POST` 将始终创建一个新资源。如果存在相同的资源,则“PUT”将替换它。因此,如果您调用 `POST` 10 次,您将创建 10 个资源。如果你调用 `PUT` 10 次,它(可能)只会创建一个。这是否回答你的问题? (2认同)

zur*_*fyx 57

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

您可以看到如何使用Live HTTP Headers在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
Run Code Online (Sandbox Code Playgroud)

在哪里说

Content-Length: 30
    username=zurfyx&pass=password
Run Code Online (Sandbox Code Playgroud)

将是岗位价值.

  • 标题与正文分开,带有额外的换行符 (3认同)
  • 澄清:这里的"内容长度"应该是"29"吗?这是字符串`username = zurfyx&pass = password`的实际长度. (2认同)

Nej*_*jat 23

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

例如:

Name: John Smith
Grade: 19
Run Code Online (Sandbox Code Playgroud)

编码为:

Name=John+Smith&Grade=19
Run Code Online (Sandbox Code Playgroud)

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

  • 您解释了我们在 HTTPBody 中放置的内容,但是我们在 HTTPHeader 中放置/写入了什么? (2认同)

Int*_*own 18

某些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
Run Code Online (Sandbox Code Playgroud)

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

请注意: HTTP/1.1 包含#32左侧的(空格)和#10右侧的(换行符).

  • 我只是强调了我无法在代码中标记的内容。这可能看起来很明显,但有时并非如此。 (2认同)

SLa*_*aks 17

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

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

  • @PeterWooster这是不需要的,但是当你忘记某些内容时,它会非常好,google它,转到第一个SO链接,并且有一个清晰,简洁的例子告诉你你需要什么而不是让你去咀嚼过于详细的规格,即使是全面的,也可能不适合复习.想想看:本网站上的大多数QA都可以归结为"去阅读规范/手册/ API /等*(链接)*".它会有用吗?不超过谷歌. (36认同)
  • @PeterWooster是的,但没有提供一个例子.在这方面,就像一个答案,说"看,你的问题的答案在应用程序的博客*(链接)*". (6认同)
  • "相同格式"有点含糊不清.他们是以"?"开头的吗? (4认同)
  • GET查询字符串的格式与application/x-www-form-urlencoded的格式不同.例如,空格的编码方式不同(%20 vs +).答案在这方面具有误导性. (3认同)
  • 仅当内容类型为"application/x-www-form-urlencoded"时,情况并非总是如此. (2认同)

Zee*_*dil 7

首先,让我们区分GETPOST

获取:这是默认的HTTP请求时向服务器和用于检索从后而来的服务器和查询字符串数据?中一个URI用于检索的独特资源。

这是格式

GET /someweb.asp?data=value HTTP/1.0
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

为什么在GET之上发布?

GET发送到服务器的值中,通常将其附加到查询字符串中的基本URL后面,这使您的数据能够被黑客入侵(对于过去暴露了您的凭据的Facebook来说,这是一个问题),这就是为什么POST习惯将数据发送到服务器,该服务器以前用于Request Body将数据发送到服务器,因为这会隐藏您的数据,并且会从字段中获取数据,计算它们的长度并将其添加到headerfor中,content-length并且没有重要数据直接附加到该服务器上,因此更加安全的URL

现在,使您的请求变得安全,可以将任何发送到服务器的值发送Request Body为,顾名思义,该值将包含用户想要发送的数据(并且以URL Encoded格式发送),并且Request Headers通过比较将保持请求的安全在该值Request BodyRequest Headers

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

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

你可以随时在你添加更多的价值Request Headers一样Cache-ControlOriginAccept

  • 关于安全性的假设仅在“ HTTPS”连接的上下文中才适用,而在“ HTTP”连接的上下文中则不成立。当“ HTTP”既不加密也不保护时,“ HTTPS”同时加密“ URL”(包括查询参数)和“请求正文”。所描述的问题来自以下事实:许多浏览器在其历史数据库(通常未加密)中存储URI(包括URL)。因此,对于任何敏感内容,请仅使用“请求正文” +“ HTTPS”。 (4认同)