了解REST:动词,错误代码和身份验证

时间:2010-01-04 19:55:37

标签: web-services rest

我正在寻找一种在基于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。如何进行身份验证

  • 遵循REST原则的基于API密钥的身份验证是什么样的?
  • 在验证REST客户端时,是否有强烈的反对使用会话的优点,除了它是公然违反REST原则? :)(这里只有半开玩笑,基于会话的身份验证可以很好地与我现有的基础设施配合使用。)

10 个答案:

答案 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客户端和REST服务之间存在合同。如果您使用HTTP作为基础协议,则以下标准是合同的一部分:

  • HTTP 1.1
    • 方法定义
    • 状态代码定义
    • 缓存控制标头
    • 接受和内容类型标题
    • auth headers
  • IRI(utf8 URI
  • 身体(挑一个)
    • 注册的应用程序特定MIME类型,例如maze+xml
    • 供应商特定的MIME类型,例如vnd.github+json
    • 通用MIME类型
      • 应用程序特定的RDF词汇,例如ld+json& hydraschema.org
      • 应用程序特定配置文件,例如hal+json&个人资料链接参数(我猜)
  • 超链接
    • 应该包含什么(选一个)
      • 发送link headers
      • 发送超媒体响应,例如html,atom + xml,hal + json,ld + json& hydra等......
    • 语义
      • 使用IANA链接关系以及可能的自定义链接关系
      • 使用特定于应用程序的RDF词汇

REST具有无状态约束,该约束声明REST服务和客户端之间的通信必须是无状态的。这意味着REST服务无法维护客户端状态,因此您无法拥有服务器端会话存储。您必须验证每个请求。因此,例如HTTP基本身份验证(HTTP标准的一部分)是可以的,因为它会在每次请求时发送用户名和密码。

回答你的问题

  1. 是的,可以。

    请注意,客户端不关心IRI结构,他们关心语义,因为它们遵循具有链接关系或链接数据(RDF)属性的链接。

    唯一重要的是IRI,单个IRI必须只识别一个资源。允许单个资源(如用户)拥有许多不同的IRI。

    为什么我们使用像/users/123/password这样的好的IRI,这很简单;只需阅读IRI就可以更容易地在服务器上编写路由逻辑。

  2. 你有更多动词,比如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角度来看登录没有意义。)

  3. 您的用户不关心问题存在的原因。他们只想知道成功或错误,以及他们可以理解的错误信息,例如:“抱歉,但我们无法保存您的帖子。”等等......

    HTTP状态标头是您的标准标头。我认为其他一切都应该在身体里。单个标头不足以描述详细的多语言错误消息。

  4. 无状态约束(以及缓存和分层系统约束)确保服务可以很好地扩展。当你可以在客户端上做同样的事情时,你肯定不会在服务器上维护数百万个会话......

    如果用户使用主客户端授予访问权限,则第三方客户端会获取访问令牌。之后,第三方客户端会向每个请求发送访问令牌。有更复杂的解决方案,例如您可以对每个请求进行签名等。有关详细信息,请查看OAuth手册。

  5. 相关文献

答案 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)

  1. 当你不知道新资源URI的样子时使用post(你创建新用户,应用程序会为新用户分配它的id),PUT用于更新或创建你知道它们将如何成为的资源代表(例如:PUT /myfiles/thisismynewfile.txt)
  2. 返回邮件正文中的错误说明
  3. 您可以使用HTTP身份验证(如果足够的话) Web服务应该是stateles

答案 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”会让您感到困惑,因为它可能意味着:

  • URI错误(HTTP)
  • 找不到用户(REST)

“403 Forbidden / Access Denied”可能意味着:

  • 需要特别许可。浏览器可以通过询问用户/密码来处理它。 (HTTP)
  • 服务器上配置的访问权限错误。 (HTTP)
  • 您需要通过身份验证(REST)

该列表可能会继续出现“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”的想象中的角色,代表着“无形的人”   检查员”。