Koajs 备忘清单

NPM version Downloads Repo Dependents Github repo

基于 Node.js 平台的下一代 web 开发框架,包含 Koa 的 API 参考列表和一些示例

入门

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_ENVdevelopment
app.keys 签名 cookie 密钥数组
app.proxy 何时信任真正的代理头字段
app.subdomainOffset 要忽略的 .subdomains 的偏移量,默认为 2
app.proxyIpHeader 代理 ip 头,默认为 X-Forwarded-For
app.maxIpsCount 从代理 ip 头读取的最大 ips 数,默认为 0(表示无穷大)

app.callback()

:- :-
app.listen(...) # 为一个绑定 3000 端口的简单 Koa 应用
app.callback() # 返回一个适合 http.createServer() 方法的回调函数用来处理请求
app.use(function) # 添加指定的中间件,详情请看 Middleware
app.keys # 设置签名 cookie 密钥
app.context # 从中创建 ctx 的原型

错误处理

app.on('error', (err, ctx) => {
  log.error('server error', err, ctx)
});

默认情况下 Koa 会将所有错误信息输出到 stderr, 除非 app.silenttrue。当 err.status404 或者 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);

这意味着您可以同时支持 HTTPSHTTPS,或者在 多个端口 监听同一个应用

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"这样的参数