Tai*_*hat 3 forms validation error-handling server-side http-status-codes
我是第一次开发网站,我选择使用 mongodb、node、express 和 angular,即 MEAN 堆栈。我正在研究的前几个功能之一是一个简单的表单,目前手头的任务是表单验证。我对如何验证表单提交进行了大量研究,并了解有必要同时实现客户端和服务器端验证。出于各种原因但主要是安全性的客户端验证和服务器端验证以获得更好的用户体验。
但是,我面临的问题是我应该如何响应将表单数据提交到我的 REST API 时可能出现的不同错误。我想知道可能出现的每种情况以及如何处理每种情况,例如要响应的状态代码以及我是否应该提供特定的错误消息?
编辑: 我会添加一些更具体的问题,但请不要将您的回答限制在这些问题上。
1)我可以假设没有客户要求的字段的请求实际上不是来自我的客户并且很可能是对手,所以我应该只发送“错误请求(400)”而不提供任何错误消息?
2)对于验证错误,例如缺少必填字段或格式不正确的字段,我是否应该使用除 200 以外的任何其他状态代码?我问这个是因为当我发送 4XX 响应时,我的浏览器控制台中会生成一个错误,而当网站的行为正常时,这似乎不正确。
我希望我说清楚了。如果没有,请告诉我,以便我可以尝试更具体。
当您声明需要客户端和服务器端验证时,您是正确的。您希望如何呈现客户端验证错误完全取决于您。禁用提交按钮,将无效输入框的边框变为红色等,是典型的。HTML5 已经为某些事情(数字、日期、长度)内置了验证方法。如果这还不够,您可以在 Google 上查找角度表单验证。
至于服务器端验证期间的 HTTP 状态代码,对于在不同场景中应该响应哪些状态代码,没有固定的标准。如果您是唯一一个使用 API 的人,那么您可以相当自由地做任何想做的事。
但是,如果您想遵循 API 的 REST 原则,则有一个事实上的标准。如果我们查看Lequoa 提供的链接,我们会发现以下类别:
目前我们对以 1 和 3 开头的代码不感兴趣。事实上,我们关心的唯一代码是带星号的代码:
以下是通常如何使用这些的一些经验法则:
200 范围内的状态代码用于成功请求。
当服务器在 GET 之后成功返回资源时,您使用200 OK。消息是请求的内容。
当服务器在 POST 后成功创建资源时,您使用201 CREATED。消息通常是创建的内容(例如新的博客文章)。
每当您删除、修补或放置某些内容时,您都可以使用204 No Content。您永远不会提供带有此状态代码的消息。
当客户端发送错误请求时使用 400 范围。
400 Bad Request用于未通过验证的请求、缺少字段的请求等。发送的消息由您决定,但它通常包含在消息字段中,如下所示:
response.status = HttpStatus.BAD_REQUEST;
response.message = { 'message': 'Illegal schoolID' };
res.status(response.status).json(response.message);
Run Code Online (Sandbox Code Playgroud)
这是我将用于提供非法学校 ID 的 GET 请求的消息。如果您想美化客户端的错误消息,您当然可以提供实际的验证结果对象。
401 Unauthorized和403 Forbidden用于身份验证(登录等)。
当客户端为不存在的资源发送 GET 时使用404 Not Found。
422 Unprocessable Entity也可用于在输入语法正确但语义错误时验证错误。
如果抛出错误或者您在回调中遇到错误,您可以使用500 Internal Server Error。例如
Model
.findById(modelId)
.exec(function (err, models) {
if (err) {
res.status(500).json(err);
return;
}
...
Run Code Online (Sandbox Code Playgroud)
这不用于验证错误,而是用于永远不应该发生的错误。毕竟,验证错误并不少见。内部服务器错误是服务器端代码中的错误,或者服务器着火或类似的错误。
当浏览器返回 4** 或 5** 状态代码时,它必须处理它。它们将被打印到控制台,这很好,您不应该使用 2** 代码使其消失。浏览器必须读取错误消息并以用户友好的方式将其显示给用户。如果服务器响应提供的消息是用户友好的,那么它可以直接显示,否则你必须写这样的东西(AngularJS):
schoolDataFactory.patchUpdateSchool(vm.school._id, newSchoolData).then(function (res) {
if (res.status === 204) {
vm.errorMessage = ''
vm.message = 'School info was updated.'
} else {
console.log('The server should send 204 No Content on successful PATCH, so this shouldn't happen.')
}
}).catch(function (error) {
vm.message = ''
if (error.status === 400 && error.data.message === 'ValidationError: schoolName') {
vm.errorMessage = 'Fix the school name'
} else if (error.status === 400 && error.data.message === 'ValidationError: schoolAddress') {
vm.errorMessage = 'Fix the school address'
} else if (error.status === 500) {
vm.errorMessage = 'Something is wrong with the server.'
}
})
Run Code Online (Sandbox Code Playgroud)
这个假设的例子向服务器发送一个 PATCH 请求,其中包含新的学校数据。如果 PATCH 成功,浏览器会收到状态代码 204 并在 then() 中运行回调。如果它收到 4** 或 5**,它会在 catch() 中运行回调来处理错误。vm.errorMessage 和 vm.message 绑定在视图中并显示给用户。
关键是如果来自服务器的响应很丑陋,您可能必须在客户端代码中转换响应消息。
我认为设计它的一个好方法是假装您只编写服务器端代码和 API。假设其他人在做前端,然后想象他们想看到什么。或者想象一下您的 API 是完全公开的,每个人都可以使用它。如果您这样做并且不对客户端是什么或谁做任何假设,那么后端将与前端松散耦合,这正是您想要的。
您唯一可以假设的是,有人会尝试使用名为 Postman 的应用程序来破坏您的一天。