今天学一下koa,之所以在express,koa,egg中选择koa,仅仅是因为我觉得koa的官网好看,看上去很简洁,就好像只要学了文档主要的几个对象就可以通吃了一样。
Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。
Koa 依赖 node v7.6.0 或 ES2015及更高版本和 async 方法支持.
一、安装
$ nvm install 7
让我们和koa的世界say个hi
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
[图片上传失败...(image-557293-1563610308704)]
二、 koa实例:app
app.listen(...):程序挂在的端口
app.use(function):将给定的中间件方法添加到此应用程序
app.keys= :设置签名的 Cookie 密钥。
app.context:app.context
错误处理:app.on('error', err => { log.error('server error', err) });
三、context
Koa Context 将 node 的 request 和 response 对象封装到单个对象中,表示一次请求的上下文,每个请求都将创建一个 Context,并在中间件中作为接收器引用,或者 ctx 标识符。
我们可以打印一下context对象
const Koa = require('koa');
ctx.req:Node 的 request 对象.
ctx.res:Node 的 response 对象.
ctx.request:koa 的 Request 对象.
ctx.response: koa 的 Response 对象.
ctx.state: 推荐的命名空间,用于通过中间件传递信息和你的前端视图。
ctx.state.user = await User.find(id);
ctx.app: 应用程序实例引用
ctx.cookies.get(name, [options]) :通过 options 获取 cookie name:
ctx.cookies.set(name, value, [options]) :通过 options 设置 cookie name 的 value :
ctx.throw([status], [msg], [properties])**: 抛出错误
因为ctx表示一个请求的上下文,所以当然它可以直接访问到request和response的属性
ctx的某些访问器和 Request 别名 和 Response 别名等效
ctx.header = request.header
ctx.headers = request.headers
ctx.method = request.method
...
ctx.body = response.body
ctx.status = response.status
ctx.message = response.message
四、Request对象
常用Request对象属性
request.header:请求标头对象
request.method:请求方法
request.length:返回以数字返回请求的 Content-Length,或 undefined
request.url:获取请求 URL.
request.originalUrl:获取请求原始URL。
request.origin:获取URL的来源,包括 protocol 和 host。
request.href:获取完整的请求URL,包括 protocol,host 和 url。
request.path:请求路径
request.querystring:设置原始查询字符串。
request.search:使用 ? 获取原始查询字符串。
request.host:获取当前主机(hostname:port)。当 app.proxy 是 true 时支持 X-Forwarded-Host,否则使用 Host。
request.hostname:存在时获取主机名。当 app.proxy 是 true 时支持 X-Forwarded-Host,否则使用 Host。
request.URL:获取 WHATWG 解析的 URL 对象。
request.type:获取请求 Content-Type 不含参数 "charset"。
request.charset:在存在时获取请求字符集,或者 undefined:
request.query:获取解析的查询字符串, 当没有查询字符串时,返回一个空对象。请注意,此 getter 不 支持嵌套解析。
request.fresh:检查请求缓存是否“新鲜”,也就是内容没有改变。此方法用于 If-None-Match / ETag, 和 If-Modified-Since 和 Last-Modified 之间的缓存协商。 在设置一个或多个这些响应头后应该引用它。
request.stale:与 request.fresh相反
request.protocol:返回请求协议,“https” 或 “http”。当 app.proxy 是 true 时支持 X-Forwarded-Proto
request.secure:通过 ctx.protocol == "https" 来检查请求是否通过 TLS 发出。
request.ip:请求远程地址。 当 app.proxy 是 true 时支持 X-Forwarded-Proto。
request.is(types...):检查传入请求是否包含 Content-Type 头字段, 并且包含任意的 mime type。 如果没有请求主体,返回 null,如果没有内容类型,或者匹配失败,则返回 false。 反之则返回匹配的 content-type。
五、Response对象
常用Response对象属性
response.header:响应标头对象。
response.socket:请求套接字。
response.status:获取响应状态
response.message:获取响应的状态消息.
response.body:获取响应主体。
response.get(field):不区分大小写获取响应标头字段值 field。
response.set(field, value):设置响应标头 field 到 value
response.redirect(url, [alt]):执行 [302] 重定向到 url.
六、常用中间件
koa中间件 Middleware
koa-logger :开发样式记录器
koa-basic-auth :用户身份认证
koa-router:koa路由
koa-body:解析http请求正文
koa-compose :将多个中间件组合成一个
koa-session:基于cookie的会话中间件,也支持外部会话存储、
koa-csrf :防止跨域攻击的
koa-views:使用任何模板引擎渲染视图
koa-static:静态文件服务中间件
查看更多 Middleware
所有的请求经过一个中间件的时候都会执行两次,Koa 的模型可以非常方便的实现后置处理逻辑
七、常见简单用法
7.1网页模板
const fs = require('fs');
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
ctx.response.type = 'html';
ctx.response.body = fs.createReadStream('./index.html');
};
app.use(main);
app.listen(3000);
7.2 原生路由
const Koa = require('koa')
const app = new Koa()
app.use((ctx, next) => {
//通过ctx.request.url获取用户请求路径
if (ctx.request.url == '/') {
ctx.body = '首页
'
} else if (ctx.request.url == '/about') {
ctx.body = '关于
'
} else {
ctx.body = '404 not found
'
}
})
app.listen(3000)
7.3 koa-router 模块路由
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
app.use(router.routes());
//.get就是发送的get请求
router.get('/',(ctx,next)=>{
ctx.response.body = '首页
'
})
router.get('/about',(ctx,next)=>{
ctx.response.body = '关于
'
})
app.listen(3000)
7.4 静态资源
const Koa = require('koa');
const app = new Koa();
const path = require('path');
const serve = require('koa-static');
const main = serve(path.join(__dirname));
app.use(main);
app.listen(3000);
// http://localhost:3000/index.html
7.5 重定向跳转
const Koa = require('koa');
const Router = require('koa-router');
const app = new Koa();
const router = new Router()
app.use(router.routes()).use(router.allowedMethods());
router.get('/about',(ctx,next)=>{
ctx.response.redirect('/');
})
router.get('/',(ctx,next)=>{
ctx.body = '首页';
})
app.listen(3000);
7.6 500错误
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
ctx.throw(500);
};
app.use(main);
app.listen(3000);
7.6 404错误
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
ctx.response.status = 404;
ctx.response.body = 'Page Not Found';
// 以上与ctx.throw(404)效果相同;
};
app.use(main);
app.listen(3000);
7.7 error事件监听
const Koa = require('koa');
const app = new Koa();
const main = ctx => {
ctx.throw(500);
};
app.on('error', (err, ctx) => {
console.error('server error', err);//err是错误源头
});
app.use(main);
app.listen(3000);
7.8 try...catch处理error
如果错误被try...catch捕获,就不会触发error事件。这时,必须调用ctx.app.emit(),手动释放error事件,才能让监听函数生效。
const Koa = require('koa');
const app = new Koa();
const handler = async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.response.status = err.statusCode || err.status || 500;
ctx.response.type = 'html';
ctx.response.body = '您要看的页面出错咯
';
ctx.app.emit('error', err, ctx);//释放error事件
}
};
const main = ctx => {
ctx.throw(500);
};
app.on('error', function (err) {
//释放error事件后这里的监听函数才可生效
console.log('错误', err.message);
console.log(err);
});
app.use(handler);
app.use(main);
app.listen(3000);
7.9 cookie
const Koa = require('koa');
const app = new Koa();
const main = function(ctx) {
const n = 'luckfine'
ctx.cookies.set('user', n);
ctx.response.body = 'user is :' + n;
setTimeout(() => {
console.log(ctx.cookies.get('user'))
},5000)
}
app.use(main);
app.listen(3000);
7.10 上传
const serve = require('koa-static');
const koaBody = require('koa-body');
const Koa = require('koa');
const fs = require('fs');
const app = new Koa();
const os = require('os');
const path = require('path');
app.use(koaBody({ multipart: true }));
// serve files from ./public
app.use(serve(path.join(__dirname, '/public')));
app.use(async function(ctx, next) {
// ignore non-POSTs
if ('POST' != ctx.method) return await next();
const file = ctx.request.files.file;
const reader = fs.createReadStream(file.path);
const stream = fs.createWriteStream(path.join(os.tmpdir(), Math.random().toString()));
reader.pipe(stream);
console.log('uploading %s -> %s', file.name, stream.path);
ctx.redirect('/');
});
app.listen(3000);