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
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.
您还可以从Bing,Apple等获得400 Bad Request,这是由AkamaiGhost提供的 .
17 回答
根据XMLHttpRequest,它无效 . 来自standard:
虽然,我认为不应该因为GET请求可能需要大量的内容 .
因此,如果您依赖浏览器的XMLHttpRequest,它很可能无法正常工作 .
我'm upset that REST as protocol doesn' t支持OOP和
Get
方法是证明 . 作为解决方案,您可以将DTO序列化为JSON,然后创建查询字符串 . 在服务器端,您可以将查询字符串反序列化为DTO .看看:
Message-based design in ServiceStack
Building RESTful Message Based Web Services with WCF
基于消息的方法可以帮助您解决Get方法限制 . 您可以像请求正文一样发送任何DTO
Nelibur web service framework provides functionality which you can use
Roy Fielding's comment about including a body with a GET request .
是的,您可以使用GET发送请求正文,但它不应该有任何意义 . 如果您通过在服务器上解析它并根据其内容更改响应来赋予它意义,那么您在the HTTP/1.1 spec, section 4.3中忽略了此建议:
和the HTTP/1.1 spec, section 9.3中的GET方法的描述:
其中声明请求主体不是GET请求中资源标识的一部分,只是请求URI .
既不是restclient也不是REST console支持这个,但卷曲确实如此 .
HTTP specification在第4.3节中说
Section 5.1.1将各种方法重定向到第9.x节 . 他们都没有明确禁止包含消息体 . 然而...
Section 5.2说
和Section 9.3说
这一点一起表明,在处理GET请求时,服务器不需要检查Request-URI和Host头字段之外的任何其他内容 .
总之,HTTP规范并不会阻止您使用GET发送消息体,但是如果所有服务器都不支持它,那么它就不会让我感到惊讶 .
恕我直言,您可以在
URL
中发送JSON
编码(即encodeURIComponent
),这样您就不会违反HTTP
规范并将JSON
发送到服务器 .你可以发送一个GET与一个正文或发送一个POST并放弃RESTish宗教信仰(它不是那么糟糕,5年前只有一个信仰的成员 - 他的评论在上面联系) .
两者都不是很好的决定,但发送GET机构可以防止某些客户端和某些服务器出现问题 .
执行POST可能会遇到一些RESTish框架的障碍 .
Julian Reschke建议上面使用像“SEARCH”这样的非标准HTTP标头,这可能是一个优雅的解决方案,除了它更不可能得到支持 .
列出能够和不能完成上述各项工作的客户可能是最有效的 .
客户那个不能发送身体GET(我知道):
可以使用正文发送GET的客户端:
可以从GET检索主体的服务器和库:
Apache
PHP
从GET中剥离主体的服务器(和代理):
Elasticsearch接受带有正文的GET请求 . 它甚至似乎是首选方式:http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/common-options.html#_request_body_in_query_string
某些客户端库(如Ruby驱动程序)可以在开发模式下将cry命令记录到stdout,并且它正在广泛使用此语法 .
虽然你可以做到这一点,因为它不希望事情以这种方式发挥作用 . HTTP请求链中有许多阶段,虽然它们符合HTTP规范,但您只能考虑透明代理,加速器,A / V工具包等事情 . )
这是Robustness Principle背后的精神_B5954_,你不想在没有充分理由的情况下突破规范的界限 .
但是,如果你有充分的理由,那就去吧 .
我不建议这样做,它违背了标准做法,并没有提供那么多回报 . 你想保持身体的内容,而不是选择 .
如果您真的想将可缓存的JSON / XML主体发送到Web应用程序,那么放置数据的唯一合理位置是使用RFC4648: Base 64 Encoding with URL and Filename Safe Alphabet编码的查询字符串 . 当然你可以只是urlencode JSON并将put放在URL param的值中,但Base64会给出较小的结果 . 请注意,有URL大小限制,请参阅What is the maximum length of a URL in different browsers? .
您可能认为Base64的填充
=
字符可能对URL的参数值不好,但似乎没有 - 请参阅此讨论:http://mail.python.org/pipermail/python-bugs-list/2007-February/037195.html . 但是,您不应该将编码数据放在没有参数名称的情况下,因为带有填充的编码字符串将被解释为具有空值的参数键 . 我会用?_b64=<encodeddata>
这样的东西 .例如,它适用于Curl,Apache和PHP .
PHP文件:
控制台命令:
输出:
您尝试实现的目标已经使用更常见的方法完成了很长时间,并且不依赖于使用GET的有效负载 .
您可以简单地构建特定的搜索媒体类型,或者如果您想要更加RESTful,请使用类似OpenSearch的内容,并将请求POST到服务器指示的URI,例如/ search . 然后,服务器可以生成搜索结果或构建最终URI并使用303重定向 .
这具有遵循传统PRG方法的优点,有助于缓存中介缓存结果等 .
也就是说,无论如何,URI都会被编码为非ASCII的任何东西,application / x-www-form-urlencoded和multipart / form-data也是如此 . 如果您的目的是支持ReSTful场景,我建议使用此而不是创建另一种自定义json格式 .
例如 Google 比忽略它更糟糕,它会认为它是 error !
使用简单的netcat自己尝试一下:
(1234内容后跟CR-LF,因此总共6个字节)
你会得到:
您还可以从Bing,Apple等获得400 Bad Request,这是由AkamaiGhost提供的 .
所以我不建议将GET请求与body实体一起使用 .
来自RFC 2616, section 4.3,"Message Body":
也就是说,服务器应始终从网络中读取任何提供的请求主体(检查Content-Length或读取分块的主体等) . 此外,代理人应转发他们收到的任何此类请求正文 . 然后,如果RFC为给定方法定义了主体的语义,则服务器实际上可以使用请求主体来生成响应 . 但是,如果RFC没有为正文定义语义,那么服务器应该忽略它 .
这符合上面Fielding的引用 .
Section 9.3,"GET"描述了GET方法的语义,并没有提到请求体 . 因此,服务器应该忽略它在GET请求上收到的任何请求主体 .
那么不合格的base64编码头呢? “SOMETHINGAPP-PARAMS:sdfSD45fdg45 / AS”
长度限制hm . 你不能让你的POST处理区分意义吗?如果你想要简单的参数,比如排序,我不明白为什么这会是一个问题 . 我想你确实很担心 .
如果您尝试利用缓存,则可能会遇到问题 . 代理人不会在GET主体中查看参数是否会对响应产生影响 .
我把这个问题提交给了IETF HTTP WG . Roy Fielding(1998年http / 1.1文件的作者)的评论是这样的
RFC 7213(HTTPbis)状态:
现在似乎很清楚,目的是禁止GET请求体上的语义,这意味着请求体不能用于影响结果 .
如果您在GET上包含一个正文,那么会有代理以各种方式破坏您的请求 .
总而言之,不要这样做 .