77

我通常是 RESTful API 设计的粉丝,但我不确定如何将 REST 原则应用于验证 API。

假设我们有一个 API 用于查询和更新用户的个人资料信息(姓名、电子邮件、用户名、密码)。我们认为公开的一个有用功能是验证,例如查询给定用户名是否有效和可用。

在这种情况下,资源是什么?应该使用哪些 HTTP 状态代码和/或标头?

作为开始,我有GET /profile/validate它接受查询字符串参数并返回204或者400如果有效或无效。但是validate显然是动词而不是名词。

4

5 回答 5

52

您所描述的事物类型在其语义上肯定更具有 RPC 风格,但这并不意味着您无法以 RESTful 方式实现目标。

没有VALIDATEHTTP 动词,那么围绕它构建整个 API 可以获得多少价值?您的故事围绕为用户提供确定给定用户名是否可用的能力——在我看来这听起来像是一个简单的资源检索检查 GET: /profile/username/...——如果结果是 404,则该名称可用。

这强调的是客户端验证就是客户端。确保数据在发送到服务器之前在客户端上得到验证是一个 UI 问题。RESTful 服务不关心客户端是否执行了验证。它会根据自己的验证逻辑简单地接受或拒绝请求。

REST 不是一个包罗万象的范例,它只描述了一种构建客户端-服务器通信的方式。

于 2012-07-26T19:41:44.953 回答
21

我们也遇到了同样的问题。我们让客户端延迟到服务器进行验证的原因是为了防止出现不匹配的规则。服务器需要在对资源进行操作之前验证所有内容。将这些规则编码两次并有可能使它们不同步是没有意义的。因此,我们提出了一个似乎与 REST 理念保持一致的策略,同时允许我们要求服务器执行验证。

我们的第一步是实现一个可以从元数据服务请求的元数据对象 ( GET /metadata/user)。然后使用此元数据对象告诉客户端如何进行基本的客户端验证(要求、类型、长度等)。我们从我们的数据库中生成其中的大部分。

第二部分包括添加一个称为分析的新资源。例如,如果我们有一个服务:

GET /users/100

我们将创建一个名为的新资源:

POST /users/100/analysis

分析资源不仅包含发生的任何验证错误,还包含必要时可能相关的统计信息。我们争论的问题之一是分析资源使用哪个动词。我们已经得出结论,它应该是一个 POST,因为分析是在请求时创建的。然而,对于 GET 也有强烈的论据。

我希望这对试图解决同样问题的其他人有所帮助。对此设计的任何反馈表示赞赏。

于 2016-02-19T14:30:55.873 回答
11

您将 REST 与资源导向混淆了,REST 中没有任何内容表明您不能在 URL 中使用动词。当谈到 URL 设计时,我通常选择最能自我描述的东西,无论是名词还是动词。

关于您的服务,我要做的是使用与更新相同的资源,但带有test查询字符串参数,因此当test=1操作未完成时,您可以使用它来返回验证错误。

PATCH /profile?test=1
Content-Type: application/x-www-form-urlencoded

dob=foo

...和回应:

HTTP/1.1 400 Bad Request
Content-Type: text/html

<ul class="errors">
  <li data-name="dob">foo is not a valid date.</li>
</ul>
于 2012-07-26T21:58:36.497 回答
0

一个非常常见的场景是拥有一个用户名或个人资料注册表单,其中的用户名和电子邮件应该是唯一的。通常会在文本框的模糊处显示一条错误消息,让用户知道用户名已经存在或者他们输入的电子邮件已经与另一个帐户相关联。其他答案中提到了很多选项,但我不喜欢需要查找 404 表示用户名不存在的想法,因此它是有效的,等待提交以验证整个对象,并返回元数据进行验证对检查唯一性没有帮助。

Imo,应该有一个 GET 路由,每个需要验证的字段返回 true 或 false。

/users/validation/username/{username}

/users/validation/email/{email}

您可以使用此模式为需要服务器端验证的任何其他字段添加任何其他路由。当然,您仍然希望在 POST 中验证整个对象。

此模式还允许在更新用户时进行验证。如果用户专注于电子邮件文本框,然后单击以触发模糊验证,则需要稍微不同的验证,因为只要电子邮件与当前用户相关联,如果电子邮件已经存在就可以了。您可以利用这些也返回 true 或 false 的 GET 路由。

/users/{userId:guid}/validation/username/{username}

/users/{userId:guid}/validation/email/{email}

同样,整个对象都需要在您的 PUT 中进行验证。

于 2021-05-18T12:45:41.693 回答
-2

很高兴在 REST API 中进行验证。无论如何,您都需要验证,并且不要在客户端使用它。在我的例子中,我只是在 API 中有一个约定,一个特殊的 error_id 表示验证错误,并且在 error_details 中,对于在此 PUT 或 POST 调用中有错误的每个字段都有一组错误消息。例如:

{
  "error": true,
  "error_id": 20301,
  "error_message": "Validation failed!",
  "error_details": {
    "number": [
      "Number must not be empty"
    ],
    "ean": [
      "Ean must not be empty",
      "Ean is not a valid EAN"
    ]
  }
}

如果您将相同的 REST API 用于 Web 和移动应用程序,您将希望能够仅通过更新 API 来更改两者的验证。特别是移动更新需要 24 小时以上才能在商店上发布。

这就是它在移动应用程序中的样子: 在此处输入图像描述

PUT 或 POST 的响应用于显示每个字段的错误消息。这是来自使用 React 的 Web 应用程序的相同调用: 在此处输入图像描述

这样,所有 REST API 响应代码(如 200 、 404)都具有应有的含义。即使验证失败,PUT 调用也会响应 200。如果调用通过验证,响应将如下所示:

{
  "error": false,
  "item": {
"id": 1,
"created_at": "2016-08-03 13:58:11",
"updated_at": "2016-11-30 08:55:58",
"deleted_at": null,
"name": "Artikel 1",
"number": "1273673813",
"ean": "12345678912222"
  }
}

您可以进行一些可能的修改。可以在没有 error_id 的情况下使用它。如果有 error_details 只需循环它们,如果您找到与字段同名的键,则将其值作为错误文本放入同一字段。

于 2016-11-30T08:08:32.263 回答