Koajs
example
const Koa = require('koa');const app = new Koa();app.use(async ctx => {ctx.body = 'Hello World';});app.listen(9800);
express vs koa
1. express 中间件是异步回调,koa2 原生支持 async/await
Introduction
Koa is a new web framework designed by the team behind Express, which aims to be a smaller, more expressive, and more robust foundation for web applications and APIs.
Context
A Koa Context encapsulates node's request and response objects into a single object which provides many helpful methods for writing web applications and APIs.
app.use(async ctx => {ctx; // is the Contextctx.request; // is a Koa Requestctx.response; // is a Koa Response});
ctx.req
Node's request object.
ctx.res
Node's response object.Bypassing Koa's response handling is not supported. Avoid using the following node properties:res.statusCoderes.writeHead()res.write()res.end()
ctx.request
A Koa Request object.ctx.request.url = ctx.url// '/hello/:name'ctx.params.name// ?user=jim&age=18ctx.request.query = ctx.query//==> obj {age:"18"user:"jim"}ctx.request.querystring = ctx.querystring//===> str "user=jim&age=18"
ctx.response
A Koa Response object.ctx.response.type = ctx.type
ctx.state
The recommended namespace for passing information through middleware and to your frontend views.ctx.state.user = await User.find(id);
koa middleware
app.use(async (ctx, next) => {console.log(`${ctx.request.method} ${ctx.request.url}`); // 打印URLawait next(); // 调用下一个middleware});app.use(async (ctx, next) => {const start = new Date().getTime(); // 当前时间await next(); // 调用下一个middlewareconst ms = new Date().getTime() - start; // 耗费时间console.log(`Time: ${ms}ms`); // 打印耗费时间});app.use(async (ctx, next) => {await next();ctx.response.type = 'text/html';ctx.response.body = '<h1>Hello, koa2!</h1>';});
middleware的顺序很重要,也就是调用app.use()的顺序决定了middleware的顺序。
如果一个middleware没有调用await next(),会怎么办?答案是后续的middleware将不再执行了。这种情况也很常见,例如,一个检测用户权限的middleware可以决定是否继续处理请求,还是直接返回403错误:
app.use(async (ctx, next) =>{if(await checkUserPermission(ctx)){await next();} else{ctx.responst.status = 403}})
example 中间件开发
一个打印日志的中间件
// ./middleware/logger-async.jsfunction log(ctx){console.log(ctx.method, ctx.header.host + ctx.url)}module.exports = function(){return async function(ctx, next){log(ctx);await next()}}
usage
const Koa = require('koa'); // koa v2const loggerAsync = require('./middleware/logger-async');const app = new Koa();app.use(loggerAsync());app.use((ctx) => {ctx.body = 'hello world!';});
koa2使用cookie
koa提供了从上下文直接读取,写入cookie的方法
ctx.cookies.get(name, [options])读取上下文请求中的cookiectx,cookies.set(name, value, [options])在上下文中写入cookiekoa2中操作的cookies是使用了npm的cookies模块,源码在:https://github.com/pillarjs/cookies,所以在读写cookie的使用参数与该模块的使用一致。
code example
const Koa = require('koa');const app = new Koa();app.use(async(ctx) => {if(ctx.url === '/index') {ctx.cookies.set('cid','hello world',{domian: 'localhost', // 写cookie所在的域名path: '/index', // 写cookie所在的路径maxAge: 10*60*1000, // cookie有效时长expires: new Date('2017-02-15'), // cookie失效时间httpOnly: false, // 是否只用于http请求获取overwrite: false // 是否允许重写})ctx.body = 'cookie is ok';} else {ctx.body = 'hello world';}});app.listen(3000, () => {console.log('[demo] cookie is starting at port 3000');});
koa-router
const Koa = require('koa');// 注意require('koa-router')返回的是函数:const router = require('koa-router')();const app = new Koa();// log request URL:app.use(async (ctx, next) => {console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);await next();});// add url-route:router.get('/hello/:name', async (ctx, next) => {var name = ctx.params.name;ctx.response.body = `<h1>Hello, ${name}!</h1>`;});router.get('/', async (ctx, next) => {ctx.response.body = '<h1>Index</h1>';});// add router middleware:app.use(router.routes());app.listen(3000);console.log('app started at port 3000...');
处理post请求
router.post('/path', async fn)用post请求处理URL时,我们会遇到一个问题:post请求通常会发送一个表单,或者JSON,它作为request的body发送,但无论是Node.js提供的原始request对象,还是koa提供的request对象,都不提供解析request的body的功能!所以,我们又需要引入另一个middleware来解析原始request请求,然后,把解析后的参数,绑定到ctx.request.body中。koa-bodyparser 就是用来干这个活的。app.use(bodyParser());由于middleware的顺序很重要,这个koa-bodyparser必须在router之前被注册到app对象上。