rest api_REST API最佳实践?

rest api

在过去的一年半中,我参与了2-3个项目,这些项目公开了大量的Rest API供“外部”使用。 我稍后会再解释为什么“ 外部 ”一词是内在引号。 在此期间,我们有时不得不设计,重新设计和重新构造这些API。 这篇博客文章表达了我对一些最佳实践的个人想法,这些最佳实践将在处理Rest API时为您提供帮助。

精心设计,尽早设计

对于许多语言而言,实现Rest服务都是一项非常琐碎的任务。 这意味着,无论您选择哪种基础框架,只需进行最少的配置和几行代码,即可在不到一个小时的时间内拥有运行中的Rest服务。 尽管这确实很方便,尤其是对于没有经验的人,但它可以很快将您带到低质量的API设计。 因此,在开始编写代码之前,请退后一分钟(或更多)并进行思考。 尝试设计您的API。 花足够的时间来了解业务领域,并弄清系统中需要哪些API客户端。 例如,如果您的系统是硬币收集者的数据库,请决定是否要允许客户添加新硬币或仅获取现有数据。 需要什么样的查询? 您将如何处理将检索大量数据的请求? 尽早回答这个问题将帮助您开发更现实的API。

名称和方法

关于资源命名及其应如何组织的讨论很多。 再次根据我的经验,我建议三个易于遵循的规则。

  1. 仅使用名词。 例如,如果您要提供用于搜索硬币数据库的服务,请避免这样命名端点:/ searchCoins或/ findCoins或/ getAllCoins等。简单的/ coins资源就足够了,因此当客户端发送GET请求时,他们会期望该资源获取所有可用硬币的列表。 同样,如果要将新硬币添加到数据库中,请避免使用诸如/ addCoin或/ saveCoin或/ insertCointToDatabase之类的名称。 您可以仅使用已有的资源来获取硬币,而不是GET请求,只需发送POST请求或PUT请求以更新硬币。
  2. 拿一枚硬币怎么样? 建议的最佳实践是使用提供资源参数的端点,例如,如果客户想要获取ID为20的硬币,那么对/ coins / 20的GET请求就足够了。 让我们来看另一个更复杂的情况。 假设您要允许客户为每个硬币添加图像。 一个快速但肮脏的解决方案是:/ addCoinImage或/ addNewImageToCoin等。稍微好一点的方法看起来像/ coins / addImage,但是就像我说的,只是丢掉所有动词。 因此,我们可以利用提供的资源来获取特定硬币的数据,并允许客户端通过向该端点发送POST请求来添加图像:/ coins / 20 / images。 到目前为止,一切都很好。 但是每一朵玫瑰都有刺。 假设我们要允许某些超级用户从系统中删除硬币。 根据我们到目前为止所讨论的内容,对/ coins / {id}资源进行简单的DELETE调用就足够了。 但是,您能想象如果{id}只是表“ COINS”的序列号时,这种方法会有多大的问题? 有人可以通过每次增加ID号来开始向该资源发送DELETE请求,从而导致我们的系统最终丢失所有数据。 我的观点是,使用标识符作为资源参数是可以的,只要这些标识符是不可能的或很难被猜到的。 因此,如果您使用序列号标识实体,则只需忘记此实现即可。 我建议的是,不要将硬币标识符作为资源参数传递,而是将DELETE请求发送到/ coins资源,并在请求正文(例如json文档)中包含足够的参数,以唯一地标识您想要的实体对象删除。
  3. 尽可能使用特定于域名的名称。 如果您的域具有硬币收集器实体,则在设计API时仅使用单词收集器而不是用户帐户即可 。 尽量避免太笼统的名称,这些名称对客户没有任何意义或有争议。 查询参数也遵循相同的原则。 强烈建议将查询参数的名称保持尽可能短,但仍然有意义。 例如,如果您要查询特定年份发行的硬币,查询参数的一个很好的选择可能是: issueYear其中以下名称太大或可能使客户感到困惑: year (不清楚), yearOfFirstIssue(无用的多余信息)

错误处理和响应

当处理错误和响应时,我的经验表明,无论结果是否成功,客户端每次发送请求时都期望相同的json响应结构容易得多。 例如,假设您要添加一个新硬币,向资源/ coins发送POST请求。 成功的响应可能包含以下json文档:

{
     "meta":{
      "code":200
   },
   "data":{
      "coinId":"a7sad-123kk-223"
   }
}

和类似这样的错误响应:

{
     "meta":{
      "code":60001,
      "error":"Can not add coin",
      "info":"Missing one ore more required fields"
   },
   "data":{
   }
}

注意,对于两种可能的结果(错误,成功),json响应文档都具有相同的基本结构。 有两个基本元素:元和数据。 前者包含有关结果的信息,如果有错误,则包括特定的错误代码,描述错误原因的消息(“错误”)以及故障根本原因的更详细说明(“原因”)。 后者(可选)包含从服务返回的任何数据。 例如,在上面的示例中,当成功添加新硬币时,服务将返回该硬币的唯一自动生成的标识符。 如果发生错误,通常此元素应为空。 这种方法的好处是,客户总是希望同一API的所有服务都能获得标准的回报。 此外,当某些事情未成功完成时,我们可以传递其他信息。 客户端可以使用(至少) 错误属性将其作为消息显示给最终用户,并使用信息属性进行记录。 或者,只要他们知道每个数字的含义,他们就可以根据错误代码处理响应。 请记住,这些错误代码不是http状态。 您仍应在每次请求时返回正确的http状态(即400、401等)

在讨论文档子主题之前,我想指出您需要记住的另一件重要事情。 假设我们不允许删除硬币硬币,但是客户端尝试在/ coins / {id}资源处发送DELETE请求。 通常,它将从Web容器返回405 http错误。 我发现过滤所有这些响应并再次返回相同的json文档非常有用。 因此,在发生上述错误的情况下,我们可以返回:

{
     "meta":{
      "code":405,
      "error":"Method not allowed for the /coins/{id} resource",
      "info":"Method DELETE is not allowed for that resource. Available methods : GET, POST, OPTIONS"
   },
   "data":{
   }
}

好多了? 响应包含相同的信息(405 http错误状态),但另外会通知客户端该资源的可用方法。

文献资料

最后但并非最不重要的。 花一些时间提供专业和开发人员友好的文档,并确保始终对其进行更新。 过时的文档要比根本没有文档差得多。 您可以使用为此目的而存在的几种开源和免费工具之一,并对所有API进行完善的文档编制。 更好的是,提供使用每种资源的示例,并在错误或成功的情况下给出预期的结果。 不要忘记,最后要记录每个错误代码并提供足够的信息,以便客户知道何时发生错误。 几个客户端会忽略任何响应消息,而是希望根据错误代码提供自己的消息。

我还有一些更实用的建议要写下来,尤其是关于API版本控制和安全性,但我认为它们都可以适合于另一篇博客文章!

翻译自: https://www.javacodegeeks.com/2014/05/rest-api-best-practices-reloaded.html

rest api

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值