REST API – 为什么使用PUT DELETE POST GET?

所以,我正在浏览一些关于创buildREST API的文章。 其中一些build议使用所有types的HTTP请求:如PUT DELETE POST GET 。 我们将创build例如index.php并以这种方式编写API:

 $method = $_SERVER['REQUEST_METHOD']; $request = split("/", substr(@$_SERVER['PATH_INFO'], 1)); switch ($method) { case 'PUT': ....some put action.... break; case 'POST': ....some post action.... break; case 'GET': ....some get action.... break; case 'DELETE': ....some delete action.... break; } 

好的,已经被授予 – 我对web服务(还没有太多了解)。 但是,通过普通的POST或者GET (包含方法名和所有参数)来接受JSON对象并不容易,然后以JSON响应。 我们可以很容易地通过PHP的json_encode()json_decode()来序列化/反序列化,并且可以用这些数据做任何我们想要的,而不必处理不同的HTTP请求方法。

我错过了什么吗?

更新1:

好的 – 在深入研究各种API并学习了很多关于XML-RPCJSON-RPCSOAPREST的知识之后,我得出这样一个结论:这种types的API是正确的。 实际上堆栈交换在他们的网站上使用这种方法非常多,我认为这些人知道他们在做Stack Exchange API 。

RE表示状态传输的概念不是以最简单的方式访问数据。

您build议使用post请求来访问JSON,这是访问/操作数据的完美方法。

REST是一种有意义的数据访问方法。 当您在REST中看到一个请求时,它应该立即显示数据正在发生的事情。

例如:

 GET: /cars/make/chevrolet 

很可能会返回一个chevy车的名单。 一个好的REST api甚至可以在查询string中包含一些输出选项,如?output=json?output=html ,这将允许访问者决定信息应该编码的格式。

在思考如何将数据types合理地合并到REST API中之后,我总结出明确指定数据types的最佳方法是通过已有的文件扩展名,例如.js.json.html.xml 。 缺less文件扩展名将默认为默认格式(如JSON); 不支持的文件扩展名可能会返回501 Not Implemented状态码 。

另一个例子:

 POST: /cars/ { make:chevrolet, model:malibu, colors:[red, green, blue, grey] } 

很可能会创build一个新的雪佛兰malibu与相关的颜色分贝。 我说可能是因为REST api不需要直接关系到数据库结构。 它只是一个屏蔽界面,所以真正的数据被保护起来(想象它像一个数据库结构的访问器和增变器)。

现在我们需要进入幂等性的问题。 通常REST通过HTTP实现CRUD 。 HTTP使用GETPUTPOSTDELETE来处理请求。

一个非常简单的REST实现可以使用下面的CRUD映射:

 Create -> Post Read -> Get Update -> Put Delete -> Delete 

这个实现有一个问题:Post被定义为非幂等方法。 这意味着,相同Post方法的后续调用将导致不同的服务器状态。 Get,Put和Delete是幂等的; 这意味着多次调用它们应该导致相同的服务器状态。

这意味着一个请求,如:

 Delete: /cars/oldest 

实际上可以实现为:

 Post: /cars/oldest?action=delete 

 Delete: /cars/id/123456 

将会导致相同的服务器状态,如果您调用一次,或者如果您调用它1000次。

处理删除oldest物品的更好方法是请求:

 Get: /cars/oldest 

并使用结果数据中的ID作出delete请求:

 Delete: /cars/id/[oldest id] 

这种方法的一个问题是,如果在请求时间/oldest时间和delete时间之间添加了另一个/cars项目。

这是一个安全性和可维护性问题。

安全的方法

只要有可能,您应该使用“安全”(单向)方法,例如GET和HEAD,以限制潜在的漏洞。

幂等方法

只要有可能,就应该使用“幂等”方法,如GET,HEAD,PUT和DELETE,这些方法不会产生副作用,因此不易出错或易于控制。

资源

总之,REST强调名词而不是动词。 随着你的API变得越来越复杂,你添加更多的东西,而不是更多的命令。

你问

通过正常的$ _POST接受JSON对象,然后用JSON响应,会不会更容易

从REST维基百科:

REST风格的应用程序最大限度地利用了预先存在的,定义明确的接口以及所选networking协议提供的其他内置function,并最大限度地减less了在其之上添加新的特定于应用程序的function

从我看到的(很less),我相信这通常是通过最大限度地使用现有的HTTP动词,并为您的服务devise一个尽可能强大和不言而喻的URLscheme。

自定义数据协议(即使它们build立在诸如SOAP或JSON之类的标准协议的基础之上)是不鼓励的,应该最小化以最好地符合REST思想。

另一方面,SOAP RPC over HTTP鼓励每个应用程序devise者定义一个新的,任意的名词和动词词汇表(例如getUsers(),savePurchaseOrder(…)),通常叠加在HTTP'POST'动词上。 这忽略了许多HTTP现有的function,例如authentication,caching和内容types协商,并且可能使应用程序devise者在新的词汇表中重新发明了许多这些function。

您正在使用的实际对象可以是任何格式。 这个想法是尽可能多地重用HTTP来暴露用户想要在这些资源(查询,状态pipe理/变异,删除)上执行的操作。

你问

我错过了什么吗?

还有很多要了解REST和URI语法/ HTTP动词本身。 例如,一些动词是幂等的,其他的则不是。 在你的问题中,我没有看到任何关于这个的事情,所以我懒得试图深入。 其他答案和维基百科都有很多很好的信息。

此外,还有很多要了解基于HTTP构build的各种networking技术,如果您使用的是真正平静的API,则可以利用这些技术。 我会开始authentication。

关于使用扩展来定义数据types。 我注意到MailChimp API正在这样做,但我不认为这是一个好主意。

 GET /zzz/cars.json/1 GET /zzz/cars.xml/1 

我的听起来像一个好主意,但我认为“更老”的方法更好 – 使用HTTP头

 GET /xxx/cars/1 Accept: application/json 

另外,HTTP头对交叉数据types的通信要好得多(如果有人需要的话)

 POST /zzz/cars Content-Type: application/xml <--- indicates we sent XML to server Accept: application/json <--- indicates we want get data back in JSON format 

我错过了什么吗?

是。 😉

这种现象是由于统一的界面约束而存在的。 REST喜欢使用已有的标准,而不是重新发明轮子。 HTTP标准已经被certificate是高度可扩展的(networking正在工作一段时间)。 我们为什么要修理一些没有坏的东西呢?

注意:如果要将客户机与服务分离,则统一接口约束非常重要。 这与为类定义接口类似,以便将它们相互分离。 OFC。 在这里统一的接口由HTTP , MIMEtypes , URI , RDF , 链接的数据词汇 , 九头蛇词汇等标准组成。

好的语义在编程中很重要。

使用除GET / POST之外的更多方法将会很有帮助,因为它会增加代码的可读性并使其更容易维护。

为什么?

因为你知道GET会从你的API检索数据。 你知道POST会添加新的数据到你的系统。 你知道PUT会进行更新。 删除将删除行等等,

我通常构build我的RESTFUL Web服务,以便我有一个函数callback命名与方法相同的事情。

我使用PHP,所以我使用function_exists(我认为它叫)。 如果函数不存在,我抛出405(方法不允许)。