验证 REST 终结点设计



REST 端点设计 说: 不使用动词

在类似工作流的创建员工中,它具有多选项卡样式,如"基本详细信息"、"教育详细信息"、"工作经验"等......按下第一个选项卡数据继续按钮,导致后端 API 调用,该调用仅验证该选项卡中的详细信息并返回验证错误列表(如果有)或移动到下一个选项卡供用户填充数据。所以基本上这需要为每个选项卡验证API,而不打算保存数据。现在自然而然的一件事如下:

发布/员工/基本/验证 (为简单起见,从端点中删除 API 版本控制详细信息)

但是在 API 中使用验证意味着动词。那怎么设计呢?

有一个单独的流程,人们可以只保存员工的"基本详细信息" - 所以它就像任何普通的 API 验证和保存一样 - 所以 POST/employee/basic/适合这种情况。

REST 端点设计说: 不使用动词

这不是 REST 约束 - REST 不关心你对资源标识符使用什么拼写。

所有这些 URL的工作方式都与您的浏览器期望它们完全一样:

  • https://www.merriam-webster.com/dictionary/post
  • https://www.merriam-webster.com/dictionary/get
  • https://www.merriam-webster.com/dictionary/put
  • https://www.merriam-webster.com/dictionary/patch
  • https://www.merriam-webster.com/dictionary/delete

资源是文档的概括;HTTP 统一接口的本质是我们有一大组文档,以及我们可以发送给它们的少量消息。

因此,如果您想要一个好的资源标识符,要考虑的重要事项是请求所针对的"文档"的性质。

例如,您用于验证用户输入的文档可能是验证策略;或者您可能更愿意将该文档视为验证报告集合的索引(其中我们为每个输入提供了一个报告)。

似乎您最终要做的是在试运行模式下运行您的操作。

例如,我的建议是添加一个干运行选项作为请求参数。

/employee/basic?dry-run=true

REST说你应该使用HTTP这样的标准来实现统一的接口。据我所知,没有 URL 标准,甚至 OData 也说它的 URL 命名约定是可选的。

浏览器是一个糟糕的REST客户端的另一件事。REST是为Web服务和机器对机器通信而设计的,而不是为浏览器与Web应用程序的通信而设计的,这是一种人与机器的通信。它用于解决诸如自动从批发商订购以用新商品填充我的网上商店等问题。如果在此方案中签入,则 REST 服务和 REST 客户端都在服务器上,与浏览器无关。如果你想从浏览器使用REST,那么最好使用基于javascript的REST客户端。因此,使用带有HTML表单的浏览器作为REST客户端是极端的。

如果您有多选项卡表单,则通常会将其收集到常规 Web 应用程序中的会话中,直到最终确定为止。所以一个解决方案是拥有一个常规的Web应用程序,这就是你实际拥有的,因为我很确定你不知道Fielding描述的强制性REST约束。在这种情况下,您只需随心所欲地做,而忘记REST。

至于命名进行验证的东西,我会做一些类似POST /employee/basic/validation的事情,并返回验证结果以及200 ok.尽管大多数验证规则(如"它是一个日期吗"、"它是一个数字吗"等)目前可以在客户端上完成,但它们甚至可以在 HTML 中完成。您可以在服务器端或客户端的会话中收集输入,并在完善员工描述后将其保存在数据库中。

按照 REST 方式,我将有一个超链接来描述所有参数及其验证,并让 REST 客户端制作选项卡并执行 REST。最后,它与 REST 服务通信的唯一时间是发送实际的 POST 时。例如,REST 客户端可以在浏览器中将输入收集到变量或 cookie 或本地存储中,或者 REST 客户端可以在服务器上并将输入收集到服务器端会话中。从 REST 服务开始,与它的通信必须是无状态的,因此它无法维护服务器端会话,只能维护 JWT,例如,所有会话数据都随每个请求一起发送。

如果要在完成之前将每个选项卡保存在Web服务中,那么您的问题类似于编程中的构建器设计模式解决的问题。在这种情况下,我会在第一步做类似POST /employeeRegistrationBuilder的事情,这将返回一个新资源,例如/employeeRegistrationBuilder/1.之后,我可以做一些类似PUT/POST /employeeRegistrationBuilder/1/basicsPUT/POST /employeeRegistrationBuilder/1/educationPUT/POST /employeeRegistrationBuilder/1/workExperience等操作,并用PUT/POST /employeeRegistrationBuilder/1/finished完成它。尽管您可以省去第一步和最后一步,并使用basics创建资源,并在发送workExperience后自动完成它。取消它会DELETE /employeeRegistrationBuilder/1,修改以前的选项卡将是PUT/PATCH /employeeRegistrationBuilder/1/basics。删除以前的选项卡将是DELETE /employeeRegistrationBuilder/1/basics.

一种更通用的方法是使用一种事务构建器并执行以下操作:

POST /transactions/ {type:"multistep", method: "POST", id: "/employee/"}
-> {id: "/transactions/1", links: [...]}
PATCH /transactions/1 {append: "basics", ...}
PATCH /transactions/1 {append: "education", ...}
PATCH /transactions/1 {remove: "basics", ...}
PATCH /transactions/1 {append: "workExperience", ...}
PATCH /transactions/1 {append: "basics", ...}
...
POST /employee/ {type: "transaction", id: "/transactions/1"}
-> /employee/123

使用此方法,您可以通过多个步骤或单个步骤创建新员工,具体取决于您是发送实际输入数据还是带有POST /employee的交易引用。

从数据保护(GDPR)的角度来看,交易可以是合同的准备,提交交易可以是签署合同。

最新更新