继续上一篇文章的学习,如果小伙伴们要回顾上一篇的内容,请点击这里 eggjs 实现服务端请求教程文档-1
三、用户详情接口开发(post 请求)
egg
有了 get
请求的示例,post
实现同理。
/app/router/detail.js
'use strict';
module.exports = app => {
const { router, controller } = app;
router.post('/api/getUserDetail', controller.home.userDetailController);
};
/app/controller/home.js
...
class HomeController extends Controller {
async userListController() { ... }
async userDetailController() {
const { ctx } = this;
ctx.body = {
data: 'userDetail query success',
success: true,
};
}
}
...
因为 post
请求无法通过 url 实现接口调用,所以我们首要目的是成功调用接口:
web
# 终端执行,使用命令行创建页面
alita g pages userDetail
/src/pages/userDetail/service.ts
import { request } from 'alita';
export async function queryUserDetail(params: any): Promise<any> {
return request('/api/getUserDetail', { method: 'post', data: params });
}
/src/pages/userDetail/index.tsx
import React, { FC } from 'react';
import { useRequest } from 'alita';
import { queryUserDetail } from './service';
import styles from './index.less';
interface UserDetailPageProps {
location: any;
}
const UserDetailPage: FC<UserDetailPageProps> = ({ location }) => {
const { id } = location.query;
const { data } = useRequest(() => queryUserDetail({ id }));
return <div className={styles.center}>{data}</div>;
};
export default UserDetailPage;
在列表页点击任意一项,即可跳转到用户详情页。url 为 http://localhost:8000/#/userDetail?id=1
但是请求似乎并没有想象的那样成功。
接口403
,报错信息 {"message":"invalid csrf token"}
。
通过百度得知框架内置了安全系统,默认开启防止 XSS
攻击 和 CSRF
攻击。参考Egg post 失败 { message: ‘invalid csrf token’ } 解决方案可得到一下的解决方案
egg
/config/config.default.js
:
config.security = {
csrf: {
headerName: 'x-csrf-token', // 自定义请求头
},
};
web
给请求头 headers
增加 x-csrf-token
:
/src/utils/index.ts
// 封装获取 cookie 的方法
export const getCookie = (name: any) => {
var arr,
reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');
if ((arr = document.cookie.match(reg))) return unescape(arr[2]);
else return '';
};
/src/app.ts
通过中间件统一给请求接口增加 header
const middleware = async (ctx: Context, next: any) => {
// 可以在这写一些请求前做的事情 操作ctx.req
ctx.req.options = {
...ctx.req.options,
headers: {
'x-csrf-token': getCookie('csrfToken'), // 前后端不分离的情况加每次打开客户端,egg会直接在客户端的 Cookie 中写入密钥 ,密钥的 Key 就是 'scrfToken' 这个字段,所以直接获取就好了
},
};
await next();
// 可以在这里对响应数据做一些操作 操作ctx.res
};
egg
最后我们在 controller
拿到接口请求的入参,重新封装出参的数据。
/app/controller/home.js
async userDetailController() {
const { ctx } = this;
const { id } = ctx.request.body;
console.log(ctx.request.body);
ctx.body = {
data: {
id,
name: `name${id}`,
},
success: true,
};
}
当有调用到接口时,终端会显示 ctx.request.body
的数据。
四、egg 中间件
写了中间件,所有请求都会经过中间件。可以在中间件进行操作处理。
可以参考官网编写 Middleware示例。
这里将实现实现一个需求,在请求头 header
增加 requestHeader
的参数。接口侧在中间件进行校验 requestHeader
的正确性。若正确,则流程继续。若不正确,则无法请求接口。
egg
在 /app
下新建 /middleware
文件夹。这也是约定,用来存放中间件。
/app/middleware/request.js
不着急实现功能,要先试试中间件是否增加成功。
通过下面的代码可以看出,若中间件实现成功,每当有接口请求,终端就会展示 options
(config.default.js) 的参数,以及请求的入参参数。
'use strict';
module.exports = options => {
return async function requestMiddleware(ctx, next) {
console.log(options.requestHeader, ctx.request.body);
await next();
};
};
/config.config.default.js
module.exports = appInfo => {
...//这里省略部分代码
config.middleware = ['request']; // 将 `request.js` 文件加入中间件中
// 给 `request.js` 增加配置参数
exports.request = {
requestHeader: 'hang',
};
return {
...config,
...userConfig,
};
};
访问 http://localhost:8000/#/userDetail?id=2
那么说明中间件配置成功。开始来编写功能代码
/app/middleware/request.js
module.exports = options => {
return async function requestMiddleware(ctx, next) {
const { requestHeader } = ctx.request.header;
if (ctx.request.header.requestheader === options.requestHeader) {
await next();
} else {
ctx.status = 403;
ctx.body = {
data: 'access was denied',
success: false,
};
}
};
};
web
若接口请求失败,在 web 中间件统一显示处理。
/config/config.ts
export const request = {
prefix: '', // 统一的请求头
middlewares: [middleware],
errorHandler: (error: ResponseError) => {
if (error.response.status === 403) {
Toast.fail('access was denied');
}
},
};
/config/config.ts
const middleware = async (ctx: Context, next: any) => {
// 可以在这写一些请求前做的事情 操作ctx.req
ctx.req.options = {
...ctx.req.options,
headers: {
'x-csrf-token': getCookie('csrfToken'), // 前后端不分离的情况加每次打开客户端,egg会直接在客户端的 Cookie 中写入密钥 ,密钥的 Key 就是 'scrfToken' 这个字段,所以直接获取就好了
requestHeader: 'hang',
},
};
await next();
};
web 接口请求统一增加 header
requestHeader
后,接口又重新正常请求。
下一篇文章请小伙伴们移步至 eggjs 实现服务端请求教程文档-3