(1)使用
基本用法:
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.response.type = 'html';
ctx.response.body =
fs.createReadStream('./view/include/test.html');
});
配置路由:
if(ctx.request.path === '/') {
ctx.response.type = 'html';
ctx.response.body = '<div>根目录</div>';
}else {
ctx.response.body = '哈哈哈,随机路径';
}
使用koa-router模块:
const Koa = require('koa');
const route = require('koa-route');
const app = new Koa();
var main = ctx => {
ctx.response.type = 'html';
ctx.response.body = '<h1>about<h1>';
}
app.use(route.get('/about'), main);
静态资源: // 直接访问浏览器js代码 可查看
const serve = require('koa-static');
const app = new Koa();
const _static = serve(path.join(__dirname));
app.use(_static);
重定向:
const redirect = ctx => {
ctx.response.redirect('/');
};
app.use(route.get('/redirect', redirect));
抛错:
ctx.throw(500) Internal Service Error
ctx.throw(404) Not Found
// 相当于:
ctx.response.status = 404;
ctx.response.body = 'Not Found';
// error事件监听:
const main = ctx => {
ctx.throw(500);
};
app.on('error',
(err, ctx) => console.error('server error', err););
throw错误能被error事件捕获,但是try…catch中的错会在catch中处理,必须调用
ctx.app.emit(‘error’, err, ctx);才能触发error事件。
(2)中间件
①同步中间件
const one = (ctx, next) => {
console.log('>> one');
next();
console.log('<< one');
}
const two = (ctx, next) => {
console.log('>> two');
next();
console.log('<< two');
}
const three = (ctx, next) => {
console.log('>> three');
next();
console.log('<< three');
}
app.use(one);
app.use(two);
app.use(three);
打印:
>> one
>> two
>> three
<< three
<< two
<< one
②异步中间件
const fs = require('fs.promised'); // promise读文件
const main = async function (ctx, next) {
ctx.response.body = await fs.readFile('./demos/template.html', 'utf8');
};
③中间件合成
const middlewares = compose([logger, main]);
app.use(middlewares);
④中间件错误捕获
const handler = async (ctx, next) => {
try {
await next(); // 执行下一个中间件 监听出错
} catch (err) {
ctx.response.status = err.statusCode || err.status || 500;
ctx.response.body = {
message: err.message // 打印错误信息
};
}};
const main = ctx => {
ctx.throw(500);
};
app.use(handler);
app.use(main);
⑤WebApp
1)Cookie
app.use(async ctx => {
const n = Number(ctx.cookies.get('view') || 0) + 1;
ctx.cookies.set('view', n);
ctx.response.body = '<h1>'+ n +'views</h1>'
});
ctx.cookies.set(name, value, [options])
通过 options 设置 cookie name 的 value :
maxAge 一个数字表示从 Date.now() 得到的毫秒数
signed cookie 签名值
expires cookie 过期的 Date
path cookie 路径, 默认是’/’
domain cookie 域名
secure 安全 cookie
httpOnly 服务器可访问 cookie, 默认是 true
overwrite 一个布尔值,表示是否覆盖以前设置的同名的 cookie (默认是 false). 如果是 true, 在同一个请求中设置相同名称的所有 Cookie(不管路径或域)是否在设置此Cookie 时从 Set-Cookie 标头中过滤掉。
2)表单
const koaBody = require('koa-body');
const main = async function(ctx) {
const body = ctx.request.body;
if (!body.name) ctx.throw(400, '.name required');
ctx.body = { name: body.name };};
app.use(koaBody());
3)文件上传
const os = require('os');
const path = require('path');
const koaBody = require('koa-body');
const main = async function(ctx) {
const tmpdir = os.tmpdir();
const filePaths = [];
const files = ctx.request.body.files || {};
for (let key in files) {
const file = files[key];
const filePath = path.join(tmpdir, file.name);
const reader = fs.createReadStream(file.path);
const writer = fs.createWriteStream(filePath);
reader.pipe(writer);
filePaths.push(filePath);
}
ctx.body = filePaths;};
app.use(koaBody({ multipart: true }));
(3)http源码
const http = require('http');
const https = require('https');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
https.createServer(app.callback()).listen(3001);
(4)调数据库
app.context.db = db();
app.use(async ctx => {
console.log(ctx.db);
});
(5)contex
ctx.type 和 ctx.length 委托给 response 对象,ctx.path 和 ctx.method 委托给 request。
node的response和request对象: ctx.res ctx.req
(6)缓存检查
request.fresh
检查请求缓存是否“新鲜”,也就是内容没有改变。此方法用于 If-None-Match / ETag, 和 If-Modified-Since 和 Last-Modified 之间的缓存协商。 在设置一个或多个这些响应头后应该引用它。
// 新鲜度检查需要状态20x或304
ctx.status = 200;
ctx.set('ETag', '123');
// 缓存是好的
if (ctx.fresh) {
ctx.status = 304;
return;
}
// 缓存是陈旧的// 获取新数据
ctx.body = await db.find('something');
(7) ctx.accepts()
switch (ctx.accepts('json', 'html', 'text')) {
case 'json': break;
case 'html': break;
case 'text': break;
default: ctx.throw(406, 'json, html, or text only');
}
(8)ctx.acceptsEncodings(‘gzip’, ‘deflate’, ‘identity’);
(9)响应头部
ctx.set('Cache-Control', 'no-cache');
ctx.set({
'Etag': '1234',
'Last-Modified': date
});
(10)if (!ctx.response.is(‘html’)) return;
(11)
ctx.response.etag =
crypto.createHash('md5').update(ctx.body).digest('hex');