入门
Hello World
Koa 需要 node v7.6.0 或更高版本来支持ES2015、异步方法,你可以安装自己支持的 node
版本
-
安装依赖
$ mkdir myapp # 创建目录 $ cd myapp # 进入目录 $ nvm install 7 $ npm init -y # 初始化一个配置 $ npm install koa # 安装依赖
-
入口文件
index.js
添加代码:const Koa = require('koa'); const app = new Koa(); app.use(async ctx => { ctx.body = 'Hello World'; }); app.listen(3000);
-
使用以下命令运行应用程序
$ node index.js
级联
const Koa = require('koa');
const app = new Koa();
// X-Response-Time x 响应时间
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
// 记录器 logger
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
console.log(
`${ctx.method} ${ctx.url} - ${ms}`
);
});
// 响应 response
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
配置
:- | :- |
---|---|
app.env |
默认为 NODE_ENV 或 development
|
app.keys |
签名 cookie 密钥数组 |
app.proxy |
何时信任真正的代理头字段 |
app.subdomainOffset |
要忽略的 .subdomains 的偏移量,默认为 2
|
app.proxyIpHeader |
代理 ip 头,默认为 X-Forwarded-For
|
app.maxIpsCount |
从代理 ip 头读取的最大 ips 数,默认为 0 (表示无穷大) |
错误处理
app.on('error', (err, ctx) => {
log.error('server error', err, ctx)
});
默认情况下 Koa
会将所有错误信息输出到 stderr
, 除非 app.silent
是 true
。当 err.status
是 404
或者 err.expose
时,默认错误处理程序也不会输出错误
Context 示例
app.use(async ctx => {
ctx; // 这是上下文 Context
ctx.request; // 这是 koa Request
ctx.response; // 这是 koa Response
});
app.listen(...)
const Koa = require('koa');
const app = new Koa();
app.listen(3000);
app.listen(...)
实际上是以下代码的语法糖:
const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
这意味着您可以同时支持 HTTPS
和 HTTPS
,或者在 多个端口
监听同一个应用
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);
ctx.throw 示例
ctx.throw(400);
ctx.throw(400, 'name required');
ctx.throw(400, 'name required', { user: user });
this.throw('name required', 400)
等价于
const err = new Error('name required');
err.status = 400;
err.expose = true;
throw err;
ctx.assert 示例
ctx.assert(
ctx.state.user,
401,
'User not found. Please login!'
);
Context(上下文) API
:- | :- |
---|---|
ctx.req |
Node 的 request 对象 |
ctx.res |
Node 的 response 对象 |
ctx.request |
Koa 的 Request 对象 |
ctx.response |
Koa 的 Response 对象 |
ctx.state |
推荐的命名空间,用于通过中间件传递信息到前端视图 |
ctx.app |
应用实例引用 |
ctx.app.emit |
发出由第一个参数定义的类型的事件 |
ctx.cookies.get(name, [options]) |
获得 cookie 中名为 name 的值 |
ctx.cookies.set(name, value, [options]) |
设置 cookie 中名为 name 的值 |
ctx.throw([status], [msg], [properties]) |
抛出包含 .status 属性的错误,默认为 500
|
ctx.assert(value, [status], [msg], [properties]) |
当 !value 时, Helper 方法抛出一个类似 .throw() 的错误 |
ctx.respond |
避免使用 Koa 的内置响应处理功能,您可以直接赋值 this.repond = false
|
ctx.cookies.set 参数
:- | :- |
---|---|
maxAge |
表示从Date开始的毫秒数 now() 到期。 |
expires |
一个 Date 对象,指示 cookie 的到期日期(默认情况下在会话结束时到期) |
path |
表示 cookie 路径的字符串(默认为/ ) |
domain |
表示 cookie 的域的字符串(无默认值) |
secure |
一个布尔值,指示 cookie 是否只通过HTTPS发送(HTTP默认为false,HTTPS默认为true)。阅读有关此选项的更多信息 |
httpOnly |
一个布尔值,指示cookie是否只通过HTTP(S)发送,而不可用于客户端 JavaScript(默认为true) |
sameSite |
一个布尔值或字符串,指示cookie是否为“同一站点”cookie(默认为false)。这可以设置为“strict”、“lax”、“none”或true(映射为“strect”) |
signed |
一个布尔值,指示是否对cookie进行签名(默认为false)。如果这是真的,还将发送另一个附加了.sig后缀的同名cookie,其中一个27字节的url安全base64 SHA1值表示cookie name=cookie值相对于第一个Keygrip键的哈希值。此签名密钥用于在下次收到cookie时检测篡改 |
overwrite |
一个布尔值,指示是否覆盖以前设置的同名 cookie (默认为false)。如果为true,则在设置此Cookie时,将从set-Cookie标头中筛选出在同一请求期间设置的具有相同名称的所有Cookie(无论路径或域如何) |
请求(Request)
:- | :- |
---|---|
request.header |
请求头对象 |
request.header= |
设置请求头对象 |
request.headers |
请求头对象。等价于 request.header. |
request.headers= |
设置请求头对象。 等价于request.header=. |
request.method |
请求方法 |
request.method= |
设置请求方法, 在实现中间件时非常有用,比如 methodOverride() |
request.length |
以数字的形式返回 request 的内容长度(Content-Length),或者返回 undefined。 |
request.url |
获得请求url地址. |
request.url= |
设置请求地址,用于重写url地址时 |
request.originalUrl |
获取请求原始地址 |
request.origin |
获取URL原始地址, 包含 protocol 和 host |
request.href |
获取完整的请求URL, 包含 protocol, host 和 url |
request.path |
获取请求路径名 |
request.path= |
设置请求路径名并保留当前查询字符串 |
request.querystring |
获取查询参数字符串(url中?后面的部分),不包含? |
request.querystring= |
设置原始查询字符串 |
request.search |
获取查询参数字符串,包含? |
request.search= |
设置原始查询字符串 |
request.host |
获取 host (hostname:port)。 当 app.proxy 设置为 true 时,支持 X-Forwarded-Host |
request.hostname |
获取 hostname。当 app.proxy 设置为 true 时,支持 X-Forwarded-Host。 |
request.URL |
获取 WHATWG 解析的对象. |
request.type |
获取请求 Content-Type,不包含像 "charset" 这样的参数。 |
request.charset |
获取请求 charset,没有则返回 undefined
|
request.query |
将查询参数字符串进行解析并以对象的形式返回,如果没有查询参数字字符串则返回一个空对象 |
request.query= |
根据给定的对象设置查询参数字符串 |
request.fresh |
检查请求缓存是否 "fresh"(内容没有发生变化) |
request.stale |
与 req.fresh 相反 |
request.protocol |
返回请求协议,"https" 或者 "http" |
request.secure |
简化版 this.protocol == "https",用来检查请求是否通过 TLS 发送 |
request.ip |
请求远程地址,当 app.proxy 设置为 true 时,支持 X-Forwarded-Host |
request.ips |
当 X-Forwarded-For 存在并且 app.proxy 有效,将会返回一个有序(从 upstream 到 downstream)ip 数组 |
request.subdomains |
以数组形式返回子域名 |
request.is(types...) |
检查请求所包含的 "Content-Type" 是否为给定的 type 值 |
request.accepts(types) |
检查给定的类型 types(s) 是否可被接受,当为 true 时返回最佳匹配,否则返回 false |
request.acceptsEncodings(encodings) |
检查 encodings 是否可以被接受,当为 true 时返回最佳匹配,否则返回 false
|
request.acceptsCharsets(charsets) |
检查 charsets 是否可以被接受,如果为 true 则返回最佳匹配,否则返回 false
|
request.acceptsLanguages(langs) |
检查 langs 是否可以被接受,如果为 true 则返回最佳匹配,否则返回 false
|
request.idempotent |
检查请求是否为幂等(idempotent) |
request.socket |
返回请求的socket |
request.get(field) |
返回请求头 |
响应(Response)
:- | :- |
---|---|
response.header |
Response header 对象 |
response.headers |
Response header 对象。等价于 response.header. |
response.socket |
Request socket. |
response.status |
获取响应状态。 默认情况下,response.status设置为404,而不像node's res.statusCode默认为200。 |
response.status= |
通过数字设置响应状态 |
response.message |
获取响应状态消息。默认情况下, response.message关联response.status。 |
response.message= |
将响应状态消息设置为给定值。 |
response.length= |
将响应Content-Length设置为给定值。 |
response.length |
如果 Content-Length 作为数值存在,或者可以通过 ctx.body 来进行计算,则返回相应数值,否则返回 undefined。 |
response.body |
获取响应体。 |
response.body= |
设置响应体为如 string ,Buffer ,Stream ,Object|Array ,null
|
response.get(field) |
获取 response header 中字段值,field 不区分大小写 |
response.set(field, value) |
设置 response header 字段 field 的值为 value |
response.append(field, value) |
添加额外的字段field 的值为 val |
response.set(fields) |
使用对象同时设置 response header 中多个字段的值 |
response.remove(field) |
移除 response header 中字段 filed |
response.type |
获取 response Content-Type,不包含像"charset"这样的参数 |
response.type= |
通过 mime 类型的字符串或者文件扩展名设置 response Content-Type |
response.is(types...) |
跟 ctx.request.is() 非常类似。用来检查响应类型是否是所提供的类型之一 |
response.redirect(url, [alt]) |
执行 [302] 重定向到对应 url |
response.attachment([filename]) |
设置 "attachment" 的 Content-Disposition,用于给客户端发送信号来提示下载 |
response.headerSent |
检查 response header 是否已经发送,用于在发生错误时检查客户端是否被通知。 |
response.lastModified |
如果存在 Last-Modified,则以 Date 的形式返回。 |
response.lastModified= |
以 UTC 格式设置 Last-Modified。您可以使用 Date 或 date 字符串来进行设置。 |
response.etag= |
设置 包含 "s 的 ETag |
response.vary(field) |
不同于field. |
response.flushHeaders() |
刷新任何设置的响应头,并开始响应体 |
请求(Request)别名
以下访问器和别名与 Request 等价:
ctx.header
ctx.headers
ctx.method
ctx.method=
ctx.url
ctx.url=
ctx.originalUrl
ctx.origin
ctx.href
ctx.path
ctx.path=
ctx.query
ctx.query=
ctx.querystring
ctx.querystring=
ctx.host
ctx.hostname
ctx.fresh
ctx.stale
ctx.socket
ctx.protocol
ctx.secure
ctx.ip
ctx.ips
ctx.subdomains
ctx.is()
ctx.accepts()
ctx.acceptsEncodings()
ctx.acceptsCharsets()
ctx.acceptsLanguages()
ctx.get()
响应(Response)别名
以下访问器和别名与 Response 等价:
ctx.body
ctx.body=
ctx.status
ctx.status=
ctx.message
ctx.message=
ctx.length=
ctx.length
ctx.type=
ctx.type
ctx.headerSent
ctx.redirect()
ctx.attachment()
ctx.set()
ctx.append()
ctx.remove()
ctx.lastModified=
ctx.etag=
request.fresh 示例
// freshness 检查需要状态 20x 或 304
ctx.status = 200;
ctx.set('ETag', '123');
// 缓存正常
if (ctx.fresh) {
ctx.status = 304;
return;
}
// 缓存已过时
// 获取新数据
ctx.body = await db.find('something');
ctx.is 示例
// Content-Type: text/html; charset=utf-8
ctx.is('html'); // => 'html'
ctx.is('text/html'); // => 'text/html'
ctx.is('text/*', 'text/html');
// => 'text/html'
// 当 Content-Type 为 application/json 时
ctx.is('json', 'urlencoded'); // => 'json'
ctx.is('application/json');
// => 'application/json'
ctx.is('html', 'application/*');
// => 'application/json'
ctx.is('html'); // => false
ctx.accepts 示例
// 接受: text/*, application/json
ctx.accepts('html');
// => "html"
ctx.accepts('text/html');
// => "text/html"
ctx.accepts('json', 'text');
// => "json"
ctx.accepts('application/json');
// => "application/json"
request.acceptsCharsets 示例
// Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5
ctx.acceptsCharsets('utf-8', 'utf-7');
// => "utf-8"
ctx.acceptsCharsets(['utf-7', 'utf-8']);
// => "utf-8"
检查 charsets
是否可以被接受,如果为 true
则返回最佳匹配, 否则返回 false
response.set 示例
ctx.set({
'Etag': '1234',
'Last-Modified': date
});
使用对象同时设置 response header 中多个字段的值
response.type 示例
const ct = ctx.type;
// => "image/png"
获取 response Content-Type,不包含像"charset"这样的参数
基于Node.js平台的下一代web开发框架,包含Koa的API参考列表和一些示例入门,为开发人员分享快速参考备忘单。