【问题标题】:REST API Best PracticesREST API 最佳实践
【发布时间】:2013-10-23 11:44:18
【问题描述】:

我们正在开发一个 REST API,并且我们允许所有四个标准动词。在 POST/PUT 的情况下,API 客户端将需要修改某些字段的值。以伪例子为例:

class Employee {
  long Id;
  long DepartmentId; // should i expose this?
  string Department; // or should i expose this?
}
  • 这里的用例是客户将发布新员工并填写所有字段。
  • API 后面的数据库中有一个部门表
  • 客户需要获得一份有效部门列表来发送
  • 客户端可以通过 API 调用获取部门列表,如下所示:

{ "department_id": "1", “部门”:“技术” },
{ "department_id": "2", “部门”:“人力资源” }

客户可以包括上述有效部门之一。我的问题是,POST/PUT 请求是否应该包含部门 ID 或名称? id 似乎更容易验证,但对客户来说不太“友好”。无论哪种情况,我们都可以根据我们的参考表正确验证,但我想知道最佳实践是什么。

【问题讨论】:

  • 客户端会不会是某种形式的选择,比如部门的下拉框?我认为应该有一个类Department
  • 我可以开设一个部门课程,但这仍然不能真正解决我的问题。我假设 API 没有前端,并且客户端必须提前请求获取所有参考数据。
  • API 消费者应该向您发送 ID 完整的对象。对他们来说更容易(新对象(),填充道具,发送东西)和你(抓取对象,在验证内容后按原样使用它,不费吹灰之力)。永远,永远使用名称来关联数据。
  • 虽然这通常不是最实用的解决方案,但从纯 RESTful 的角度来看,最佳实践是在应用 HATEAOS 原则的同时使用 URI 作为标识符...

标签: rest


【解决方案1】:

它应该使用 ID。 API 使用者必须能够理解引用。在这种情况下,它需要理解它是指一个特定的部门。为此,客户端可能必须首先查询可用部门的列表,但只要您确实公开了这样的端点,您就不必担心。

使用部门名称会使部门名称成为唯一键,这会严重改变语义。此外,您可能需要为部门名称编制索引以有效地实现这一点,这是使用该名称的另一个严重缺点。

【讨论】:

    【解决方案2】:
    class Employee {
      long Id;
      Department Dept;
    }
    

    class Employee {
          long Id;
          long DepartmentId;
        }
    
        class Department{
          long DepartmentId; 
          string DepartmentName; 
        }
    

    这对于类结构来说更清晰。至于客户,他们将需要一个选择控件来选择部门——您不能指望他们知道 ID 或获得正确的名称。我使用AutoComplete 框来选择大型列表,或使用dropdown 框来选择小列表。

    要回答关于将什么发回from 客户的问题,我会发回ID

    【讨论】:

    • 雇员为什么要包含一个部门?为什么Employee的主键是Id,而部门的主键是DepartmentId
    • 什么是API没有前端?客户需要提前获取部门列表,这很好,只是他们传回去更有意义的问题是什么?
    • @mnemosyn,我没有提出命名约定,这是一个伪示例。 Employee 需要一个对 Department 的引用,要么具有 Department 对象,要么具有 PK、DepartmentId。我只是在说明 Employee 不应该有部门信息。
    • @christiandev: 啊,好吧...取决于人们如何读取“类”...在 json 端点中,可能想要公开去规范化的部门名称
    • @AdamLevitt,既然客户正在获取部门列表,那么您应该将 ID IMO 传回。
    【解决方案3】:

    通常更好的做法是让 URI 传达含义。例如

    www.mylocalpaper.com/news/local/politics/2013_town_budget_approved
    

    优于

    www.mylocalpaper.com/sections/12/subsection/13/article/45
    

    因为第 12 节第 13 小节第 45 条对网络服务器代码之外的任何人都没有任何意义。显然要确保每个部门的 URL 是唯一的(URL 中的 U)。

    您还应该向客户端返回部门的完整 URL,而不仅仅是一个短名称,并使用该 URL 将用户添加到该部门。所以返回

    { "add_employee_url": "/departments/tech/employees/", "name": "Technology" },
    { "add_employee_url": "/departments/hr/employees/", "name": "Human Resources" }
    

    然后,客户端只需将员工详细信息发布到与选择匹配的 URL。客户用户选择“技术”,客户发帖至/departments/tech/employees/

    如果部门的 URL 发生变化(例如,tech 变为 technology),客户端不会在意,因为它正在获取操作的完整 URL。

    【讨论】:

    • 如果Employee对象上有很多这样的字段怎么办?不只是部门...
    • 新员工的信息应该在请求的正文中,例如 JSON 或 XML 或任何格式。将此数据发布到 /departments/tech/employees 基本上是说这里是一个新员工资源,请使用此信息(例如姓名、年龄、薪水等)将此新员工添加到该部门。如果服务器决定最终 URL,您可以这样做,例如它根据数据库中的自动增量编号为用户生成一个新 ID。然后服务器应该将它创建的 URL 返回给客户端,例如 /departments/tech/employees/13434。
    • 如果客户端决定 URL,例如员工资源的 URL 应该是她已知的员工编号,那么客户端可以简单地将数据放入该 URL(例如 PUT /department /tech/employees/AB3423)。服务器应该识别出这个员工实际上还没有在系统中,并根据数据创建一个新的数据库记录,但是这个创建应该对客户端隐藏。如果客户确定了最终 URL,您就可以这样做。
    猜你喜欢
    • 2020-05-29
    • 1970-01-01
    • 2018-04-27
    • 2018-05-25
    • 2020-04-23
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    相关资源
    最近更新 更多