本文记录koa 用法,及 源码中用到的三方库。 备忘。
目录
koa
delegates 简化嵌套对象访问
depd 漂亮的deprecate信息
statuses http code <--> message
accepts http headers解析
debug 控制调试日志
安装
npm i koa -s
ts的话再装2个 开发依赖, 方便跳转
npm i @types/node -d
npm i @types/koa -d
const animal = {
dog: {
name: '旺财',
talk() {
console.log('wang!');
}
},
}
animal.dog.name 可以访问嵌套对象中的属性。
能不能 animal.name 就直接访问了 animal.dog.name
能!, 用 https://github.com/tj/node-delegates
const delegate = require('delegates');
// animal 的定义, 不再重复
delegate(animal, 'dog')
.access('name')
.method('talk')
animal.talk(); // 输出 wang!
console.log(animal.name); // 输出 旺财
用法
.access('name')
animal.name = 'dog2'; // 即可以set
console.log(animal.name); // 又可以get
.getter('name')
console.log(animal.name); // 可以get
animal.name = 'dog2'; // 不可以!!! 实际上会设置了 animal 的name属性 而不是 dog.name
.setter('name')
console.log(animal.name); // 不可以!!!
animal.name = 'dog2'; // 相当于设置 dog.dog.name
.fluent('name')
animal.name('name') // 设置 animal.dog.name
console.log(animal.name()) // 获取 animal.dog.name
koa 的 context 就是借助了 delegate 来方便访问 嵌套的 request 和 response 对象
输出 deprecate 信息, 五颜六色的,蛮漂亮的
const deprecate = require('depd')('wjs');
deprecate('i am a deprecate info');
输出结果
cookie 是 服务器返回给客户端的一些 key-value 对
比如下面这个例子。 服务器返回 了 4个 key-value 对。 分别是
LastVisit 当前时间
k1 v1
k2 v2
k3 v3
客户端下次访问会携带上这些 key-value. 服务器存啥,客户端返回啥。
还可以指定这些key 的过期时间, 是否验证, 详细见下面的例子
const http = require('http');
const Cookies = require('cookies');
const moment = require('moment');
//cookies进行签名(加密)
var keys = ['keyboard cat'];
var server = http.createServer(function (req, res) {
if (req.url == '/favicon.ico')
return
//创建cookie对象
var cookies = new Cookies(req, res, { keys: keys })
// 获取cookie,new Cookies时设置了签名,获取时也要进行签名认证
var lastVisit = cookies.get('LastVisit', { signed: true });
// 设置cookie('键名','值','有效期')
const now = new Date().getTime();
cookies.set('LastVisit', now,{ signed: true });
cookies.set('k1', 'v1', { signed: true,maxAge:0 }); //永久有效
cookies.set('k3', 'v3', { signed: true,maxAge:-1 }); //删除cookie
cookies.set('k2', 'v2',{ signed: true,maxAge:60000*60*24*7 }); //单位毫秒,有效期为7天
if (!lastVisit) {
res.setHeader('Content-Type', 'text/plain;charset=utf8')
res.end('你好,你这是首次访问!')
} else {
console.log(cookies.get('k1', { signed: true })); // v1
console.log(cookies.get('k2', { signed: true })); // v2
console.log(cookies.get('k3', { signed: true })); // undefined 马上就被删了 所以没有传回来
res.setHeader('Content-Type', 'text/plain;charset=utf8')
res.write('当前时间 ' + moment(now).format("YYYY-MM-DD HH:mm:ss.SSS"));
res.end('\n上次时间 ' + moment(parseInt(lastVisit)).format("YYYY-MM-DD HH:mm:ss.SSS") + '.')
}
})
server.listen(3000, function () {
console.log('Visit us at http://127.0.0.1:3000/ !')
})
http code <--> message 相互转换
npm 周下载 1700多w, https://github.com/jshttp/statuses 204赞
很多人用, 却不给人家点个赞。
koa 用的是 "statuses": "^1.5.0" ,已经和最新的版本不兼容了
const status = require('statuses');
console.log(status[500]); // Internal Server Error
console.log(status["forbidden"]); // 403
最新版本 "statuses": "^2.0.0" 要这样
const status = require('statuses');
console.log(status.message[500]); // Internal Server Error
console.log(status.code["forbidden"]); // 403
// 调用 函数 返回 string 对应的 code
status('forbidden') // => 403
// 如果是 retry 的 code 返回 true, 否则返回 undefined
status.retry[501] // => undefined
status.retry[503] // => true
// 如果 code 期望 body 是 empty的 返回 true
status.empty[200] // => undefined
status.empty[204] // => true
status.empty[304] // => true
// 如果是重定向的code, 返回 true
status.redirect[200] // => undefined
status.redirect[301] // => true
status.message code --> messgae string
status.code messgae string --> code
确实要更直观些~~~~
负责处理http 捎带的 headers 信息
即 req.headers 中的信息
var accepts = require('accepts')
var http = require('http')
function app (req, res) {
var accept = accepts(req)
// 数组里的顺序是有意义的,出现在前面的将被优先选择
switch (accept.type(['json', 'html'])) {
case 'json':
res.setHeader('Content-Type', 'application/json')
res.write('{"hello":"world!"}')
break
case 'html':
res.setHeader('Content-Type', 'text/html')
res.write('hello, world!')
break
default:
// 指定了head 又不是json和html 的 就到这里
res.setHeader('Content-Type', 'text/plain')
res.write('hello, world!')
break
}
res.end()
}
http.createServer(app).listen(3000)
// 没指定 就采用 type() 数组第一个 即 json
curl http://localhost:3000
// json
curl -H'Accept: application/json' http://localhost:3000
// html
curl -H'Accept: text/html' http://localhost:3000
// 下面两个 accept.type(['json', 'html']) 找不到合适的,返回false
// 采用 default 分支
curl -H'Accept: text/plain' http://localhost:3000
curl -H'Accept: application/mathml+xml' http://localhost:3000
// err.js
const Debugger = require('debug');
const a = Debugger('worker:a');
const b = Debugger('worker:b');
a('debug info from a')
b('debug info from b')
DEBUG=worker:* node err.js 显示 worker下所有的日志
DEBUG=worker:a node err.js 只显示 woker:a 的日志
assert(name === 'wjs', 401, 'authentication failed')
如果name 不是 wjs, throw http-errors 异常,
err.status = 401
err.message = 'authentication failed'
err.expose = true
源码
var createError = require('http-errors')
function assert (value, status, msg, opts) {
if (value) return
throw createError(status, msg, opts)
}
var createError = require('http-errors')
createError(401, 'Please login to view this page.') // 状态码 错误消息