# koa2概览篇
30 秒速记
Koa=Express原班人马做的极简框架:核心只有ctx+ 异步中间件,路由、静态资源、body解析都靠插件ctx一次请求一份,ctx.body/ctx.status/ctx.path是ctx.request/ctx.response的代理- 中间件
await next()形成洋葱模型:进去一层层往里,出来一层层往外 - 不调
next()链条就断在这层;没人设ctx.body就是404 Not Found - 错误处理放最外层
try { await next() } catch,再配app.on('error')打日志
Koa 是一个只提供请求上下文和中间件机制的轻量框架,其他能力都靠中间件拼出来。 它最大的特点是洋葱模型:每个中间件 await next() 之前是「进去」,之后是「出来」,所以一个中间件就能同时拿到请求开始和结束的时机,记耗时、统一捕错特别顺手。ctx 把 Node 原生的 req / res 包了一层,常用的 ctx.body、ctx.status 直接用就行。跟 Express 比,它不内置路由,要装 @koa/router,body 解析要装 koa-bodyparser。
const Koa = require('koa')
const app = new Koa()
app.use(async (ctx, next) => { // 最外层:计时 + 统一捕错
const start = Date.now()
try { await next() } catch (err) {
ctx.status = err.status || 500
ctx.body = { message: err.message }
}
console.log(ctx.method, ctx.path, Date.now() - start + 'ms')
})
app.use(ctx => { ctx.body = 'hello' }) // 没设 body 就会返回 404 Not Found
app.listen(3000)
Koa 就是一种简单好用的 Web 框架。它的特点是优雅、简洁、表达力强、自由度高
# 一、基本用法
1.1 架设 HTTP 服务
只要三行代码,就可以用
Koa架设一个HTTP服务。
const Koa = require('koa');
const app = new Koa();
app.listen(3000);
打开浏览器,访问
http://127.0.0.1:3000。你会看到页面显示"Not Found",表示没有发现任何内容。这是因为我们并没有告诉Koa应该显示什么内容
1.2 Context 对象
Koa提供一个Context对象,表示一次对话的上下文(包括HTTP请求和HTTP回复)。通过加工这个对象,就可以控制返回给用户的内容
Context.response.body属性就是发送给用户的内容
const Koa = require("koa");
const app = new Koa();
app.use(ctx => { //处理请求的中间件
ctx.response.body = "hello world";
}).listen(3000);
上面代码中,
main函数用来设置ctx.response.body。然后,使用app.use方法加载main函数
ctx.response代表HTTP Response。同样地,ctx.request代表HTTP Request
1.3 HTTP Response 的类型
Koa默认的返回类型是text/plain,如果想返回其他类型的内容,可以先用ctx.request.accepts判断一下,客户端希望接受什么数据(根据HTTP Request的Accept字段),然后使用ctx.response.type指定返回类型
const Koa = require("koa");
const app = new Koa();
app.use(ctx => {
if (ctx.request.accepts('xml')) {
ctx.response.type = 'xml';
ctx.response.body = '<data>Hello World</data>';
} else if (ctx.request.accepts('json')) {
ctx.response.type = 'json';
ctx.response.body = { data: 'Hello World' };
} else if (ctx.request.accepts('html')) {
ctx.response.type = 'html';
ctx.response.body = '<p>Hello World</p>';
} else {
ctx.response.type = 'text';
ctx.response.body = 'Hello World';
}
}).listen(3000);
1.4 网页模板
实际开发中,返回给用户的网页往往都写成模板文件。我们可以让 Koa 先读取模板文件,然后将这个模板返回给用户
const Koa = require("koa");
const app = new Koa();
const fs = require('fs');
app.use(ctx => {
ctx.response.type = 'html';
ctx.response.body = fs.createReadStream('./demos/template.html');
}).listen(3000);
# 二、路由
网站一般都有多个页面。通过
ctx.request.path可以获取用户请求的路径,由此实现简单的路由
const Koa = require("koa");
const app = new Koa();
const fs = require('fs');
app.use(ctx => {
if (ctx.request.path !== '/') {
ctx.response.type = 'html';
ctx.response.body = '<a href="/">Index Page1</a>';
} else {
ctx.response.body = 'Hello World';
}
}).listen(3000);
2.2 koa-route 模块
原生路由用起来不太方便,我们可以使用封装好的
koa-route模块
const Koa = require("koa");
const app = new Koa();
const fs = require('fs');
const route = require('koa-route');
const main = route.get("/", ctx => {
ctx.response.type = 'html';
ctx.response.body = '<a href="/">Index Page1</a>';
})
const about = route.get("/about", ctx => {
ctx.response.body = 'Hello World';
})
app.use(main);
app.use(about);
app.listen(3000);
2.3 静态资源
如果网站提供静态资源(图片、字体、样式表、脚本…),为它们一个个写路由就很麻烦,也没必要。
koa-static模块封装了这部分的请求
// 访问 http://localhost:3000/test.json
const Koa = require("koa");
const app = new Koa();
const path = require('path');
const serve = require('koa-static');
const main = serve(path.join(__dirname, "../public/"));
app.use(main);
app.listen(3000);
2.4 重定向
有些场合,服务器需要重定向(
redirect)访问请求。比如,用户登陆以后,将他重定向到登陆前的页面。ctx.response.redirect()方法可以发出一个302跳转,将用户导向另一个路由
const Koa = require("koa");
const app = new Koa();
const route = require("koa-route");
const redirect = route.get("/redirect", ctx => {
ctx.response.redirect('/');
ctx.response.body = '<a href="/">Index Page</a>';
})
const main = route.get("/", ctx => {
ctx.