eggjs 实现服务端请求教程文档-2

继续上一篇文章的学习,如果小伙伴们要回顾上一篇的内容,请点击这里 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 的数据。

feat-user-detail 分支

四、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 后,接口又重新正常请求。

feat-middleware 分支

下一篇文章请小伙伴们移步至 eggjs 实现服务端请求教程文档-3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值