koa初见

image

今天学一下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');
image

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

image.png

image

所有的请求经过一个中间件的时候都会执行两次,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 = '<h1>首页</h1>'
    } else if (ctx.request.url == '/about') {
        ctx.body = '<h1>关于</h1>'
    } else {
        ctx.body = '<h1>404 not found</h1>'
    }
})
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 = '<h1>首页</h1>'
})
router.get('/about',(ctx,next)=>{
  ctx.response.body = '<h1>关于</h1>'
})

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 = '<p>您要看的页面出错咯</p>';
        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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268