【问题标题】:Proper route for checking resource existence in a RESTful API [closed]在 RESTful API 中检查资源存在的正确途径 [关闭]
【发布时间】:2014-01-31 23:59:24
【问题描述】:

设计用于检查资源是否存在的 API 端点的最佳/轻松方式是什么?

例如有一个用户数据库。当新用户尝试注册时,我想检查电子邮件是否已被即时使用。

我的想法是:POST /user/exists 和有效载荷类似于{"email": "foo@bar.com"}。响应将是 200 OK 或 409 Conflict。

这是正确的方法吗?

谢谢!

【问题讨论】:

  • 您可以这样做,但 Tragedian 的解决方案更好,因为 a) 您不必构造主体,b) 响应是可缓存的,c) 它通过使用准确地将请求描述为安全的一个 GET。

标签: api rest restful-url


【解决方案1】:

HEAD 是最有效的存在检查:

HEAD /users/{username}

请求用户的路径,如果存在则返回200,如果不存在则返回404

请注意,您可能不想公开检查电子邮件地址的端点。它打开了一个安全和隐私漏洞。已经在网站周围公开显示的用户名(例如在 reddit 上)可能没问题。

【讨论】:

  • 我认为这只有在用户名是用户的“主键”时才有效。最常见的是一个 API 有一个GET /users/{id},但是这个资源会与HEAD /users/{username} 冲突,因为理论上 HEAD 方法要求的响应与 GET 请求的响应相同。
  • 请注意,如果此类请求来自 Web 浏览器(例如 AJAX 调用),JS 控制台将被 404 错误污染。虽然非技术用户不会看到它们,而且 Google 表示此类错误不会影响 SEO (support.google.com/webmasters/answer/35120),但这仍然不太理想.. :(
  • 考虑到正常的 READ 是作为/user/id 完成的。手头的任务是检查“foo@bar.com”帐户是否存在。我的回答是,这取决于: 1. 如果 id 是电子邮件;作为/user/jdoe@gmail.com,那么@Baz 提供的解决方案是有意义的HEAD /users/{username}。 (HTTP docs) 2. 当 id 是账户 ID(整数)时;如/user/456734 那么@x1a0 POST /user/exists 提供的解决方案是有意义的。我只是将其更改为 GET /user/exists?email=foo@bar.com 的“GET”,因为您正在阅读(要求回答是/否),您并没有尝试“创建”任何资源。
  • head 方法很简单,但无法返回有意义的错误消息,向客户端提供有关出错的附加信息(有时 4xx 5xx 错误代码是不够的)
【解决方案2】:

我认为检查存在的正确方法是使用HEAD 动词来表示您通常通过GET 请求获得的任何资源。

我最近遇到了一种情况,我想检查服务器上是否存在一个可能很大的视频文件。我不希望服务器尝试开始将字节流式传输到任何客户端,因此我实现了一个 HEAD 响应,该响应仅返回客户端在对该视频执行 GET 请求时将收到的标头。

您可以查看 W3 规范 here 或阅读 this blog post 了解 HEAD 动词的实际用途。

我认为这很棒,因为您不必考虑如何形成与普通 RESTful 路由不同的路由来检查是否存在任何资源,无论是文件还是典型资源,例如用户或其他东西。

【讨论】:

    【解决方案3】:
    GET /users?email=foo@bar.com
    

    这是一个基本的搜索查询:找到指定了电子邮件地址的用户。如果不存在用户则以空集合响应,或以符合条件的用户响应。

    【讨论】:

    • 您可以返回 204 且没有正文或 404 表示未找到任何正文。这样可以避免在否定情况下解析正文。
    • 我反对在这里使用 404:用户资源确实存在并且可以接受地处理请求。 204 更接近事实,但我个人会发现空集合更容易解析。
    • 当然/Users 存在,但这不是我想要获取的资源。我正在尝试 GET /users?email=foo@bar.com 并且该资源不存在。查询参数与路径参数一样是资源识别的一部分。
    • Tragedian/Darrel ,我想说你们俩都可能是对的;这取决于 OP 是否将“/users?email=foo@bar.com”中资源的媒体类型定义为表示“电子邮件地址为 foo@bar.com 的用户”或“电子邮件地址为 foo 的用户的集合” @bar.com”。如果是前者,那么 404 是合适的,如果是后者,那么 204。
    • 这不是一个很好的解决方案,因为数据应该随请求返回,只是一个简单的布尔值。
    【解决方案4】:

    我更喜欢:

    HEAD /users/email/foo@bar.com
    

    解释:您正试图通过所有用户查找使用电子邮件foo@bar.com 的人。我在这里假设电子邮件不是您的资源的关键并且您具有一定的灵活性,因为如果您需要另一个端点来检查来自用户的其他信息的可用性,这种方法可以非常合身。

    作为响应,您只返回 200(如果不可用)或 404(如果可用)作为 http 代码响应。

    你也可以使用:

    HEAD /emails/foo@bar.com

    如果 HEAD /users/email/foo@bar.com 与现有的休息资源冲突,例如 GET /users/email/foo@bar.com 与不同的业务规则。如Mozilla's documentation 所述:

    HEAD 方法要求的响应与 GET 请求相同,但没有响应正文。*。

    所以,拥有不同规则的GETHEAD 是不好的。

    如果电子邮件是users 的“关键”,HEAD /users/foo@bar.com 也是一个不错的选择,因为您(可能)有一个GET /users/foo@bar.com

    【讨论】:

    • 我相信您的意思是“200(如果可用)或 404(如果不可用)”
    • 嗨!当找到带有一些电子邮件的用户时返回 200。所以,如果有用户拥有该邮箱,则该邮箱是不可用的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    • 2013-05-07
    • 2019-11-04
    相关资源
    最近更新 更多