在HTTP GET请求中,参数作为查询字符串发送:
1
| http://example.com/page?parameter=value&also=another |
在HTTP POST请求中,参数不会随URI一起发送。
价值观在哪里?在请求头中?在请求主体中?它是什么样子的?
这些值以内容类型指定的格式在请求正文中发送。
通常内容类型为application/x-www-form-urlencoded,因此请求主体使用与查询字符串相同的格式:
1
| parameter=value&also=another |
当您使用表单中的文件上传时,您使用的是multipart/form-data编码,它的格式不同。它更复杂,但是你通常不需要关心它是什么样子的,所以我不会举一个例子,但是知道它的存在是很好的。
- 我忘记了文件上传是不同的(+1/接受)。你的回答足够了,不过如果有更多关于multipart/form-data的信息,那就太好了。不过,对于那些感兴趣的人,这里有一个问题。
- 注意:正文与标题之间只有一行空白。
- 您解释了我们在httpbody中放置的内容,但是我们在httpheader中放置/写入的内容是什么?它有什么作用?
- @亲爱的:一个帖子的HTTP头看起来像一个GET头,但是用动词post代替GET,并用content-type值(和可选的content-length值)作为请求的内容(body)。每种类型的请求都有一个头部,有些类型也有一个主体。
- 你能用这个方法发送JSON吗?
- @Kennethworden否,非方法将正确发送JSON。但是,您可以以使用multipart/form-data编码的格式上载JSON文件,或者如果您负责请求构造,可以将内容类型更改为application/json并将JSON文本直接粘贴到HTTP正文中。
- 就编码而言,MDN文档将可能的值声明为application/x-www-form-urlencoded(默认)、multipart/form-data或text/plain(仅限html5)源:developer.mozilla.org/en-us/docs/web/html/element/…
- @Guffa其他请求类型如Put和Delete呢?这是否应用于投递请求?如果是,我们可以为这个查询提供任何用例吗?
- 由于这个问题明确地说明了相反的情况,所以应该提到,POST请求可能与GET请求一样具有URL编码的查询参数。虽然这可能不是常见的做法,但它得到了有效的使用:斯坦福的corenlp工具。在这种特定情况下,查询参数甚至包含与@kennethworden的注释部分相关的JSON编码值。
- 以下问题的答案也很有趣。application/x-www-form-urlencoded或multipart/form数据?
内容放在HTTP头之后。HTTP POST的格式是让HTTP头后跟一个空白行,再跟请求主体。post变量在主体中存储为键值对。
您可以在http文章的原始内容中看到这一点,如下所示:
1 2 3 4 5 6 7
| POST /path/script.cgi HTTP/1.0
From: [email protected]
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时,情况并非总是如此。
- @卡米洛·马丁……[+1]对于伟大的问题&;@Joe Alfano….[+1]很好的回答……我现在对邮局的要求有了一个清晰的认识……但是如果一个图像带有键,值对的数据信息…..帖子的结构如何?
- @乔,你为什么要在那里有一个From的头球?
- @乔,我喜欢随机包含From头球。在上面有418HTTP状态代码。
简短回答:在POST请求中,值在请求的"正文"中发送。对于web表单,它们最有可能使用application/x-www-form-urlencoded或multipart/form-data的媒体类型发送。为处理Web请求而设计的编程语言或框架通常做"正确的事情"?有了这些请求,您就可以方便地访问容易解码的值(如php中的$_REQUEST或$_POST,或者python中的cgi.FieldStorage(),flask.request.form)。好的。
现在让我们离题一点,这可能有助于理解区别;)好的。
GET和POST请求之间的差异很大程度上是语义上的。它们的"使用"也不同,这就解释了如何传递值的不同。好的。GET(相关RFC部分)
当执行GET请求时,您向服务器请求一个或一组实体。为了允许客户机过滤结果,它可以使用URL的所谓"查询字符串"。查询字符串是?后面的部分。这是URI语法的一部分。好的。
因此,从应用程序代码(接收请求的部分)的角度来看,您需要检查URI查询部分以获得对这些值的访问。好的。
请注意,键和值是URI的一部分。浏览器可能会对URI长度施加限制。HTTP标准规定没有限制。但在撰写本文时,大多数浏览器确实限制了URI(我没有特定的值)。不应使用GET请求向服务器提交新信息。尤其是大文件。这就是你应该使用POST或PUT的地方。好的。岗位(相关RFC部分)
当执行POST请求时,客户机实际上正在向远程主机提交一个新的文档。因此,查询字符串(语义上)没有意义。这就是为什么在应用程序代码中您不能访问它们。好的。
POST有点复杂(而且更灵活):好的。
当接收到一个POST请求时,您应该总是期望一个"有效负载",或者用HTTP术语来说:一个消息体。消息体本身是非常无用的,因为没有标准(据我所知)。可能是应用程序/八位字节流?)格式。正文格式由Content-Type头定义。当将html FORM元素与method="POST"一起使用时,通常是application/x-www-form-urlencoded。另一种非常常见的类型是多部分/表单数据(如果使用文件上载)。但是它可以是任何东西,从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(相关RFC部分)
PUT请求的处理方式与POST请求的处理方式基本相同。最大的区别是,POST请求应该让服务器决定如何(如果有的话)创建新资源。历史上(从现在已经过时的RFC2616开始,它将创建一个新的资源作为请求发送到的URI的"从属"(子)资源)。好的。
相比之下,PUT请求应该在该URI上"存储"一个资源,并使用该内容。不多不少。其理念是,客户负责在"投入"资源之前创造出完整的资源。服务器应该接受给定URL上的内容。好的。
因此,POST请求通常不用于替换现有资源。PUT请求既可以创建也可以替换。好的。边注
还有一些"路径参数"可以用来向远程服务器发送额外的数据,但它们非常罕见,我在这里不会详细介绍。但是,作为参考,这里有一个来自RFC的摘录:好的。
Aside from dot-segments in hierarchical paths, a path segment is considered
opaque by the generic syntax. URI producing applications often use the
reserved characters allowed in a segment to delimit scheme-specific or
dereference-handler-specific subcomponents. For example, the semicolon (";")
and equals ("=") reserved characters are often used to delimit parameters and
parameter values applicable to that segment. The comma (",") reserved
character is often used for similar purposes. For example, one URI producer
might use a segment such as"name;v=1.1" to indicate a reference to version
1.1 of"name", whereas another might use a segment such as"name,1.1" to
indicate the same. Parameter types may be defined by scheme-specific
semantics, but in most cases the syntax of a parameter is specific to the
implementation of the URIs dereferencing algorithm.
Ok.
好啊。
- 我可能真的有点相切了。我在答案的顶部加了一个"tl;dr",这应该更清楚。
- 我刚才还把它编辑成参考RFC7231而不是RFC2616(已经过时一段时间了)。除了更新的链接,这个答案的主要区别在于"放置"部分。
- 我认为Put的处理方式与Post不同,因为它应该是等幂的?stackoverflow.com/questions/611906/…
- @罗杰帕克,你没有错。如果你读了PUT部分的第二段,你会发现它是等幂的。相反,根据定义,POST可以不是。POST将始终创建新资源。如果存在相同的资源,PUT将替换它。因此,如果您给POST打10次电话,您将创建10个资源。如果你给PUT打10次电话,它(可能)只会创建一个。那能回答你的问题吗?
不能直接在浏览器的URL栏上键入。
例如,您可以看到如何通过实时HTTP头在Internet上发送日志数据。结果会是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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 |
在哪里说
1 2
| Content-Length: 30
username=zurfyx&pass=password |
将是post值。
- 用于记住主机字段。
- 说明:这里是不是应该是29?这是字符串username=zurfyx&pass=password的实际长度。
- @河马是一个换行的角色吗?
- @我明白你的意思了。所以我想内容的结尾总是有一个新行。
- 标题与正文之间用额外的换行符分隔
post请求中的默认媒体类型是application/x-www-form-urlencoded。这是用于编码键值对的格式。钥匙可以重复。每个键值对由一个&字符分隔,每个键值与它的值由一个=字符分隔。
例如:
1 2
| Name: John Smith
Grade: 19 |
编码为:
1
| Name=John+Smith&Grade=19 |
这将放在HTTP头后面的请求主体中。
- 您解释了我们在httpbody中放置的内容,但是我们在httpheader中放置/写入的内容是什么?
- 你提到钥匙可能是重复的,那么这种重复的结果是什么?最后一个将自动覆盖以前的值吗?谢谢。
一些Web服务要求您分别放置请求数据和元数据。例如,远程函数可能期望签名的元数据字符串包含在URI中,而数据发布在HTTP主体中。
POST请求在语义上可能如下所示:
1 2 3 4 5 6 7 8 9 10 11 12
| 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,后者是Web服务器的"解析指令"。
请注意:http/1.1的包装左侧为EDOCX1(空格),右侧为EDOCX1(换行)。
- /user/john和/?user=john之间的区别仅仅是语义上的区别(HTTP并没有对查询字符串进行特殊处理),所以我认为这是合理的预期。但是你所说的"被左边的空间包裹"是什么意思呢?There aren't spaces before the HTTP method. 你的意思是柱体的空白线?
- 在上述代码中,...Ym04和HTTP/1.1之间有一个空格(ascii 32)。所以查询字符串只存在于动词和协议版本之间。
- 您的注释使其听起来像是意外的、特定于版本的内容。坦白地说,很明显那里有一个空间。换行也适用于其他行,就像所有的Unix一样。
- 我只是强调了我不能在代码中标出的内容。这似乎很明显,但有时不是。
- 的确,我们可以像处理GET请求那样,通过使用?分隔uri和参数,将查询参数作为URL的一部分来传递。
HTTP POST中的表单值以与查询字符串相同的格式在请求正文中发送。
有关详细信息,请参见规范。
- "同样的格式"有点含糊不清。例如,它们是从一个?开始的吗?
- @camilomartin:不;格式与querystring的内容相同。看说明书。
- 如果你想更具体一点,请阅读RFC:tools.ietf.org/html/rfc2616第54页
- 顺便说一句,这个答案和另一个一样好,它实际上表示值进入请求主体。它提供了W3C规范。
- @是的,但没有提供一个例子。在这方面,就像回答"看,在应用程序的博客(链接)中有一个问题的答案"一样。
- @彼得沃斯特,这是不需要的,但它是非常好的,当你忘记了一些东西,谷歌它,去第一个链接,这是如此,有一个清晰,简明的例子告诉你需要什么,而不是让你去咀嚼过度详细的规格,即使是全面的,可能是不适合刷新。想一想:这个站点上的大多数QA可以归结为"阅读规范/手册/API/etc(链接)"。它有用吗?不超过谷歌。
- 只有当内容类型为application/x-www-form-urlencoded时,情况并非总是如此。
- get查询字符串的格式不同于application/x-www-form-urlencoded。例如,空白的编码方式不同(20对+)。答案在这方面有误导性。
首先,我们来区分GET和POST
GET:是对服务器的默认HTTP请求,用于从服务器中检索数据,查询字符串在URI中的?之后,用于检索唯一资源。
这是格式
1
| GET /someweb.asp?data=value HTTP/1.0 |
这里,data=value是传递的查询字符串值。
post:它用于将数据安全地发送到服务器,以便在需要时使用,这是POST请求的格式。
1 2 3 4 5
| 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中,发送到服务器的值通常附加到查询字符串中的基URL,这使您的数据能够被黑客攻击(在Facebook中,这在几天内是一个问题,在Facebook中,您的凭据被公开),这就是为什么POST被用于向使用Request Body将数据发送到服务器的原因。ER更安全,因为它隐藏了您的数据,加上它从字段中获取您的数据,计算它们的长度,并将它们添加到header中,用于content-length,并且没有重要数据直接附加到URL。
既然您的请求是安全的,那么任何发送到服务器的值都可以在Request Body中发送,因为名称意味着它将包含用户想要发送的数据(并且以URL Encoded格式发送),并且Request Headers将通过比较Request Body和Request Headers中的值来保持请求的安全性。
您可以使用Google开发人员工具的网络部分查看有关如何向服务器发出请求的基本信息。
你可以在你的Request Headers中添加更多的值,比如Cache-Control、Origin、Accept。
- 关于安全性的假设只在HTTPS连接的情况下是正确的,而不是HTTP连接的情况下。HTTPS加密URL(包括查询参数)和Request Body,当HTTP既不加密也不保护时。所描述的问题来自这样一个事实:许多浏览器将URIs(包括URLs)存储在其历史数据库中(通常不加密)。所以,对于任何敏感的东西,只使用Request Body+HTTPS。
- @我同意你的解释。您也可以建议将此作为编辑,我很乐意接受!:)