我正在寻找一种在基于PHP的Web应用程序,数据库和CMS中围绕默认函数包装API的方法。
我环顾四周,发现了几个“骨架”框架。除了我的问题中的答案,还有Tonic,我喜欢的REST框架,因为它非常轻量级。
我最喜欢REST的简单性,并希望基于它创建一个API架构。我试图了解基本原则并且还没有完全理解它。因此,一些问题。
1。我理解得对吗?
说我有一个资源“用户”。我可以设置一些像这样的URI:
/api/users when called with GET, lists users
/api/users when called with POST, creates user record
/api/users/1 when called with GET, shows user record
when called with PUT, updates user record
when called with DELETE, deletes user record
到目前为止,它是RESTful架构的正确表示吗?
2。我需要更多动词
理论上创建,更新和删除可能就足够了,但在实践中我需要更多的动词。我意识到这些是可以嵌入到更新请求中的东西,但它们是具有特定返回代码的特定操作,我不想将它们全部放入一个操作中。
用户示例中的一些想法是:
activate_login
deactivate_login
change_password
add_credit
我如何表达RESTful URL架构中的操作?
我的直觉是对像
这样的网址进行GET调用/api/users/1/activate_login
并期待返回状态代码。
但是,这偏离了使用HTTP动词的想法。你觉得怎么样?
第3。如何返回错误消息和代码
REST的美丽很大一部分源于其使用标准HTTP方法。如果出错,我会发出一个包含3xx,4xx或5xx错误状态代码的标头。对于详细的错误描述,我可以使用正文(对吗?)。到现在为止还挺好。但是传输专有错误代码的方法是什么呢?在描述错误时更详细(例如“无法连接数据库”或“数据库登录错误”)?如果我把它和信息一起放入体内,我必须在事后解析它。这种事情有标准的标题吗?
4。如何进行身份验证
答案 0 :(得分:604)
答案 1 :(得分:77)
答案 2 :(得分:30)
re 1 :到目前为止看起来很好。请记住在“Location:”标题中返回新创建的用户的URI,作为POST响应的一部分,以及“201 Created”状态代码。
re 2 :通过GET激活是一个坏主意,包括URI中的动词是一种设计气味。您可能需要考虑在GET上返回表单。在Web应用程序中,这将是一个带有提交按钮的HTML表单;在API用例中,您可能希望返回包含PUT的URI的表示以激活帐户。当然,您也可以在对/ users的POST响应中包含此URI。使用PUT将确保您的请求是幂等的,即如果客户端不确定成功,它可以安全地再次发送。一般来说,想想你可以将动词转化为什么资源(类似于“动词的名词化”)。问问自己,您的具体行动与哪种方法最为一致。例如。 change_password - >放;停用 - >可能是DELETE; add_credit - >可能是POST或PUT。通过将客户端包含在您的表示中,将客户端指向适当的URI。
re 3。不要发明新的状态代码,除非您认为它们非常通用,因此值得在全球范围内进行标准化。尽量使用最合适的状态代码(在RFC 2616中阅读所有这些代码)。在响应正文中包含其他信息。如果您确实想确定要创建新的状态代码,请再想一想;如果您仍然相信,请确保至少选择正确的类别(1xx - > OK,2xx - > informational,3xx - >重定向; 4xx->客户端错误,5xx - >服务器错误)。我是否提到发明新的状态代码是一个坏主意?
重新4。如果有可能,请使用HTTP内置的身份验证框架。查看Google在GData中进行身份验证的方式。通常,不要在您的URI中放置API密钥。尽量避免会话以增强可伸缩性并支持缓存 - 如果对请求的响应因之前发生的事情而有所不同,那么您通常会将自己绑定到特定的服务器流程实例。最好将会话状态转换为客户端状态(例如,使其成为后续请求的一部分),或者通过将其转换为(服务器)资源状态使其明确,即为其提供自己的URI。
答案 3 :(得分:22)
1。你对如何设计资源有了正确的想法,恕我直言。我不会改变一件事。
2。不要尝试使用更多动词扩展HTTP,而应考虑基本HTTP方法和资源可以减少建议的动词。例如,您可以设置资源,而不是activate_login
动词,/api/users/1/login/active
这是一个简单的布尔值。要激活登录,只需PUT
一个说“真”或1或其他的文档。要停用,PUT
那里的文档为空或表示0或错误。
同样,要更改或设置密码,只需PUT
到/api/users/1/password
即可。
每当你需要添加某些内容(如信用卡)时,请考虑POST
s。例如,您可以POST
对/api/users/1/credits
这样的资源执行PUT
,其中包含要添加的信用数量的正文。可以使用同一资源上的POST
覆盖值而不是添加。正文中带有负数的404 Not Found
会减去,依此类推。
3。我强烈建议不要扩展基本的HTTP状态代码。如果找不到与您的情况完全匹配的那个,请选择最接近的一个并将错误详细信息放在响应正文中。另外,请记住HTTP标头是可扩展的;您的应用程序可以定义您喜欢的所有自定义标头。例如,我工作的一个应用程序可能会在多种情况下返回X-Status-Extended
。我们只是添加了一个新的标头HTTP/1.1 404 Not Found
X-Status-Extended: 404.3 More Specific Error Here
,而不是让客户端解析响应主体,它包含我们的专有状态代码扩展。所以你可能会看到像:
X-Status-Extended
这样,像Web浏览器这样的HTTP客户端仍然知道如何处理常规404代码,而更复杂的HTTP客户端可以选择查看{{1}}标头以获取更具体的信息。
4. 。对于身份验证,我建议您使用HTTP身份验证。但恕我直言,使用基于cookie的身份验证没有任何问题,如果这对你来说更容易。
答案 4 :(得分:12)
REST具有统一的接口约束,该约束声明REST客户端必须依赖于标准而不是实际REST服务的应用程序特定细节,因此REST客户端不会因轻微更改而中断,并且可能是可重用的。
因此REST客户端和REST服务之间存在合同。如果您使用HTTP作为基础协议,则以下标准是合同的一部分:
REST具有无状态约束,该约束声明REST服务和客户端之间的通信必须是无状态的。这意味着REST服务无法维护客户端状态,因此您无法拥有服务器端会话存储。您必须验证每个请求。因此,例如HTTP基本身份验证(HTTP标准的一部分)是可以的,因为它会在每次请求时发送用户名和密码。
是的,可以。
请注意,客户端不关心IRI结构,他们关心语义,因为它们遵循具有链接关系或链接数据(RDF)属性的链接。
唯一重要的是IRI,单个IRI必须只识别一个资源。允许单个资源(如用户)拥有许多不同的IRI。
为什么我们使用像/users/123/password
这样的好的IRI,这很简单;只需阅读IRI就可以更容易地在服务器上编写路由逻辑。
你有更多动词,比如PUT,PATCH,OPTIONS等等,但你不需要更多动词......你必须学习如何添加新资源,而不是添加新动词。 / p>
activate_login -> PUT /login/active true
deactivate_login -> PUT /login/active false
change_password -> PUT /user/xy/password "newpass"
add_credit -> POST /credit/raise {details: {}}
(由于无状态约束,从REST角度来看登录没有意义。)
您的用户不关心问题存在的原因。他们只想知道成功或错误,以及他们可以理解的错误信息,例如:“抱歉,但我们无法保存您的帖子。”等等......
HTTP状态标头是您的标准标头。我认为其他一切都应该在身体里。单个标头不足以描述详细的多语言错误消息。
无状态约束(以及缓存和分层系统约束)确保服务可以很好地扩展。当你可以在客户端上做同样的事情时,你肯定不会在服务器上维护数百万个会话......
如果用户使用主客户端授予访问权限,则第三方客户端会获取访问令牌。之后,第三方客户端会向每个请求发送访问令牌。有更复杂的解决方案,例如您可以对每个请求进行签名等。有关详细信息,请查看OAuth手册。
答案 5 :(得分:11)
对于您所说的示例,我将使用以下内容:
activate_login
POST /users/1/activation
deactivate_login
DELETE /users/1/activation
change_password
PUT /passwords
(假设用户已通过身份验证)
add_credit
POST /credits
(假设用户已通过身份验证)
对于错误,您将以您收到请求的格式在正文中返回错误,因此如果您收到:
DELETE /users/1.xml
您将以XML格式发回响应,JSON等也是如此......
对于身份验证,您应该使用http身份验证。
答案 6 :(得分:6)
答案 7 :(得分:5)
我建议(作为第一遍)PUT
只应用于更新现有实体。 POST
应该用于创建新的。即。
/api/users when called with PUT, creates user record
对我来说感觉不对。然而,第一部分的其余部分(重新使用动词)看似合乎逻辑。
答案 8 :(得分:5)
答案 9 :(得分:2)
关于REST返回码:混合HTTP协议代码和REST结果错误。
然而,我看到许多实现混合它们,许多开发人员可能不同意我的看法。
HTTP返回代码与HTTP Request
本身相关。 REST调用是使用超文本传输协议请求完成的,它的工作级别低于调用的REST方法本身。 REST是一种概念/方法,其输出是业务/逻辑结果,而HTTP结果代码是传输结果。
例如,当您调用/ users /时返回“404 Not found”会让您感到困惑,因为它可能意味着:
“403 Forbidden / Access Denied”可能意味着:
该列表可能会继续出现“500 Server error”(Apache / Nginx HTTP抛出错误或REST中的业务约束错误)或其他HTTP错误等...
从代码中,很难理解失败原因是什么,HTTP(传输)失败或REST(逻辑)失败。
如果HTTP请求在物理上成功执行,则总是返回200代码,无论是否找到记录。因为URI资源是找到并且由http服务器处理。是的,它可能会返回一个空集。是否有可能收到一个空的网页,其中200为http结果,对吧?
除此之外,您可以返回200个HTTP代码,只返回带有空数组/对象的JSON,或者使用bool结果/成功标志来通知执行的操作状态。
此外,一些互联网服务提供商可能会拦截您的请求并返回404 http代码。这并不意味着您的数据未找到,但在传输级别出现问题。
来自Wiki:
2004年7月,英国电信提供商BT集团部署了Cleanfeed 内容阻止系统,它向任何请求返回404错误 互联网观察认定为可能违法的内容 基础。其他ISP返回HTTP 403“禁止”错误 情况。用假404错误作为手段的做法 泰国和突尼斯也报道了隐瞒审查制度。在 突尼斯,2011年革命前审查严重, 人们开始意识到假404错误的本质和创造 一个名为“Ammar 404”的想象中的角色,代表着“无形的人” 检查员”。