前言
NodeJS这东西是不是学过了,之后感觉又像没学到什么东西???
我最近翻到了之前学习node的笔记,又结合了一些大佬的经验,这里把node系列相关的东西串联一下,分享给小伙伴们,顺便我自己也加深一下印象。
总共分为七篇
node打怪升级系列 - 手写中间件篇
本文重点记录下中间件篇
里的装备
正文开始
中间件是什么?
连接顶层应用和底层应用,在之间做一系列事情的能力
比如:底层是山里的泉水,顶层是2块一瓶的农夫山泉饮用水
中间件就是中间那些取水、净化、灭菌之类的那些工序
实现一个中间件
1,自己写一个允许跨域的中间件
下面是一个允许接口跨域
的中间件
js
const Koa = require('koa');
const Router = require('koa-router');
// const cors = require('koa2-cors')
const app = new Koa();
const router = new Router();
// app.use(cors())
app.use(async (ctx, next) => {
// cors
ctx.set('Access-Control-Allow-Origin', "*"); // 访问源
ctx.set('Access-Control-Allow-Headers', "Content-Type, Content-Length, Authorization, Accept"); // 客户端头有哪些
ctx.set('Access-Control-Allow-Methods', "PUT, POST, GET, DELETE, OPTIONS"); // 允许客户端请求用什么方法
// Access-Control-Allow-Credentails // true -> cookies // 允许使用cookie
// Access-Control-Max-Age // option 预检的存活时间
// Access-Control-Expose-Headers // 允许服务端返回的头信息
ctx.set('Content-Type', "application/json;charset=utf-8");
if (ctx.request.method.toLowerCase() === 'options') {
ctx.state = 200;
} else {
await next();
}
})
router.get('/api', (ctx, next) => {
ctx.type = "application/json"
ctx.body = { data: "hello, api" }
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3008, () => {
console.log('server is listening in 3008');
})
其实和Koa自带的koa2-cors
差不多,只不过koa2-cors
逻辑更详细点
koa2-cors的使用方法
js
const cors = require('koa2-cors')
app.use(cors())
顺便提一下,中间件的使用是用app.use(中间件)
use这里主要是对中间件进行收集放到middleware
里进行逻辑处理
感兴趣的可以看看洋葱模型篇 的 app.use收集函数到中间件
2,对比下koa2-cors
的源码
首先,找到源码的位置
下面我们看一下koa2-cors
的源码
通过上图可以看到其实koa2-cors
是导出了一个函数
,返回值是一个cors函数
而我们使用app.use(cors())
后,其实是把cors函数
放入了middleware
进行编排
cors函数的主要逻辑
js
async function cors(ctx, next) {
let origin;
origin = options.origin || ctx.get('Origin') || '*';
ctx.set('Access-Control-Allow-Origin', origin);
if (ctx.method === 'OPTIONS') {
// Preflight Request
if (!ctx.get('Access-Control-Request-Method')) {
return await next();
}
// Access-Control-Max-Age
if (options.maxAge) {
ctx.set('Access-Control-Max-Age', String(options.maxAge));
}
// Access-Control-Allow-Credentials
if (options.credentials === true) {
// When used as part of a response to a preflight request,
// this indicates whether or not the actual request can be made using credentials.
ctx.set('Access-Control-Allow-Credentials', 'true');
}
// Access-Control-Allow-Methods
if (options.allowMethods) {
ctx.set('Access-Control-Allow-Methods', options.allowMethods.join(','));
}
// Access-Control-Allow-Headers
if (options.allowHeaders) {
ctx.set('Access-Control-Allow-Headers', options.allowHeaders.join(','));
} else {
ctx.set('Access-Control-Allow-Headers', ctx.get('Access-Control-Request-Headers'));
}
ctx.status = 204; // No Content
} else {
try {
await next();
} catch (err) {
throw err;
}
}
};
代码也很简单
总的来说就是 ctx.method === 'OPTIONS'
的时候进行ctx.set('Access-Control-Allow-xxx)
解决跨域三件套
反之走await next();
进入下一个流程中。
然后,就没啦~~~ 是不是感觉中间件也没啥高大上
的~~~
完结
这篇文章我尽力把我的笔记和想法放到这了,希望对小伙伴有帮助。
欢迎转载,但请注明来源。
最后,希望小伙伴们给我个免费的点赞,祝大家心想事成,平安喜乐。