纠正采用二进制数据的nullipotent操作的HTTP请求方法

时间:2014-12-14 00:29:39

标签: rest http post get asp.net-web-api

考虑一个没有副作用的Web API方法,但它将二进制数据作为参数。一个示例是一种方法,告诉用户他们的图像是否是照片,但不会将图像或结果永久存储在其服务器上。

这种方法应该是GET还是POST

GET似乎没有推荐的方法在URL参数之外发送数据,但该方法的行为意味着GET,根据HTTP规范,它是安全的,无状态的响应。这在REST的语义下尤其受到限制,这意味着POST方法在服务器上创建了一个新对象。

2 个答案:

答案 0 :(得分:4)

  

这特别限制了REST的语义,这意味着POST方法在服务器上创建了一个新对象。

虽然POST请求意味着发送的实体将被视为"作为Request-URI"标识的资源的新下属,但不要求此结果创建一个新的永久对象或任何这样的新对象由URI标识(因此,就客户端所知,没有新对象)。物体可以是瞬态的,代表例如"提供数据块,例如提交表单的结果,数据处理过程"并且在表示该对象的实体已被发送后不持久。

虽然这意味着POST 可以创建一个新资源,当它是将为该新资源提供其URI的服务器时,肯定是最好的方法(与当客户端指示新URI时,PUT是更合适的方法,它也可以用于删除对象的情况(尽管如果它删除了可由URI识别的单个*资源,那么{ {1}}更合适了,无论是创建和删除对象,还是更改多个对象,都可能意味着您的厨房灯亮起,但响应是相同的,无论是否有效,因为从网络服务器到厨房的通信光不允许有关成功的反馈。它真的可以做任何事情。

但是,你的本能很好,希望这是一个DELETE:虽然GET的松散意味着我们可以为几乎所有请求提供一个案例(正如使用的方法所做的那样)用于类似RPC的协议的HTTP,基本上将HTTP视为传输协议,这在理论上是不优雅的,在实践中效率低,在定义上很笨拙。你有一个幂等函数,它完全依赖于客户感兴趣的东西,并且在某些方面最明显地映射了POST

如果我们可以将所有内容都放在URI中,那么GET就很容易了。例如,我们可以定义一个简单的整数加法,类似GET表示添加http://example.net/addInts?x=1;y=271,因此是一个表示数字3的永久不可变资源(因为{{1的结果)随着时间的推移,随着资源的变化而变化,但是这个资源永远不会改变)然后使用像HTML 2或javascript这样的机制来允许服务器通知客户端如何构造其他数字的URI(以维护HATEOS和/或COD约束)。 Simples!

这里的问题是,您没有可以简洁地表示的输入,因为数字GET<form>可以在上面。从理论上讲,您可以执行1之类的操作,从而创建一个表示检查结果资源的URI。但是,该URI对于图像中的每3个字节将具有4个字符。虽然URI长度没有绝对限制,但理论和实践都允许它失败(理论上HTTP允许代理和服务器设置URI长度的限制,并且在实践中它们确实如此)。

可以使用2并使用与http://example.net/photoshoppedCheck?image=data:image/png;base64,iVBORw0KGgoAAAANSU…相同的方式发送请求正文,并且某些网络服务器甚至允许您执行此操作。但是,GET被定义为返回描述URI中标识的资源的实体,其中标题限制了该实体的描述:由于请求主体不是该定义的一部分,因此必须你的代码忽略了!如果你想弯曲这个规则那么你必须考虑:

  1. 有些网络服务器会拒绝请求或剥离正文,因此您可能无法使用。
  2. 如果您的网络服务器确实允许,那么未指定的事实意味着您无法确定升级是否赢得了修复&#34;这样就破坏了你的代码。
  3. 有些代理会拒绝或删除请求。
  4. 一些客户端库肯定会拒绝允许开发人员发送请求正文以及POST
  5. 所以理论和实践都是禁忌。

    关于我们除了GET之外我们可以做的唯一其他方法是拥有一个我们认为代表未映射的图像的URI。因此,如果你GET得到一个描述图像的实体(显然它可能是实际的图像,但如果我们延伸内容协商的概念它也可能是其他的东西)然后POST将检查图像,如果它被认为没有被拍照,它会使用相同的图像和GET或只是PUT进行响应,而如果它被认为是照片,则会以200回复,因为我们尝试204将photoshopped图片作为资源,只能是非photoshopped图片。因为我们立即回应,所以没有同时请求的竞争条件。

    坦率地说,这对我来说太可怕了。虽然我认为我已经通过规范的字母为它做了一个案例,但这只是令人讨厌的:REST旨在帮助我们设计清晰的API,而不是我们可以提供过于聪明的钝的API - 具有良好的理由。

    不,一直到这里是将400图像转换为固定的URI,然后返回一个描述分析的简单实体。

    它完全合理,因为REST(PUT基于该图像创建一个瞬态对象,然后用描述该对象的实体进行响应,然后该对象再次消失)。它是直截了当的。它尽可能高效(我们不能进行任何HTTP缓存†但大多数网络延迟都是在上传而不是下载)。它也适用于&#34;处理某些事物的一般用例。 POST最初是为此而发明的。 (请记住,首先是HTTP,然后REST描述了它为什么运行良好,然后改进了HTTP以更好地发挥这些优势)。

    总而言之,将Web应用程序从REST移开的典型错误是在POSTPOSTPOST(以及GET时滥用PUT来绝对做所有事情。也许是WebDAV方法)会更优越,不会在那些不符合条件的情况下使用它的权力,并且不会认为资源的新下属&# 34;必须意味着一个完整的长寿资源。


    *请注意&#34;单身&#34;这里的资源可能由几个可能有自己的URI的资源组成,因此可以很容易地有一个删除多个对象的DELETE,但如果删除X则删除A,B&amp; C然后更明显的是,如果您没有X或者您的API不可理解,您就无法拥有A,B或C.一般来说,这取决于被建模的内容,以及一件事取决于另一件事的程度是多么明显。

    †严格来说,我们可以,因为我们可以发送缓存标头,表明向同一个URI发送相同的实体会产生相同的结果,但是没有通用的网络软件将会这样做,您的自定义客户端可以记住&#34;无论如何,关于给定图像本身的意见。

答案 1 :(得分:1)

这很难。与许多其他场景一样,没有绝对正确的方法。您必须尝试根据HTTP语义的限制来解释RESTful原则。 (顺便说一下,我认为将REST视为语义是不对的,REST是一种常用于HTTP服务的架构风格,但可用于任何类型的接口。)

我目前的项目遇到了类似的情况。我们选择使用POST,但响应代码为200(OK),而不是RESTful Web API通常返回的201(资源创建)。