RESTful API 设计的最佳实践示范
当前位置:以往代写 > 网页教程 >RESTful API 设计的最佳实践示范
2019-06-14

RESTful API 设计的最佳实践示范

RESTful API 设计的最佳实践示范

  目前互联网上充斥着大量的关于RESTfulAPI(为了方便,以后API和RESTfulAPI一个意思)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API格式如何?你的API是否应该加入版本信息?当你开始写一个app的时候,特别是后端模型部分已经写完的时候,你不得不殚精竭虑的设计和实现自己app的publicAPI部分。因为一旦发布,对外发布的API将会很难改变。

  即使如此,Facebook、谷歌、Github、Netflix和几个其他的科技巨头已经允许开发者和其产品通过API调用他们的数据,并为他们提供平台。即使你不是写API的专业人士,拥有精美的API也对你的应用程序有好处。

  关于设计API的最好方法,网络上有较长一段时间的争论,但官方也没有对此给出解释。

  API是一个接口,通过它许多开发者可与数据交互。设计优良的API使用起来很方便,并给开发者的工作带来便利。API是开发者的GUI,如果它设计不合理,开发者会将它替换。所以,开发者的经验是衡量API质量的最重要的指标。

RESTful API 设计最佳实践_web开发_RESTful API _API_课课家教育

  一、术语

  以下是与RESTAPI相关的重要术语:

  资源(Resource)是一个对象或对某物的表示。它有一些相关联的数据,并有一组方法进行操作。例如:动物,学校和员工是资源。这些资源都有着删除,添加,更新操作。

  集合(Collection)是一系列资源,例如:公司集合是很多公司的集合。

  URL(统一资源定位符)是一种路径,可以通过它定位资源并且也可以对它执行一些动作。

  二、API设计的基本要求

  1.当标准合理的时候遵守标准。

  2.API应该对程序员友好,并且在浏览器地址栏容易输入。

  3.API应该简单,直观,容易使用的同时优雅。

  4.API应该具有足够的灵活性来支持上层ui。

  5.API设计权衡上述几个原则。

  三、使用RESTfulURLs和action.

  虽然前面我说没有一个万能的API设计标准。但确实有一个被普遍承认和遵守:RESTfu设计原则。它被RoyFelding提出(在他的”基于网络的软件架构“论文中第五章)。而REST的核心原则是将你的API拆分为逻辑上的资源。这些资源通过http被操作(GET,POST,PUT,DELETE)。

  四、那么我应该如何拆分出这些资源呢?

  显然从API用户的角度来看,”资源“应该是个名词。即使你的内部数据模型和资源已经有了很好的对应,API设计的时候你仍然不需要把它们一对一的都暴露出来。这里的关键是隐藏内部资源,暴露必需的外部资源。

  在SupportFu里,资源是ticket、user、group。

  一旦定义好了要暴露的资源,你可以定义资源上允许的操作,以及这些操作和你的API的对应关系:

  1.GET/tickets#获取ticket列表

  2.GET/tickets/12#查看某个具体的ticket

  3.POST/tickets#新建一个ticket

  4.PUT/tickets/12#更新ticket12.

  5.DELETE/tickets/12#删除ticekt12

  可以看出使用REST的好处在于可以充分利用http的强大实现对资源的CURD功能。而这里你只需要一个endpoint:/tickets,再没有其他什么命名规则和url规则了,cool!

  五、API端点(路径)

  为了更好理解,我们给公司写API,这些公司都有一些员工。/getAllEmployees是对员工列表进行回应的API。公司其他API大致如下:

  /addNewEmployee

  /updateEmployee

  /deleteEmployee

  /deleteAllEmployees

  /promoteEmployee

  /promoteAllEmployees

  并且将有大量的和这些操作不同的API端点,它们包含大量冗余的行为。因此,当API数量增加时,这些API端点将很难维护。

  哪里不对?

  每个URL代表一种资源(Resource),所以URL中只能有名词,不能有动词。API路径/addNewEmployee包含了操作addNew和资源名称Employee。

  那么怎样算是正确的方式?

  /companies是一个很好的不包含操作的例子。但是问题来了,我们该怎样告诉服务器我们要进行的操作呢?新增,删除,还是更新?

  这时HTTP方法(GET,POST,DELETE,PUT)(也称为动词)就可以起到作用了。

  资源在API端点中应该总是复数,如果我们想访问资源的一个实例,我们可以传递URL中的id。

  方法GET路径/companies是获取所有公司的列表。

  方法GET路径/companies/34是获取公司34的详细信息。

  方法DELETE路径/companies/34是删除公司34.

#p#分页标题#e#

  在其他的一些使用案例中,如果我们有一些资源在某个资源之下,例如,一个公司的员工,那么在这样的例子中API的endpoint(端点)就应该是这样的:

  GET/companies/3/employees可以取得编号为3的公司的员工列表

  GET/companies/3/employees/45可以取得编号为3的公司的45号员工的细节信息

  DELETE/companies/3/employees/45可以删除编号为3的公司的45号员工

  POST/companies可以创建一个新公司并返回新创建公司的细节信息

  现在这样,API是不是更严谨和一致了呢?

  结论:路径应该包含资源的复数形式,HTTP方法应该定义成各种行为在资源上执行。

  六、HTTP方法(动词)

  HTTP定义了几组方法,这些方法给出了对资源要执行的操作类型。

  URL是一个句子,其中资源是名词,HTTP方法是动词。

  主要的HTTP方法如下:

  GET方法从资源请求数据,不产生多余结果。

  例如:/companies/3/employees会返回公司3的所有雇员列表。

  POST方法请求服务器在数据库中创建资源,这主要用于提交Web表单时。

  例如:/companies/3/employees创建一个公司3的新雇员。

  POST是非幂等的,这意味着多个请求将会有不同的效果。

  PUT方法请求服务器更新资源或创建资源(如果不存在的话)。

  例如:/companies/3/employees/john将请求服务器在公司3的雇员集合中更新或在不存在的情况下创建关于john的资源。

  PUT是幂等的,这意味着多次请求具有相同的效果。

  DELETE方法将请求的资源或实例从数据库中删除。

  例如:/companies/3/employees/john/将请求服务器从公司3的雇员集中删除john资源。

  HTTP中还有很多其他方法,我们将在另一篇文章中讨论。

  七、HTTP响应状态码

  当客户端通过API向服务器发起请求时,无论请求是失败的、通过的还是错误的,客户端应该获得反馈。HTTP状态码是一堆标准化的数值码,在不同的情况下具有不同的解释。服务器应始终返回正确的状态码。

  以下是HTTP状态码的主要分类:

  2xx(成功类别)

  这些状态代码表示请求的操作已被服务器接收到并成功处理。

  200Ok:标准的HTTP响应,表示GET、PUT或POST的处理成功。

  201Created:在创建新实例时,应返回此状态代码。例如,使用POST方法创建一个新的实例,应该始终返回201状态码。

  204内容不存在:表示请求已被成功处理,但并未返回任何内容。

  DELETE算是其中一个很好的例子。

  APIDELETE/companies/43/employees/2将删除员工2,作为响应,我们不需要在该API的响应正文中的任何数据,因为我们明确地要求系统将其删除。如果有任何错误发生,例如,如果员工2在数据库中不存在,那么响应码将不是2xx对应的成功类别,而是4xx客户端错误类别。

  3xx(重定向类别)

  304未修改:表示客户端的响应已经在其缓存中。因此,不需要再次传送相同的数据。

  4xx(客户端错误类别)

  这些状态代码表示客户端发起了错误的请求。

  400错误请求:表示客户端的请求没有被处理,因为服务器不能理解客户端请求的是什么。

  401未授权:表示客户端不被允许访问该资源,需要使用指定凭证重新请求。

  403禁止访问:表示请求是有效的并且客户端已通过身份验证,但客户端不被允许以任何理由访问对应页面或资源。例如有时授权的客户端不被允许访问服务器上的目录。

  404未找到:表示所请求的资源现在不可用。

  410资源不可用:表示所请求的资源后续不再可用,该资源已被移动。

  5xx(服务器错误类别)

  500是服务器内部错误,表示请求已经被接收到了,但服务器被要求处理某些未预设的请求而完全混乱。

  503服务不可用表示服务器已关闭或无法接收和处理请求。大多数情况是服务器正在进行维护。

  八、字段套管约定

  您可以遵循任何套管约定,但要确保其在应用程序中一致。如果请求主体或响应类型是JSON,那么请按照camelCase(驼峰命名法)来保持一致。

  九、搜索、排序、过滤和分页

  这些行为都只是针对一个数据集进行的查询。由于还没有一套新的API来处理这些行为。因此,我们需要向GET方法的API附加查询参数。

  我们来理解几个例子看它们是如何实现这些行为的。

  排序(sorting),客户端想要获得排序后的公司列表,GET/companies端点应当接受多个查询排序参数。

  例如,GET/companies?sort=rank_asc将根据等级以升序的方式对公司进行排序。

  过滤(Filtering),用来过滤数据集,我们可以通过查询参数传递不同的选项。

  例如,GET/companies?category=banking&location=india将根据公司类别为银行以及所处位置为印度来过滤公司的列表数据。

  搜索(Searching),当需要在公司列表中搜索公司名称时,API端点应当是GET/companies?search=DigitalMckinsey。

#p#分页标题#e#

  分页(Pagination),当数据集太大时,我们将数据集分成更小的块,这样有助于提高性能,并且更易于处理响应。例如,GET/companies?page=23表示获取第23页的公司列表。

  如果在GET方法中附加了很多查询参数,会造成URI太长,服务器可能会响应414的HTTP状态,表示这个URI太长,在这种情况下,我们也可以将参数传递给POST方法的请求体中。

  十、限制API返回值的域

  有时候API使用者不需要所有的结果,在进行横向限制的时候(例如值返回API结果的前十项)还应该可以进行纵向限制。并且这个功能能有效的提高网络带宽使用率和速度。可以使用fields查询参数来限制返回的域例如:

  GET/ticketsfields=id,subject,customer_name,updated_at&state=open&sort=-updated_at

  十一、更新和创建操作应该返回资源

  PUT、POST、PATCH操作在对资源进行操作的时候常常有一些副作用:例如created_at,updated_at时间戳。为了防止用户多次的API调用(为了进行此次的更新操作),我们应该会返回更新的资源(updatedrepresentation.)例如:在POST操作以后,返回201created状态码,并且包含一个指向新资源的url作为返回头

  十二、是否需要“HATEOAS“

  网上关于是否允许用户创建新的url有很大的异议(注意不是创建资源产生的url)。为此REST制定了HATEOAS来描述了和endpoint进行交互的时候,行为应该在资源的metadata返回值里面进行定义。

  十三、只提供json作为返回格式

  现在开始比较一下XML和json了。XML即冗长,难以阅读,又不适合各种编程语言解析。当然XML有扩展性的优势,但是如果你只是将它来对内部资源串行化,那么他的扩展优势也发挥不出来。很多应用(youtube,twitter,box)都已经开始抛弃XML了,我也不想多费口舌。给了google上的趋势图吧:

现在开始比较一下XML和json了。XML即冗长,难以阅读,又不适合各种编程语言解析。当然XML有扩展性的优势,但是如果你只是将它来对内部资源串行化,那么他的扩展优势也发挥不出来。很多应用(youtube,twitter,box)都已经开始抛弃XML了,我也不想多费口舌。给了google上的趋势图吧:

  当然如果的你使用用户里面企业用户居多,那么可能需要支持XML。如果是这样的话你还有另外一个问题:你的http请求中的media类型是应该和accept头同步还是和url?为了方便(browserexplorability),应该是在url中(用户只要自己拼url就好了)。如果这样的话最好的方法是使用.xml或者.json的后缀。

  十四、版本控制

  当你的API被开始被广泛使用后,突然升级API会打破现有的产品、服务。

  如果有任何重大的中断更新,我们可以将新的API集命名为v2或v1.x.x

  小编结语:

  更多内容尽在课课家教育!

    关键字:

在线提交作业