让我们从Response Resources
休息一下,转到代码的另一部分,让我们回到我们心爱的路由器,今天我们将谈论Restful Routes
以及如何在我们的项目中实施它们。
宁静的API概念
那么,Restful Api
是什么,您以前可能听说过这种表达,但是这是什么意思? Restful Api
是Roy Fielding
在他的论文中引入的一个概念,这是我们应该遵循的一组规则来创建一个Restful Api
,此概念的主要思想是使我们的API More standard
和consistent
,以便我们可以轻松地使用它在任何项目中。
RESTFUL API规则
我们应该遵循6个规则来创建一个Restful Api
,让我们看一下:
-
使用名词作为路径路径。例如,
/users
而不是/getAllUsers
。 -
使用HTTP动词进行路线方法。例如,
GET
而不是getAllUsers
。 -
将复数名词用于路径路径。例如,
/users
而不是/user
。 -
使用查询参数过滤,排序和分页集合。例如,
/users?sort=age&limit=10
。 -
使用HTTP状态代码表示响应的状态。例如,
200
成功,未找到404
,而500
用于服务器错误。 -
使用Snake_case(Nove Camelcase)查询参数和字段。例如,
/users?sort_by=age
。
我更喜欢最后一点的骆驼,但这取决于您。
恢复的API路线
现在我们知道了规则,让我们看一下应该在项目中实施的路线,我们将实现以下路线:
-
GET /users
获取所有用户。 -
GET /users/:id
获取一个用户。 -
POST /users
创建新用户。 -
PUT /users/:id
更新用户。 -
DELETE /users/:id
删除用户。 -
PATCH /users/:id
部分更新用户。
这些是我们可以在每个模块中静止的API中实现的主要路由,但是当然,我们可以添加我们需要的所有其他路线,例如,我们可以添加一条路由以获取用户的帖子或获得用户的评论或获得用户的朋友等等。
RESTFUL API实现
我们将从下一篇文章开始开始我们的实施,但是本文我们需要首先修复一些内容,因为如果您逐步与我合作,您将被击中代码。
反应身体解析器
我们已经较早地引入了Response Body Parser,以使任何称为异步的toJSON
,其中有一些问题,例如,Is.iterable
会循环浏览strings
,这绝对不是我们想要的,所以我们需要修复它,这是新的,这是新的Response Body Parser
的版本:
// src/core/http/response.ts
// ...
/**
* Parse the given value
*/
protected async parse(value: any): Promise<any> {
// if it is a falsy value, return it
if (!value || Is.scalar(value)) return value;
// if it has a `toJSON` method, call it and await the result then return it
if (value.toJSON) {
return await value.toJSON();
}
// if it is iterable, an array or array-like object then parse each item
if (Is.iterable(value)) {
const values = Array.from(value);
return Promise.all(
values.map(async (item: any) => {
return await this.parse(item);
}),
);
}
// if not plain object, then return it
if (!Is.plainObject(value)) {
return value;
}
// loop over the object and check if the value and call `parse` on it
for (const key in value) {
const subValue = value[key];
value[key] = await this.parse(subValue);
}
return value;
}
我在此处添加的是Is.scalar
检查,这检查值是否为string
,number
或boolean
,如果是这样,请返回它,因为我们不会解析它。
我还通过将Array.from
拆分以在变量中初始化,从而增强了承诺中的代码,这是为了使代码更可读取。
防止向响应发送响应对象
当验证器返回响应实例时,任何中间件也可以返回响应实例,路由器处理程序当然可以这样做,那么我们需要检查返回的输出是否是响应实例,然后只需返回而不将其发送到response.send
方法,也更加一致,我们还可以在send
方法本身内添加检查。
// src/core/http/response.ts
// ...
/**
* Send the response
*/
public async send(data?: any, statusCode?: number) {
// if the data is a response instance, then just return current response object
if (data === this) return this;
if (data) {
this.currentBody = data;
}
// parse the body and make sure it is transformed to sync data instead of async data
data = await this.parseBody();
if (statusCode) {
this.currentStatusCode = statusCode;
}
if (!this.currentStatusCode) {
this.currentStatusCode = 200;
}
// ...
}
现在让'更新我们的request
执行方法。
// src/core/http/request.ts
/**
* Execute the request
*/
public async execute() {
// check for middleware first
const middlewareOutput = await this.executeMiddleware();
if (middlewareOutput !== undefined) {
// 👇🏻 make sure first its not a response instance
if (middlewareOutput instanceof Response) return;
// 👇🏻 send the response
return this.response.send(middlewareOutput);
}
const handler = this.route.handler;
// 👇🏻 check for validation using validateAll helper function
const validationOutput = await validateAll(
handler.validation,
this,
this.response,
);
if (validationOutput !== undefined) {
// 👇🏻 make sure first its not a response instance
if (validationOutput instanceof Response) return;
// 👇🏻 send the response
return this.response.send(validationOutput);
}
// call executingAction event
this.trigger("executingAction", this.route);
const output = await handler(this, this.response);
// 👇🏻 make sure first its not a response instance
if (output instanceof Response) return;
// call executedAction event
this.trigger("executedAction", this.route);
// 👇🏻 send the response
await this.response.send(output);
}
现在我们在这里很好。让我们也更新响应的另一部分。
找不到响应
我们已经在响应类中具有我们的notFound
方法,但是需要向其发送数据,这是可以的,但是我们可以通过使其可选来统一响应,因此我们可以在不发送任何数据的情况下调用它,这是notFound
方法的更新版本:
// src/core/http/response.ts
/**
* Send a not found response with status code 404
*/
public notFound(
data: any = {
error: "notFound",
},
) {
return this.send(data, 404);
}
// ...
我们为什么要这样做?因为稍后,我们可以将其增强以使其可配置,因此我们可以发送一个自定义响应,例如,我们可以发送一个自定义的未找到JSON响应。
这也适用于badRequest
方法,但我们现在将其保留。
- 结论
因此,在本文中,我们讨论了Restful APIs
及其标准,然后我们对response
课程进行了一些增强,以使其更加一致,并且我们还对request
班级进行了一些增强,以使其更加一致。
在下一章中,我们将开始实施我们的Restful API
,并查看如何使用路由器系统处理,请继续关注!
â•给我买一杯咖啡。
如果您喜欢我的文章并看到对您有用,则可以buy me a coffee,它将帮助我继续前进并继续创建更多内容。
ð项目存储库
您可以在Github上找到此项目的最新更新
ð加入我们的社区
在Discord上加入我们的社区以获得帮助和支持(节点JS 2023频道)。
ð视频课程(阿拉伯语)
如果您想以视频格式学习此课程,则可以在Youtube上找到该课程,该课程是阿拉伯语。
ð奖励内容ð
您可能会看这些文章,这肯定会提高您的知识和生产力。
一般主题
- Event Driven Architecture: A Practical Guide in Javascript
- Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript
- After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
软件包和库
- Collections: Your ultimate Javascript Arrays Manager
- Supportive Is: an elegant utility to check types of values in JavaScript
- Localization: An agnostic i18n package to manage localization in your project
React JS软件包
课程(文章)