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-RPC , JSON-RPC , SOAP , REST的知识之后,我得出这样一个结论:这种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使用GET
, PUT
, POST
和DELETE
来处理请求。
一个非常简单的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(方法不允许)。