文章目录
使用Egg实现基本HTTP谓词操作
1 目标
本文的目的是使用Egg实现基本HTTP谓词操作。
HTTP 谓词 | 功能 | 用途 | 示例 |
---|---|---|---|
GET | 获取资源 | 从服务器检索数据,不会对服务器上的数据产生任何影响 | 获取所有项目:GET /items 获取指定ID的项目:GET /items/1 |
POST | 创建资源 | 向服务器发送数据,并在服务器上创建新的资源 | 添加新项目:POST /items 请求体:{ “name”: “New Item”, “description”: “New Description” } |
PUT | 更新资源(替换整个资源) | 替换服务器上的现有资源 | 更新项目:PUT /items/1 请求体:{ “name”: “Updated Item”, “description”: “Updated Description” } |
PATCH | 更新资源(部分更新资源) | 更新服务器上的现有资源的部分内容 | 部分更新项目:PATCH /items/1 请求体:{ “description”: “Partially Updated Description” } |
DELETE | 删除资源 | 从服务器上删除指定资源 | 删除项目:DELETE /items/1 |
2 步骤
2.1 安装
2.1.1安装Egg.js的脚手架工具
npm install egg-init -g
2.1.2使用脚手架工具创建一个新项目
egg-init egg-example --type=simple
cd egg-example
npm install
2.2 代码
2.2.1 创建app.js
在app.js中声明全局变量
// app.js
module.exports = (app) => {
app.beforeStart(async () => {
// 在应用启动时初始化数据(全局变量)
app.items = [
{ id: 1, name: "Item 1", description: "Description 1" },
{ id: 2, name: "Item 2", description: "Description 2" },
];
});
};
2.2.2 创建控制器
在app/controller目录下创建一个新的控制器文件items.js:
// app/controller/items.js
"use strict";
const Controller = require("egg").Controller;
class ItemsController extends Controller {
constructor(ctx) {
super(ctx);
}
async index() {
const { ctx, app } = this;
ctx.body = app.items;
}
async show() {
const { ctx, app } = this;
const item = app.items.find((i) => i.id === parseInt(ctx.params.id));
if (!item) {
ctx.status = 404;
ctx.body = "Item not found";
return;
}
ctx.body = item;
}
async create() {
const { ctx, app } = this;
const newItem = {
id: app.items.length + 1,
name: ctx.request.body.name,
description: ctx.request.body.description,
};
app.items.push(newItem);
ctx.status = 201;
ctx.body = newItem;
}
async update() {
const { ctx, app } = this;
const itemIndex = app.items.findIndex(
(i) => i.id === parseInt(ctx.params.id)
);
if (itemIndex === -1) {
ctx.status = 404;
ctx.body = "Item not found";
return;
}
const updatedItem = {
id: app.items[itemIndex].id,
name: ctx.request.body.name,
description: ctx.request.body.description,
};
app.items[itemIndex] = updatedItem;
ctx.body = updatedItem;
}
async partialUpdate() {
const { ctx, app } = this;
const item = app.items.find((i) => i.id === parseInt(ctx.params.id));
if (!item) {
ctx.status = 404;
ctx.body = "Item not found";
return;
}
if (ctx.request.body.name) {
item.name = ctx.request.body.name;
}
if (ctx.request.body.description) {
item.description = ctx.request.body.description;
}
ctx.body = item;
}
async destroy() {
const { ctx, app } = this;
const itemIndex = app.items.findIndex(
(i) => i.id === parseInt(ctx.params.id)
);
if (itemIndex === -1) {
ctx.status = 404;
ctx.body = "Item not found";
return;
}
const deletedItem = app.items.splice(itemIndex, 1);
ctx.body = deletedItem;
}
}
module.exports = ItemsController;
2.2.3 添加获取CSRF令牌函数
在app/controller目录下修改home.js:
const { Controller } = require("egg");
class HomeController extends Controller {
async index() {
const { ctx } = this;
ctx.body = "hi, egg";
}
//新增一个获取token的接口
async csrfToken() {
this.ctx.body = {
csrfToken: this.ctx.csrf,
};
}
}
module.exports = HomeController;
2.2.4 添加路由
在app目录下修改router.js:
/**
* @param {Egg.Application} app - egg application
*/
module.exports = (app) => {
const { router, controller } = app;
router.get("/", controller.home.index);
router.get("/csrfToken", controller.home.csrfToken);
router.get("/items", controller.items.index);
router.get("/items/:id", controller.items.show);
router.post("/items", controller.items.create);
router.put("/items/:id", controller.items.update);
router.patch("/items/:id", controller.items.partialUpdate);
router.delete("/items/:id", controller.items.destroy);
};
2.3 运行
npm run dev
2.4 补充
在调用post等接口时候由于有CSRF保护,所以必须携带令牌。在请求头中添加x-csrf-token字段,并将值设置为获取到的CSRF令牌。