我正在尝试做出架构决策,我担心在设计基本的 REST API / 框架时我会遗漏一些关于 URL 路由 / 映射的重要内容。
创建路由类等通常出现在 REST API 框架中,需要手动将 URL 映射到类和类方法(操作),这似乎是封装问题的失败。当这一切都可以通过动态解析 URL 并具有自动路由器或首页控制器来确定时。
GET https://api.example.com/companies/
获取所有公司列表的集合资源。
GET https://api.example.com/companies/1
按 ID 获取单个公司。
这一切似乎都遵循模板:https://api.example.com/<controller>/<parameter>/
好处一:URL解耦和抽象
我假设拥有典型路由类的纸面上的好处之一是您可以将 URL 从资源/物理类中解耦或抽象出来。因此,如果您愿意,您可以使用任意 URL,GET https://api.example.com/poo/
而不是GET https://api.example.com/companies/
获取所有公司。
但在我见过的几乎每个示例和用例中,都希望有一个与所需控制器、操作和参数 1 : 1 匹配的 URL。
另一个可能的好处是,使用 URL 映射和典型路由器可能更容易实现资源中的集合资源或嵌套资源。例如:
GET https://api.example.com/companies/1/users/
或者
GET https://api.example.com/companies/1/users/1/
想出一个可以动态解析它以知道要调用什么控制器来获取数据、使用什么参数以及在哪里使用它们的范式可能是相当具有挑战性的。但我想我已经想出了一种标准方法,可以动态地进行这项工作。
而手动映射这很容易。
我可以绕过它重新路由GET https://api.example.com/companies/1/users/
到用户控制器而不是公司控制器,并将参数“1”设置为 WHERE 子句的公司 ID。
好处 1.1:与物理路径无关
好处 1 的补充内容是,开发人员可以完全更改 URL 方案和文件夹结构,而不会影响 API,因为所有内容都是抽象映射的。如果我选择移动文件、文件夹、类或重命名它们,应该只是更改映射/路由的问题。
但是仍然没有真正得到这个好处,因为即使您必须将整个 API 移动到另一个位置,在 .htaccess 中的一个微不足道的更改也可以立即解决这个问题。
所以这:
GET https://api.example.com/companies/
至
GET https://api.example.com/v1/companies/
不会影响代码,即使是最轻微的。即使使用动态路由器。
好处 2:控制公开的功能
我想一个典型的路由器类给你的另一个好处是,通过一个只解释和解析 URL 的动态路由器,你可以准确地控制你想要向 API 使用者公开的功能。如果你只是动态地做所有事情,你有点脱掉裤子,自动让你的消费者访问整个系统。
我认为这对动态路由器来说是一个可能的好处,因为您不必手动定义所有路由并将其映射到资源。这一切都在那里,自动。为了解决暴露问题,我可能会通过定义不应允许 API 使用者使用哪些功能的黑名单来做相反的事情。我可能会更有效率,先定义一个黑名单,然后用映射定义每个可用资源。再说一次,我想这也风险更大。你甚至可以做一个白名单......这类似于典型的路由器,但你根本不需要任何扩展逻辑。在将 URL 传递给动态路由器之前,它只是系统将检查的 URL 列表。或者它可能只是动态路由器类的私有属性。
好处 3:当 HTTP 方法不完全符合要求时
我看到典型路由器发光的一种情况是您需要执行与现有资源冲突的操作。让我解释。
假设您想通过在用户类中运行登录功能来验证用户身份。但是现在,您不能POST https://api.example.com/users/
使用凭据执行,因为它是为添加新用户而保留的。相反,您需要以某种方式在您的用户类中运行登录方法。您不想使用POST https://api.example.com/users/login/
任何一种,因为那样您使用的是 HTTP 方法以外的动词。但是,对于典型的路由器,您可以直接映射它,如前所述。简单的。
url => "https://api.example.com/tenant/"
Controller => "users"
Action => "login"
Params => "api_key, api_secret"
但是,我再一次看到了一个合理的选择。我可以创建另一个控制器,称为登录或租户,实例化我的用户控制器,并运行登录功能。因此,消费者可以POST https://api.example.com/tenant/
凭凭证和指责。验证。
虽然,要使这种替代方法起作用,我必须物理地创建另一个控制器,但使用 URL 映射器时,我不需要。但是这种关注点、功能和资源的分离也非常好。但是,也许这是主要的权衡,您宁愿只定义一个 URL 路由,还是必须为遇到的每个细微差别创建新类?
我没有看到或理解什么?我在这里错过了一个核心概念而只是无知吗?拥有典型的 URL 映射和路由类和功能是否有更多的好处,我只是不知道,或者我几乎得到了这个?