洞察两种 REST API 设计的可行性

Insight into the feasibility of two REST API designs

我过去开发了几个 REST API,目前正在为我们公司的内部软件解决方案构建一个新的。我选择了 MEAN 堆栈来构建它,并选择了 Mongoose 来管理模式设计和数据层验证。良好的设计、耐用性和可扩展性是我的首选。

API 将被我们内部的 Angular 应用程序、Android 应用程序使用,谁知道还有什么,它可能有一天会被我们的 PHP 使用网站,或者在更远的未来我们可能会为其他企业提供该平台。

我目前正在权衡两种设计:

通用设计

API 消费者可以根据前端要求灵活地进行查询,同时将非常复杂的编译移至自定义端点。全局限制(例如:最多可以返回 100 条记录),每个经过身份验证的系统用户类型都可以限制架构和记录级别访问。

'use strict';

module.exports = function (app) {

            // Api routing
            var api = require('../controllers/api.controller.js');

            /**
             * Cental API router
             */

            app.route('/api/create')
                .post(api.create);

            app.route('/api/read')
                .get(api.read);

            app.route('/api/update')
                .put(api.update);

            app.route('/api/remove')
                .delete(api.remove);

            app.route('/api/dashboard/:country/:date') //Complex endpoint
                .get(api.dashboard);
    };

创建调用的示例响应:

{
   "response":[
      {
         "_id":"54f703531c3757fe23923250",
         "entity_id":3,
         "customer_id":104,
         "base_grand_total":15,
         "total_qty_ordered":1,
         "total_item_count":1,
         "customer_gender":1,
         "shipping_address_id":6,
         "quote_id":8,
         "increment_id":"200000089",
         "order_currency_code":"AED",
         "country_id":"AE",
         "status":"pending_receiving"
      }
   ],
   "numberAffected":1,
   "result":"created",
   "dataModel":"Orders",
   "errorMsg":null,
   "error":0
}

用例:使用 AngularJS 删除用户。

            var req = {
                method: 'DELETE',
                url: '/api/remove',
                data: {query: {'_id': id}, dataModel: 'Users' // 'Orders', 'Products' 'Etc'},
                headers: {
                    'Content-Type': 'application/json'
                }
            };

            $http(req).success(function (res) {

                $scope.users.splice(rowIndex,1);
                console.log(res);

            }).error(function (res) {

                console.log(res);
            });

限制设计

获取客户​​需求并提供端点。可能看起来像这样:

public function userProfileAction()
public function createPostAction()
public function getPostsByUserAction()
public function getPostsByDistanceAction()
public function getPostsByFollowedUsersAction()
public function getPostsByVenueAction()
public function getPostsLikedByUserAction()
public function deletePostAction()
public function reportPostAction()
public function recommendPostAction()
public function followUserAction()
public function likePostAction()

为了防止这个问题跑偏,我想具体一点,只关注每种方法的优缺点。

我看到的通用设计的优点是它没有与服务器紧密耦合,因此我们可以构建很多功能,而无需一次又一次地返回和编码端点。缺点是,如果我在 4 API 个消费者中有相同的查询,如果我决定进行更改,我需要更改每个消费者中的查询。对于受限设计,反之亦然。

你们能指出更多我可能遗漏的、利弊的、我应该注意的事情吗?是否存在安全问题或我可能忽略的主要设计缺陷。

谢谢!

有显着的优缺点:

通用的优点API:

  • 它是通用目的,旨在提供对允许客户执行的所有合法功能的访问权限。
  • 客户可能会使用通用目的 API 来解决他们甚至还不知道自己需要的未来问题。
  • 随着客户需求的发展,对新 API 功能的请求可能会减少很多,因为已经提供了一般访问权限。

通用的缺点API:

  • 编码工作可能更多,测试工作也很可能更多。
  • 安全或访问控制问题可能更复杂。
  • 被非预期客户滥用的可能性更高。
  • 客户可能必须 "build" 他们自己的层在您的 API 之上,方法是拼凑几个 API 调用以获得他们想要的特定功能。
  • API 提供的解决方案可能无法像专门针对给定客户需求的规范设计的端点那样高效地提供解决方案(换句话说,客户可能必须使用多个 API 请求或可能获取和查看比最佳数据更多的数据)。

受限 API 的 pros/cons 几乎与这些相反。


一个中间立场是让客户提交一份他们需要访问哪些功能的详细规范,然后设计一个通用目的 API,但最初只实施解决客户当前问题所需的部分问题。

这为您提供了一个通用设计,并为您将来以合乎逻辑、有计划的方式扩展对其他领域的访问做好了准备。但是,您不会实施或不必测试超出客户现在真正需要的内容(这通常是业务需求)。而且,您可以 100% 确定您的通用实现子集满足客户当前的需求,因为您可以根据他们的需求规范对其进行测试。


在没有让客户列出他们的具体和当前需求的情况下一直达到一般目的 API 会冒意外无法涵盖客户需要的所有需求的风险。而且,它可能会花时间实施和测试许多当前不需要的东西。

一直到一个受限制的 API 将 API 调用与每个特定的客户规范请求对齐,这使得很难有一个全面周到的 API 设计(因为一个从来没有从一开始就设计出来,你最终会得到客户请求的大杂烩。

据推测,您可以看出这两个极端都不太理想。