本文属于“前端solo”系列文章第七篇
「导语」:本文主要引导你实现接口功能(测试接口),并讲述egg.js中的 Router 和 Controller 。
因为热身项目采用的是新手视角,所以我就渐进式的写博客,刚开始学习编程的时候,也经常写测试代码去了解要学习的知识点,如果你从来没有自己写过web Api接口,那么请跟随我的脚步...
还记得我们项目启动后在浏览器输入地址http://127.0.0.1:7001/
的画面吗? 空荡荡的页面上冷不丁写着hi,egg
几个小字,不仔细看差点以为是出bug白屏了,这几个小字从哪里来的?
不禁想起个熟悉的面试题:
❝Q:从输入url到页面加载完成,中间发生了什么?
A:1. 域名解析后拿到ip地址
❞
根据ip地址找到服务器后浏览器跟服务器建立tcp连接
浏览器发送http请求
服务器处理请求返回相关资源
关闭tcp连接后浏览器解析资源渲染页面
借助前端开发的经验,我们知道已经完成了前三步,发送了一个Http请求到服务器了,请求的信息在浏览器控制台中可以轻易得到,另外我们也能看到返回结果就是hi,egg。
现在咱们重点关注第四步,服务器是怎么处理的。
请求首先要经过路由,才能被送到特定的业务处理器,如果你熟悉MVC,再联想到Vue中路由的功能,你就很容易理解egg中的Router(路由)的作用。官方说Router 主要用来描述请求 URL 和具体承担执行动作的 Controller 的对应关系。土话说就是我们在egg的router中可以根据请求地址和请求方式去找对应的Controller处理请求。
结合hi,egg这个请求的路由代码来看,意思是说当我们用「get」方式请求路径 「http://127.0.0.1:7001/」 的时候,把请求交给controller中HomeController的index方法去处理。
'use strict';
module.exports = app => {
const { router, controller } = app;
router.get('/', controller.home.index);
};
看一下app的controller文件夹下的home.js
//home.js
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller {
async index() {
const { ctx } = this; ctx.body = 'hi, egg'; } } module.exports = HomeController;
看到熟悉的hi,egg字符串,修改下改成hi,xiaer,再刷新下浏览器果然显示的文字变成了hi,xiaer,虽然我们还没讲ctx
和ctx.body
是什么东西,但是隐约可以猜到接口的返回结果可能就是在这里处理好的。
那么Controller
到底做啥的?我们翻一下官方文档[1]
哇,很少看到这么详细的中文文档了,真是修福报呀!(滑稽)上面说的很明白了,Controller 负责解析用户的输入,处理后返回相应的结果。完整读完官方文档中关于Controller的部分,大致可以得到如下总结:
既然凭借router和controller就可以处理http请求并返回结果,那么我们先写几个弱智的测试接口加深一下印象,同时尝试一些官方文档中提到的router和controller的用法。
先来一个get请求方式,url传参的接口
// app/router.js 中
'use strict';
/**
* @param {Egg.Application} app - egg application */ module.exports = app => { const { router, controller } = app; router.get('/', controller.home.index); //接口测试 get方法 router.get('/test/get', controller.home.testGet); };
// app/controller/home.js中
'use strict';
const Controller = require('egg').Controller;
class HomeController extends Controller { async index() { const { ctx } = this; ctx.body = 'hi, egg'; }; //测试接口 /test/get async testGet() { const { ctx } = this; const query = this.ctx.query; ctx.body = `hi,${query.name||'小可爱'}, 你get到我了`; }; } module.exports = HomeController;
在浏览器输入地址,并添加参数name后可得到如下请求结果:
啊,好棒棒的接口!
post请求方式 请求参数:{id:1}
// app/router.js 中
router.post('/test/post', controller.home.testPost);
// app/controller/home.js中 新增方法testPost
//测试接口 /test/post
async testPost() {
const { ctx } = this;
const req = ctx.request.body;
ctx.body = { code: 200, message: "请求成功", data: "你请求的参数是" + JSON.stringify(req) }; };
神马?十动然拒?十分感动然后拒绝了我们的接口请求?看报错信息是invalid csrf token。不要惊慌,一切都在预料之内,这是因为egg的安全策略[2]导致的,框架内置了 egg-security插件并开启了CSRF防御功能,我们先临时在项目的config文件夹中config.default.js中关闭一下该功能即可
// config/config.default.js
'use strict';
/**
* @param {Egg.EggAppInfo} appInfo app info
*/
module.exports = appInfo => { const config = exports = { security: { csrf: { enable: false }, } }; return { ...config, }; };
然后我们再次请求,看看结果: 多么熟悉的返回啊,虽然目前一切是假的。
下一期将讲述:第一个API接口(下)
个人公众号,爱关注不关注把,公司项目来活了,设计图都出来了,以后更新稍慢一些,但绝对不会停更。还是利用工作时间写,下班了需要陪伴家人,如果年轻的时候不好好的陪伴家人,以后中年时期为整个家庭奋斗的时候更没时间陪,人呐,总是看不透彻,大概是不好意思承认自己只是个普通人吧。我不是说普通人就可以不努力不上进,提高效率才是关键!
egg-Controller文档: https://eggjs.org/zh-cn/basics/controller.html
[2]egg安全策略: https://eggjs.org/zh-cn/core/security.html#web-安全概念