5

我正在尝试做出架构决策,我担心在设计基本的 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 映射和路由类和功能是否有更多的好处,我只是不知道,或者我几乎得到了这个?

4

1 回答 1

1

您描述的路由的许多好处是正确的,您所说的有关物理映射的一些内容也是正确的。我想提供一些经验/实用信息,这些信息在过去几年中影响了我对路由器的看法。

  1. 首先,当您根据 MVC 设计模式构建应用程序时,url 的动态解析(大多数情况下)效果很好。例如,我曾经使用 Kohana 构建了一个非常大的应用程序,它是一个分层 MVC 框架,它允许您扩展控制器和模型以制作嵌套 url。一般来说,这很有意义。但是很多时候,围绕一次性 URL 的需求构建一个完整的类和模型系统以使应用程序更具功能性并没有多大意义。但是有时 MVC 不是您正在使用的设计模式,因此它不是 API 的定义特性,并且在这种情况下路由是美丽的。通过使用具有很大结构自由度的框架,可以很容易地看到这个问题,

  2. 比人们想象的更常见的是,除了可供消费的主要 RESTful 端点外,功能齐全的 API 还具有 RPC 元素。当消费者在装饰现有资源方法映射时,这些附加功能不仅更有意义。这往往发生您构建了大部分应用程序并覆盖了大部分基础之后,然后您意识到您想要添加一些与资源相关的小功能干净地适合 CREATE / READ / UPDATE / DELETE 类别。当你看到它时你就会知道。

  3. 真的不能低估,不要为了添加一个本质上不遵循相同规则的端点而对控制器和模型的实际结构进行黑客攻击,添加、删除、更改内容要安全得多其他控制器方法(API 端点)。

  4. 另一个非常重要的事情是,您的 API 端点实际上比我们通常意识到的更具可塑性。我的意思是,你可以在星期一对端点的结构感到满意,然后在星期五,你从上面收到这个任务,说你需要将所有这些 API 调用更改为其他结构,那就是美好的。但是如果你有一个大型应用程序,这需要非常非常多的文件重命名、类重命名、链接以及各种非常易破解的代码当你使用的框架对类命名、文件命名、物理文件路径结构和类似的东西有严格的规则时......想象一下,改变一个类名以使其与新结构一起工作,现在你已经有了去寻找实例化旧类的每一行代码,并改变它。此外,在这种情况下,可以说问题在于您的代码与 API 的 url 结构紧密耦合,如果您的 url 需要更改,那么这不是很容易维护。

无论哪种方式,你真的应该决定什么最适合特定的应用程序。但是您使用路由器的次数越多,您就越会明白它们为何如此有用。

于 2013-10-07T20:36:04.617 回答