准备工作
新建自己的 kaimo-koa 文件夹,结构如下:
- lib
application.js
:创建应用context.js
:上下文request.js
:koa 中自己实现的 request 的对象response.js
:koa 中自己实现的 response 的对象
package.json
:里面需要注意 main 字段,我们需要将lib/application.js
作为入口
{
"name": "kaimo-koa",
"version": "1.0.0",
"description": "",
"main": "lib/application.js",
"directories": {
"lib": "lib"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
ctx 是什么东西?
ctx 中整合了 request 和 response,req 以及 res
- koa 自己实现的 request 和 response
- http 原生的 req 以及 res
ctx.request.req.url
跟 ctx.req.url
是等价的
ctx.path
就是去 ctx.request.path
上取的,ctx.request
内部使用了 url 模块进行解析
代码实现基本的逻辑以及属性的扩展
application.js
:创建应用
const EventEmitter = require("events");
const http = require("http");
const context = require("./context");
const request = require("./request");
const response = require("./response");
console.log("kaimo-koa---->");
class Application extends EventEmitter {
constructor() {
super();
// 防止多个实例共享 context request response 需要进行拷贝
this.context = Object.create(context);
this.request = Object.create(request);
this.response = Object.create(response);
}
use(callback) {
this.callback = callback;
}
// 创建一个上下文
createContext(req, res) {
// 每次请求都应该是一个全新的 context,需要拷贝
let ctx = Object.create(this.context);
// 上下文中有一个 request 对象,是自己封装的
ctx.request = Object.create(this.request);
// 上下文中还有一个 req 属性 指代的是原生的 req,自己封装的 request 对象上有 req 属性
ctx.req = ctx.request.req = req;
return ctx;
}
handleRequest(req, res) {
const ctx = this.createContext(req, res);
this.callback(ctx);
}
listen(...args) {
const server = http.createServer(this.handleRequest.bind(this));
server.listen(...args);
}
}
module.exports = Application;
request.js
:koa 中自己实现的 request 的对象,进行属性扩展
const url = require("url");
const request = {
// 属性访问器的方式 ctx.request.url 就会执行 url()
get url() {
// this 就是 ctx.request
return this.req.url;
},
get path() {
return url.parse(this.req.url).pathname;
},
get query() {
return url.parse(this.req.url).query;
}
// ... 可以自己添加其他的扩展属性
};
module.exports = request;
编写 demo.js
测试
const Koa = require("./kaimo-koa");
const app = new Koa();
app.use(async (ctx, next) => {
ctx.body = "Hello kaimo Koa";
console.log("url---->", ctx.request.url);
console.log("path---->", ctx.request.path);
console.log("query---->", ctx.request.query);
});
app.on("error", (err) => {
console.log(err);
});
app.listen(3000);
启动服务后访问 http://localhost:3000/kaimo?a=313
nodemon demo.js