Pau*_*gan 1578
是.换句话说,任何HTTP请求消息都允许包含消息体,因此必须解析消息.但是,GET的服务器语义受到限制,使得正文(如果有的话)对请求没有语义含义.解析的要求与方法语义的要求是分开的.
所以,是的,你可以使用GET发送一个正文,不,这样做永远不会有用.
这是HTTP/1.1的分层设计的一部分,一旦规范被分区(正在进行中),它将再次变得清晰.
罗伊....
是的,您可以使用GET发送请求正文,但它不应该有任何意义.如果你通过在服务器上解析它并根据其内容更改响应来赋予它意义,那么你忽略了HTTP/1.1规范第4.3节中的这个建议:
[...]如果请求方法不包含实体主体的定义语义,那么在处理请求时应该忽略消息体.
和HTTP/1.1规范中的GET方法的描述,第9.3节:
GET方法意味着检索Request-URI标识的任何信息([...]).
其中声明请求主体不是GET请求中资源标识的一部分,只是请求URI.
更新 引用为"HTTP/1.1规范"的RFC2616现已过时.2014年,它被RFC 7230-7237取代.引用"处理请求时应该忽略消息体"已被删除.它现在只是"请求消息框架独立于方法语义,即使该方法没有定义消息体的任何用途"第二个引用"GET方法意味着检索任何信息......由Request-URI标识"被删除了. - 来自评论
cas*_*key 273
虽然你可以这样做,但是在HTTP规范没有明确排除的范围内,我建议避免使用它只是因为人们不希望事情以这种方式工作.HTTP请求链中有许多阶段,虽然它们"大部分"符合HTTP规范,但您唯一可以肯定的是它们的行为与Web浏览器一样.(我在想透明代理,加速器,A/V工具包等等)
这就是" 稳健性原则 " 背后的精神,大致是"你接受的是自由的,你所发送的是保守的",你不想在没有充分理由的情况下突破规范的界限.
但是,如果你有充分的理由,那就去吧.
Dar*_*ler 140
如果您尝试利用缓存,则可能会遇到问题.代理人不会在GET主体中查看参数是否会对响应产生影响.
Mar*_*son 94
GET
,有身体!?就规范而言,您可以,但是,正如我们将看到的,不明智地这样做并不是一个好主意。
\nRFC 7231 \xc2\xa74.3.1规定主体“没有定义的语义”,但这并不是说它是被禁止的。如果您将正文附加到请求中,那么您的服务器/应用程序将如何处理它,这取决于您。RFC 继续指出 GET 可以是“各种数据库记录的编程视图”。显然,这样的视图多次是由大量输入参数定制的,将这些输入参数放入请求目标的查询组件中并不总是方便甚至安全。
\n好处:我喜欢这些措辞。很明显,读取/获取资源不会对服务器产生任何可观察到的副作用(该方法是“安全的”),并且无论第一个请求的结果如何,都可以重复请求以达到相同的预期效果(该方法是“幂等的”)。
\n坏处: HTTP/1.1 的早期草案禁止 GET 有正文,并且据称,某些实现甚至直到今天都会删除正文、忽略正文或拒绝消息。例如,哑 HTTP 缓存可能仅根据请求目标构造缓存密钥,而忽略主体的存在或内容。甚至更愚蠢的服务器可能会如此无知,以至于将正文视为新请求,这实际上被称为“请求走私”(这是“向一个设备发送请求,而另一设备不知道的行为” -来源)。
\n由于我认为主要是对实现之间的不可操作性的担忧,正在进行的工作建议将 GET 主体分类为“不应该”,“除非[请求]直接发送到先前已指示的原始服务器,在或在带外,这样的请求是有目的的并且将得到充分的支持”(强调我的)。
\n解决办法:有一些技巧可以用来解决这种方法的一些问题。例如,只需将从正文派生的哈希值附加到查询组件,或者通过响应cache-control: no-cache
来自服务器的标头来完全禁用缓存,即可将正文不感知的缓存间接变为正文感知。
遗憾的是,当涉及到请求链时,人们通常无法控制甚至不知道所有当前和未来的 HTTP 中介以及它们将如何处理 GET 主体。这就是为什么这种方法通常被认为是不可靠的。
\nPOST
,不是幂等的!POST
是一个替代方案。POST 请求通常包含消息正文(仅供记录,正文不是必需的,请参阅RFC 7230 \xc2\xa73.3.2)。RFC 7231 ( \xc2\xa74.3.3 )中的第一个用例示例是“向数据处理过程提供数据块[...]”。因此,就像对 body 进行 GET 一样,后端的 body 会发生什么取决于您。
好处:当人们希望出于任何目的发送请求正文时,也许可以采用一种更常见的方法,因此,团队成员可能会产生最少的噪音(有些人可能仍然错误地认为 POST 必须创建资源)。
\n此外,我们经常传递参数的是一个对不断变化的数据进行操作的搜索函数,并且只有在响应中提供了明确的新鲜度信息时,POST 响应才可缓存。
\n缺点: POST 请求未定义为幂等,导致请求重试犹豫。例如,在页面重新加载时,浏览器不愿意重新提交 HTML 表单而不用不可读的神秘消息提示用户。
\n修复:好吧,仅仅因为 POST 没有被定义为幂等并不意味着它一定不能是幂等的。事实上,RFC 7230 \xc2\xa76.3.1写道:“知道(通过设计或配置)对给定资源的 POST 请求是安全的用户代理可以自动重复该请求”。因此,除非您的客户端是 HTML 表单,否则这可能不是一个真正的问题。
\nQUERY
是圣杯有一个新方法的提案QUERY
,它定义了消息正文的语义并将该方法定义为幂等的。看到这个。
编辑:作为旁注,在发现他们仅使用PUT
服务器端搜索功能的请求的代码库后,我偶然发现了这个 StackOverflow 问题。他们的想法是包含一个带有参数的主体并且也是幂等的。PUT 的问题是请求正文具有非常精确的语义。具体来说,PUT“请求创建目标资源的状态或用[主体中]的状态替换”(RFC 7231 \xc2\xa74.3.4)。显然,这排除了 PUT 作为可行的选择。
Dav*_*bin 69
restclient和REST控制台都不支持这个,但卷曲确实如此.
的HTTP规范说,在第4.3节
如果请求方法的规范(第5.1.1节)不允许在请求中发送实体主体,则消息主体不得包含在请求中.
第5.1.1节将我们重定向到第9.x节的各种方法.他们都没有明确禁止包含消息体.然而...
通过检查Request-URI和Host头字段来确定Internet请求标识的确切资源.
而9.3节说
GET方法意味着检索由Request-URI标识的任何信息(以实体的形式).
这一点一起表明,在处理GET请求时,服务器不需要检查Request-URI和Host头字段之外的任何其他内容.
总之,HTTP规范并不会阻止您使用GET发送消息体,但是如果所有服务器都不支持它,那么它就不会让我感到惊讶.
jle*_*our 48
Elasticsearch接受带有正文的GET请求.这似乎是首选方式:http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/common-options.html#_request_body_in_query_string
某些客户端库(如Ruby驱动程序)可以在开发模式下将cry命令记录到stdout,并且它正在广泛使用此语法.
Ser*_*Seb 30
您尝试实现的目标已经使用更常见的方法完成了很长时间,并且不依赖于使用GET的有效负载.
您可以简单地构建特定的搜索媒体类型,或者如果您想要更加RESTful,请使用类似OpenSearch的内容,并将请求POST到服务器指示的URI,比如/ search.然后,服务器可以生成搜索结果或构建最终URI并使用303重定向.
这具有遵循传统PRG方法的优点,有助于缓存中介缓存结果等.
也就是说,无论如何,URI都会被编码为非ASCII的任何东西,application/x-www-form-urlencoded和multipart/form-data也是如此.如果您的目的是支持ReSTful场景,我建议使用此而不是创建另一种自定义json格式.
fij*_*ron 22
你可以发送一个GET与一个正文或发送一个POST并放弃RESTish宗教信仰(它不是那么糟糕,5年前只有一个信仰成员 - 他的评论在上面联系).
也不是很好的决定,但发送GET机构可能会阻止某些客户端和某些服务器出现问题.
执行POST可能会遇到一些RESTish框架的障碍.
Julian Reschke建议使用像"SEARCH"这样的非标准HTTP标头,这可能是一个优雅的解决方案,除了它更不可能得到支持.
列出能够和不能完成上述各项操作的客户可能是最有效的.
无法通过身体发送GET的客户(我知道):
可以使用正文发送GET的客户端:
可以从GET检索正文的服务器和库:
从GET中剥离主体的服务器(和代理):
小智 22
哪个服务器会忽略它? - fijiaaron 2012年8月30日21:27
例如Google比忽略它更糟糕,它会认为这是一个错误!
使用简单的netcat自己尝试:
$ netcat www.google.com 80
GET / HTTP/1.1
Host: www.google.com
Content-length: 6
1234
Run Code Online (Sandbox Code Playgroud)
(1234内容后跟CR-LF,所以总共6个字节)
你会得到:
HTTP/1.1 400 Bad Request
Server: GFE/2.0
(....)
Error 400 (Bad Request)
400. That’s an error.
Your client has issued a malformed or illegal request. That’s all we know.
Run Code Online (Sandbox Code Playgroud)
您还可以从Bing,Apple等获得400 Bad Request,这是由AkamaiGhost提供的.
所以我不建议将GET请求与body实体一起使用.
izr*_*rik 17
从RFC 2616,第4.3节 "消息正文":
服务器应该在任何请求上读取和转发消息体; 如果请求方法不包含实体主体的定义语义,那么在处理请求时应该忽略消息主体.
也就是说,服务器应始终从网络中读取任何提供的请求主体(检查Content-Length或读取分块的主体等).此外,代理应转发他们收到的任何此类请求正文.然后,如果RFC为给定方法定义了主体的语义,则服务器实际上可以使用请求主体来生成响应.但是,如果RFC 没有为正文定义语义,那么服务器应该忽略它.
这符合上面Fielding的引用.
第9.3节 "GET"描述了GET方法的语义,并没有提到请求体.因此,服务器应该忽略它在GET请求上收到的任何请求主体.
小智 17
我把这个问题提交给了IETF HTTP WG.Roy Fielding的评论(1998年http/1.1文件的作者)就是这样
"......除了解析和丢弃该机构以外,还可以执行任何其他操作"
RFC 7213(HTTPbis)声明:
"GET请求消息中的有效负载没有定义的语义;"
现在似乎很清楚,目的是禁止GET请求体上的语义,这意味着请求体不能用于影响结果.
如果你在GET上包含一个正文,那里有代理肯定会以各种方式破坏你的请求.
总而言之,不要这样做.
小智 8
根据XMLHttpRequest,它无效.从标准:
4.5.6
send()
方法Run Code Online (Sandbox Code Playgroud)client . send([body = null])
发起请求.可选参数提供请求正文.如果请求方法是
GET
或,则忽略该参数HEAD
.
InvalidStateError
如果未打开任何状态或send()
设置了标志,则引发异常 .该方法必须运行以下步骤:
send(body)
- 如果未打开状态,则抛出
InvalidStateError
异常.- 如果
send()
设置了标志,则抛出InvalidStateError
异常.- 如果请求方法是
GET
或HEAD
,则将body设置为null.- 如果body为null,请转到下一步.
虽然,我认为不应该因为GET请求可能需要大量的内容.
因此,如果您依赖浏览器的XMLHttpRequest,它很可能无法正常工作.
如果您真的想要将可缓存的JSON/XML主体发送到Web应用程序,那么放置数据的唯一合理位置是使用RFC4648编码的查询字符串:Base 64 Encoding with URL and Filename Safe Alphabet.当然你可以只是urlencode JSON并将put放在URL param的值中,但Base64会给出较小的结果.请记住,有URL大小限制,请参阅不同浏览器中URL的最大长度是多少?.
您可能认为Base64的填充=
字符可能对URL的param值不利,但似乎没有 - 请参阅此讨论:http://mail.python.org/pipermail/python-bugs-list/2007-February/037195.html.但是,您不应该将编码数据放在没有参数名称的情况下,因为带有填充的编码字符串将被解释为具有空值的参数键.我会用类似的东西?_b64=<encodeddata>
.
您有一个选项列表,这些选项比使用带有 GET 的请求正文要好得多。
假设您有每个类别的类别和项目。两者都由 id 标识(在本示例中为“catid”/“itemid”)。您想按照特定“顺序”中的另一个参数“sortby”进行排序。您想为“sortby”和“order”传递参数:
你可以:
example.com/category/{catid}/item/{itemid}?sortby=itemname&order=asc
example.com/category/{catid}/item/{itemid}/{sortby}/{order}
都有它们的缺点,但比使用带有 body 的 GET 好得多。
我很不高兴REST协议不支持OOP,Get
方法就是证据.作为解决方案,您可以将DTO序列化为JSON,然后创建查询字符串.在服务器端,您可以将查询字符串反序列化为DTO.
看看:
基于消息的方法可以帮助您解决Get方法限制.您可以像请求正文一样发送任何DTO
var client = new JsonServiceClient(Settings.Default.ServiceAddress);
var request = new GetClientRequest
{
Id = new Guid("2217239b0e-b35b-4d32-95c7-5db43e2bd573")
};
var response = client.Get<GetClientRequest, ClientResponse>(request);
as you can see, the GetClientRequest was encoded to the following query string
http://localhost/clients/GetWithResponse?type=GetClientRequest&data=%7B%22Id%22:%2217239b0e-b35b-4d32-95c7-5db43e2bd573%22%7D
Run Code Online (Sandbox Code Playgroud)
不符合 base64 编码的标头呢?“一些应用程序参数:sdfSD45fdg45/aS”
长度限制嗯。你不能让你的 POST 处理区分含义吗?如果你想要像排序这样的简单参数,我不明白为什么这会成为一个问题。我想你肯定担心。
如果您想允许带有正文的 GET 请求,一种方法是支持带有标头“X-HTTP-Method-Override: GET”的 POST 请求。此处描述: https: //en.wikipedia.org/wiki/List_of_HTTP_header_fields。此标头意味着虽然方法是 POST,但应将请求视为 GET。正文允许用于 POST,因此您确信没有人会丢弃您的 GET 请求的有效负载。
此标头通常用于通过某些无法识别这些方法的代理发出 PATCH 或 HEAD 请求,并用 GET 替换它们(调试起来总是很有趣!)。
归档时间: |
|
查看次数: |
979291 次 |
最近记录: |