# Koa中文文檔 - [點擊查看](https://www.w3cways.com/doc/koa/)
# 簡介
koa 是由 Express 原班人馬打造的,致力于成為一個更小、更富有表現力、更健壯的 Web 框架。使用 koa 編寫 web 應用,通過組合不同的 generator,可以免除重復繁瑣的回調函數嵌套,并極大地提升錯誤處理的效率。koa 不在內核方法中綁定任何中間件,它僅僅提供了一個輕量優雅的函數庫,使得編寫 Web 應用變得得心應手。
## 安裝
Koa需要 node v7.6.0或更高版本來支持ES2015、異步方法
你可以安裝自己支持的node版本。
```javascript
$ nvm install 7
$ npm i koa
$ node my-koa-app.js
```
### Babel異步函數
在node < 7.6的版本中使用async 函數, 我們推薦使用[babel's require hook](http://babeljs.io/docs/usage/require/).
```javascript
require('babel-core/register');
// require the rest of the app that needs to be transpiled after the hook
const app = require('./app');
```
為了解析和轉譯異步函數,你應該至少有[transform-async-to-generator](http://babeljs.io/docs/plugins/transform-async-to-generator/) or [transform-async-to-module-method](http://babeljs.io/docs/plugins/transform-async-to-module-method/)這2個插件。例如,在你的.babelrc文件中,應該有如下代碼
```javascript
{
"plugins": ["transform-async-to-generator"]
}
```
也可以使用[env preset](http://babeljs.io/docs/plugins/preset-env/)并設置"node": "current"來替代.
## 應用
Koa 應用是一個包含一系列中間件 generator 函數的對象。 這些中間件函數基于 request 請求以一個類似于棧的結構組成并依次執行。 Koa 類似于其他中間件系統(比如 Ruby's Rack 、Connect 等), 然而 Koa 的核心設計思路是為中間件層提供高級語法糖封裝,以增強其互用性和健壯性,并使得編寫中間件變得相當有趣。
Koa 包含了像 content-negotiation(內容協商)、cache freshness(緩存刷新)、proxy support(代理支持)和 redirection(重定向)等常用任務方法。 與提供龐大的函數支持不同,Koa只包含很小的一部分,因為Koa并不綁定任何中間件。
任何教程都是從 hello world 開始的,Koa也不例外^_^:
```javascript
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
```
### 級聯
Koa 的中間件通過一種更加傳統(您也許會很熟悉)的方式進行級聯,摒棄了以往 node 頻繁的回調函數造成的復雜代碼邏輯。 然而,使用異步函數,我們可以實現"真正" 的中間件。與之不同,當執行到 yield next 語句時,Koa 暫停了該中間件,繼續執行下一個符合請求的中間件('downstrem'),然后控制權再逐級返回給上層中間件('upstream')。
下面的例子在頁面中返回 "Hello World",然而當請求開始時,請求先經過 x-response-time 和 logging 中間件,并記錄中間件執行起始時間。 然后將控制權交給 reponse 中間件。當一個中間件調用next()函數時,函數掛起并控件傳遞給定義的下一個中間件。在沒有更多的中間件執行下游之后,堆棧將退出,并且每個中間件被恢復以執行其上游行為。
```javascript
const Koa = require('koa');
const app = new Koa();
// x-response-time
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 實例屬性,目前支持的配置項如下:
- app.env 默認為 NODE_ENV or "development"
- app.proxy 如果為 true,則解析 "Host" 的 header 域,并支持 X-Forwarded-Host
- app.subdomainOffset 默認為2,表示 .subdomains 所忽略的字符偏移量。
### app.listen(...)
Koa 應用并非是一個 1-to-1 表征關系的 HTTP 服務器。 一個或多個Koa應用可以被掛載到一起組成一個包含單一 HTTP 服務器的大型應用群。
如下為一個綁定3000端口的簡單 Koa 應用,其創建并返回了一個 HTTP 服務器,為 Server#listen() 傳遞指定參數(參數的詳細文檔請查看[nodejs.org](http://nodejs.org/api/http.html#http_server_listen_port_hostname_backlog_callback))。
```javascript
const Koa = require('koa');
const app = new Koa();
app.listen(3000);
```
The app.listen(...) 實際上是以下代碼的語法糖:
```javascript
const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
```
這意味著您可以同時支持 HTTPS 和 HTTPS,或者在多個端口監聽同一個應用。
```javascript
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);
```
### app.callback()
返回一個適合 http.createServer() 方法的回調函數用來處理請求。 您也可以使用這個回調函數將您的app掛載在 Connect/Express 應用上。
### app.use(function)
為應用添加指定的中間件,詳情請看 [Middleware](https://github.com/koajs/koa/wiki#middleware)
### app.keys=
設置簽名cookie密鑰。
該密鑰會被傳遞給KeyGrip, 當然,您也可以自己生成 KeyGrip. 例如:
```javascript
app.keys = ['im a newer secret', 'i like turtle'];
app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
```
在進行cookie簽名時,只有設置 signed 為 true 的時候,才會使用密鑰進行加密:
```javascript
ctx.cookies.set('name', 'tobi', { signed: true });
```
### app.context
app.context是從中創建ctx的原型。 可以通過編輯app.context向ctx添加其他屬性。當需要將ctx添加到整個應用程序中使用的屬性或方法時,這將會非常有用。這可能會更加有效(不需要中間件)和/或更簡單(更少的require()),而不必擔心更多的依賴于ctx,這可以被看作是一種反向模式。
例如,從ctx中添加對數據庫的引用:
```javascript
app.context.db = db();
app.use(async ctx => {
console.log(ctx.db);
});
```
注:
- ctx上的很多屬性是被限制的,在app.context只能通過使用Object.defineProperty()來編輯這些屬性(不推薦)。可以在 https://github.com/koajs/koa/issues/652 上查閱
- 已安裝的APP沿用父級的ctx和配置. Thus, mounted apps are really just groups of middleware.
### 錯誤處理
默認情況下Koa會將所有錯誤信息輸出到 stderr, 除非 app.silent 是 true.當err.status是404或者err.expose時,默認錯誤處理程序也不會輸出錯誤。要執行自定義錯誤處理邏輯,如集中式日志記錄,您可以添加一個"錯誤"事件偵聽器:
```javascript
app.on('error', err => {
log.error('server error', err)
});
```
如果錯誤發生在 請求/響應 環節,并且其不能夠響應客戶端時,Contenxt 實例也會被傳遞到 error 事件監聽器的回調函數里。
```javascript
app.on('error', (err, ctx) => {
log.error('server error', err, ctx)
});
```
當發生錯誤但仍能夠響應客戶端時(比如沒有數據寫到socket中),Koa會返回一個500錯誤(Internal Server Error)。 無論哪種情況,Koa都會生成一個應用級別的錯誤信息,以便實現日志記錄等目的。
## Context(上下文)
Koa Context 將 node 的 request 和 response 對象封裝在一個單獨的對象里面,其為編寫 web 應用和 API 提供了很多有用的方法。 這些操作在 HTTP 服務器開發中經常使用,因此其被添加在上下文這一層,而不是更高層框架中,因此將迫使中間件需要重新實現這些常用方法。
context 在每個 request 請求中被創建,在中間件中作為接收器(receiver)來引用,或者通過 this 標識符來引用:
```javascript
app.use(async ctx => {
ctx; // is the Context
ctx.request; // is a koa Request
ctx.response; // is a koa Response
});
```
許多 context 的訪問器和方法為了便于訪問和調用,簡單的委托給他們的 ctx.request 和 ctx.response 所對應的等價方法, 比如說 ctx.type 和 ctx.length 代理了 response 對象中對應的方法,ctx.path 和 ctx.method 代理了 request 對象中對應的方法。
### API
Context 詳細的方法和訪問器。
#### ctx.req
Node 的 request 對象。
#### ctx.res
Node 的 response 對象。
Koa 不支持 直接調用底層 res 進行響應處理。請避免使用以下 node 屬性:
- res.statusCode
- res.writeHead()
- res.write()
- res.end()
#### ctx.request
Koa 的 Request 對象。
#### ctx.response
Koa 的 Response 對象。
#### ctx.state
推薦的命名空間,用于通過中間件傳遞信息到前端視圖
```javascript
ctx.state.user = await User.find(id);
```
#### ctx.app
應用實例引用。
#### ctx.cookies.get(name, [options])
獲得 cookie 中名為 name 的值,options 為可選參數:
- signed 如果為 true,表示請求時 cookie 需要進行簽名。
注意:Koa 使用了 Express 的 [cookies](https://github.com/jed/cookies) 模塊,options 參數只是簡單地直接進行傳遞。
#### ctx.cookies.set(name, value, [options])
設置 cookie 中名為 name 的值,options 為可選參數:
- maxAge 一個數字,表示 Date.now()到期的毫秒數
- signed 是否要做簽名
- expires cookie有效期
- pathcookie 的路徑,默認為 /'
- domain cookie 的域
- secure false 表示 cookie 通過 HTTP 協議發送,true 表示 cookie 通過 HTTPS 發送。
- httpOnly true 表示 cookie 只能通過 HTTP 協議發送
- overwrite 一個布爾值,表示是否覆蓋以前設置的同名的Cookie(默認為false)。 如果為true,在設置此cookie時,將在同一請求中使用相同名稱(不管路徑或域)設置的所有Cookie將從Set-Cookie頭部中過濾掉。
注意:Koa 使用了 Express 的 [cookies](https://github.com/jed/cookies) 模塊,options 參數只是簡單地直接進行傳遞。
#### ctx.throw([status], [msg], [properties])
拋出包含 .status 屬性的錯誤,默認為 500。該方法可以讓 Koa 準確的響應處理狀態。 Koa支持以下組合:
```javascript
ctx.throw(400);
ctx.throw(400, 'name required');
ctx.throw(400, 'name required', { user: user });
```
this.throw('name required', 400) 等價于:
```javascript
const err = new Error('name required');
err.status = 400;
err.expose = true;
throw err;
```
注意:這些用戶級錯誤被標記為 err.expose,其意味著這些消息被準確描述為對客戶端的響應,而并非使用在您不想泄露失敗細節的場景中。
您可以選擇傳遞一個屬性對象,該對象被合并到錯誤中,這對裝飾機器友好錯誤非常有用,并且這些錯誤會被報給上層請求。
```javascript
ctx.throw(401, 'access_denied', { user: user });
```
koa用 [http-errors](https://github.com/jshttp/http-errors)來創建錯誤。
#### ctx.assert(value, [status], [msg], [properties])
當!value時, Helper 方法拋出一個類似.throw()的錯誤。 類似node's [assert()](http://nodejs.org/api/assert.html) 方法。
```javascript
ctx.assert(ctx.state.user, 401, 'User not found. Please login!');
```
koa 使用 [http-assert](https://github.com/jshttp/http-assert) 來斷言。
#### ctx.respond
為了避免使用 Koa 的內置響應處理功能,您可以直接賦值 this.repond = false;。如果您不想讓 Koa 來幫助您處理 reponse,而是直接操作原生 res 對象,那么請使用這種方法。
注意: 這種方式是不被 Koa 支持的。其可能會破壞 Koa 中間件和 Koa 本身的一些功能。其只作為一種 hack 的方式,并只對那些想要在 Koa 方法和中間件中使用傳統 fn(req, res) 方法的人來說會帶來便利。
#### Request aliases
以下訪問器和別名與 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 aliases
以下訪問器和別名與 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)
Koa Request 對象是對 node 的 request 進一步抽象和封裝,提供了日常 HTTP 服務器開發中一些有用的功能。
### API
#### 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
```javascript
ctx.request.origin
// => http://example.com
```
#### request.href
獲取完整的請求URL, 包含 protocol, host 和 url
```javascript
ctx.request.href;
// => http://example.com/foo/bar?q=1
```
#### 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。
如果主機是IPv6, Koa 將解析轉換為 [WHATWG URL API](https://nodejs.org/dist/latest-v8.x/docs/api/url.html#url_the_whatwg_url_api), 注意 這可能會影響性能
#### request.URL
獲取 WHATWG 解析的對象.
#### request.type
獲取請求 Content-Type,不包含像 "charset" 這樣的參數。
```javascript
const ct = ctx.request.type;
// => "image/png"
```
#### request.charset
獲取請求 charset,沒有則返回 undefined:
```javascript
ctx.request.charset;
// => "utf-8"
```
#### request.query
將查詢參數字符串進行解析并以對象的形式返回,如果沒有查詢參數字字符串則返回一個空對象。注意:該方法不支持嵌套解析。
例如 "color=blue&size=small":
```javascript
{
color: 'blue',
size: 'small'
}
```
#### request.query=
根據給定的對象設置查詢參數字符串。 注意:該方法不 支持嵌套對象。
```javascript
ctx.query = { next: '/login' };
```
#### request.fresh
檢查請求緩存是否 "fresh"(內容沒有發生變化)。該方法用于在 If-None-Match / ETag, If-Modified-Since 和 Last-Modified 中進行緩存協調。當在 response headers 中設置一個或多個上述參數后,該方法應該被使用。
```javascript
// freshness check requires status 20x or 304
ctx.status = 200;
ctx.set('ETag', '123');
// cache is ok
if (ctx.fresh) {
ctx.status = 304;
return;
}
// cache is stale
// fetch new data
ctx.body = await db.find('something');
```
#### request.stale
與 req.fresh 相反。
#### request.protocol
返回請求協議,"https" 或者 "http"。 當 app.proxy 設置為 true 時,支持 X-Forwarded-Host。
#### 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
以數組形式返回子域名。
子域名是在host中逗號分隔的主域名前面的部分。默認情況下,應用的域名假設為host中最后兩部分。其可通過設置 app.subdomainOffset 進行更改。
舉例來說,如果域名是 "tobi.ferrets.example.com":
如果沒有設置 app.subdomainOffset,其 subdomains 為 ["ferrets", "tobi"]。 如果設置 app.subdomainOffset 為3,其 subdomains 為 ["tobi"]。
#### request.is(types...)
檢查請求所包含的 "Content-Type" 是否為給定的 type 值。 如果沒有 request body,返回 undefined。 如果沒有 content type,或者匹配失敗,返回 false。 否則返回匹配的 content-type。
```javascript
// With Content-Type: text/html; charset=utf-8
ctx.is('html'); // => 'html'
ctx.is('text/html'); // => 'text/html'
ctx.is('text/*', 'text/html'); // => 'text/html'
// When Content-Type is application/json
ctx.is('json', 'urlencoded'); // => 'json'
ctx.is('application/json'); // => 'application/json'
ctx.is('html', 'application/*'); // => 'application/json'
ctx.is('html'); // => false
```
比如說您希望保證只有圖片發送給指定路由
```javascript
if (ctx.is('image/*')) {
// process
} else {
ctx.throw(415, 'images only!');
}
```
#### Content Negotiation
Koa request 對象包含 content negotiation 功能(由 [accepts](http://github.com/expressjs/accepts) 和 [negotiator](http://github.com/expressjs/accepts) 提供):
- request.accepts(types)
- request.acceptsEncodings(types)
- request.acceptsCharsets(charsets)
- request.acceptsLanguages(langs)
如果沒有提供 types,將會返回所有的可接受類型。
如果提供多種 types,將會返回最佳匹配類型。如果沒有匹配上,則返回 false,您應該給客戶端返回 406 "Not Acceptable"。
為了防止缺少 accept headers 而導致可以接受任意類型,將會返回第一種類型。因此,您提供的類型順序非常重要。
#### request.accepts(types)
檢查給定的類型 types(s) 是否可被接受,當為 true 時返回最佳匹配,否則返回 false。type 的值可以是一個或者多個 mime 類型字符串。 比如 "application/json" 擴展名為 "json",或者數組 ["json", "html", "text/plain"]。
```javascript
// Accept: text/html
ctx.accepts('html');
// => "html"
// Accept: text/*, application/json
ctx.accepts('html');
// => "html"
ctx.accepts('text/html');
// => "text/html"
ctx.accepts('json', 'text');
// => "json"
ctx.accepts('application/json');
// => "application/json"
// Accept: text/*, application/json
ctx.accepts('image/png');
ctx.accepts('png');
// => false
// Accept: text/*;q=.5, application/json
ctx.accepts(['html', 'json']);
ctx.accepts('html', 'json');
// => "json"
// No Accept header
ctx.accepts('html', 'json');
// => "html"
ctx.accepts('json', 'html');
// => "json"
```
this.accepts() 可以被調用多次,或者使用 switch:
```javascript
switch (ctx.accepts('json', 'html', 'text')) {
case 'json': break;
case 'html': break;
case 'text': break;
default: ctx.throw(406, 'json, html, or text only');
}
```
#### request.acceptsEncodings(encodings)
檢查 encodings 是否可以被接受,當為 true 時返回最佳匹配,否則返回 false。 注意:您應該在 encodings 中包含 identity。
```javascript
// Accept-Encoding: gzip
ctx.acceptsEncodings('gzip', 'deflate', 'identity');
// => "gzip"
ctx.acceptsEncodings(['gzip', 'deflate', 'identity']);
// => "gzip"
```
當沒有傳遞參數時,返回包含所有可接受的 encodings 的數組:
```javascript
// Accept-Encoding: gzip, deflate
ctx.acceptsEncodings();
// => ["gzip", "deflate", "identity"]
```
注意:如果客戶端直接發送 identity;q=0 時,identity encoding(表示no encoding) 可以不被接受。當這個方法返回false時,雖然這是一個邊界情況,您仍然應該處理這種情況。
#### request.acceptsCharsets(charsets)
檢查 charsets 是否可以被接受,如果為 true 則返回最佳匹配, 否則返回 false。
```javascript
// 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 的數組:
```javascript
// Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5
ctx.acceptsCharsets();
// => ["utf-8", "utf-7", "iso-8859-1"]
```
#### request.acceptsLanguages(langs)
檢查 langs 是否可以被接受,如果為 true 則返回最佳匹配,否則返回 false。
```javascript
// Accept-Language: en;q=0.8, es, pt
ctx.acceptsLanguages('es', 'en');
// => "es"
ctx.acceptsLanguages(['en', 'es']);
// => "es"
```
當沒有傳遞參數時,返回包含所有可接受的 langs 的數組:
```javascript
// Accept-Language: en;q=0.8, es, pt
ctx.acceptsLanguages();
// => ["es", "pt", "en"]
```
#### request.idempotent
檢查請求是否為冪等(idempotent)
#### request.socket
返回請求的socket。
#### request.get(field)
返回請求頭
## Response
Koa Response 對象是對 node 的 response 進一步抽象和封裝,提供了日常 HTTP 服務器開發中一些有用的功能。
### API
#### 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=
通過數字設置響應狀態:
- 100 "continue"
- 101 "switching protocols"
- 102 "processing"
- 200 "ok"
- 201 "created"
- 202 "accepted"
- 203 "non-authoritative information"
- 204 "no content"
- 205 "reset content"
- 206 "partial content"
- 207 "multi-status"
- 208 "already reported"
- 226 "im used"
- 300 "multiple choices"
- 301 "moved permanently"
- 302 "found"
- 303 "see other"
- 304 "not modified"
- 305 "use proxy"
- 307 "temporary redirect"
- 308 "permanent redirect"
- 400 "bad request"
- 401 "unauthorized"
- 402 "payment required"
- 403 "forbidden"
- 404 "not found"
- 405 "method not allowed"
- 406 "not acceptable"
- 407 "proxy authentication required"
- 408 "request timeout"
- 409 "conflict"
- 410 "gone"
- 411 "length required"
- 412 "precondition failed"
- 413 "payload too large"
- 414 "uri too long"
- 415 "unsupported media type"
- 416 "range not satisfiable"
- 417 "expectation failed"
- 418 "I'm a teapot"
- 422 "unprocessable entity"
- 423 "locked"
- 424 "failed dependency"
- 426 "upgrade required"
- 428 "precondition required"
- 429 "too many requests"
- 431 "request header fields too large"
- 500 "internal server error"
- 501 "not implemented"
- 502 "bad gateway"
- 503 "service unavailable"
- 504 "gateway timeout"
- 505 "http version not supported"
- 506 "variant also negotiates"
- 507 "insufficient storage"
- 508 "loop detected"
- 510 "not extended"
- 511 "network authentication required"
注意:不用擔心記不住這些字符串,如果您設置錯誤,會有異常拋出,并列出該狀態碼表來幫助您進行更正。
#### response.message
獲取響應狀態消息。默認情況下, response.message關聯response.status。
#### response.message=
將響應狀態消息設置為給定值。
#### response.length=
將響應Content-Length設置為給定值。
#### response.length
如果 Content-Length 作為數值存在,或者可以通過 ctx.body 來進行計算,則返回相應數值,否則返回 undefined。
#### response.body
獲取響應體。
#### response.body=
設置響應體為如下值:
- string written
- Buffer written
- Stream piped
- Object || Array json-stringified
- null no content response
如果 res.status 沒有賦值,Koa會自動設置為 200 或 204。
#### String
Content-Type 默認為 text/html 或者 text/plain,兩種默認 charset 均為 utf-8。 Content-Length 同時會被設置。
#### Buffer
Content-Type 默認為 application/octet-stream,Content-Length同時被設置。
#### Stream
Content-Type 默認為 application/octet-stream。
當stream被設置為響應體時, .onerror將作為監聽器自動添加到錯誤事件中以捕獲任何錯誤。此外,每當請求被關閉(甚至更早)時,stream都將被銷毀。如果不想要這兩個功能,請不要直接將stream設置為響應體。例如,當將響應體設置為代理中的HTTP stream時,會破壞底層連接。
請查閱: https://github.com/koajs/koa/pull/612 來獲取更多信息。
以下是stream error處理的示例,并且不會自動銷毀stream:
```javascript
const PassThrough = require('stream').PassThrough;
app.use(async ctx => {
ctx.body = someHTTPStream.on('error', ctx.onerror).pipe(PassThrough());
});
```
#### Object
Content-Type默認為application/json。 這包括普通對象{ foo: 'bar' }和數組['foo', 'bar']。
#### response.get(field)
獲取 response header 中字段值,field 不區分大小寫。
```javascript
const etag = ctx.response.get('ETag');
```
#### response.set(field, value)
設置 response header 字段 field 的值為 value。
```javascript
ctx.set('Cache-Control', 'no-cache');
```
#### response.append(field, value)
添加額外的字段field 的值為 val
```javascript
ctx.append('Link', '<http://127.0.0.1/>');
```
#### response.set(fields)
使用對象同時設置 response header 中多個字段的值。
```javascript
ctx.set({
'Etag': '1234',
'Last-Modified': date
});
```
#### response.remove(field)
移除 response header 中字段 filed。
#### response.type
獲取 response Content-Type,不包含像"charset"這樣的參數。
```javascript
const ct = ctx.type;
// => "image/png"
```
#### response.type=
通過 mime 類型的字符串或者文件擴展名設置 response Content-Type
```javascript
ctx.type = 'text/plain; charset=utf-8';
ctx.type = 'image/png';
ctx.type = '.png';
ctx.type = 'png';
```
注意:當為你選擇一個合適的charset時,例如response.type = 'html'將默認為"utf-8"。 如果需要覆蓋charset,請使用ctx.set('Content-Type', 'text/html')直接設置響應頭字段值。
#### response.is(types...)
跟ctx.request.is()非常類似。用來檢查響應類型是否是所提供的類型之一。這對于創建操作響應的中間件特別有用。
例如,這是一個中間件,它可以縮小除stream以外的所有HTML響應。
```javascript
const minify = require('html-minifier');
app.use(async (ctx, next) => {
await next();
if (!ctx.response.is('html')) return;
let body = ctx.body;
if (!body || body.pipe) return;
if (Buffer.isBuffer(body)) body = body.toString();
ctx.body = minify(body);
});
```
#### response.redirect(url, [alt])
執行 [302] 重定向到對應 url。
字符串 "back" 是一個特殊參數,其提供了 Referrer 支持。當沒有Referrer時,使用 alt 或者 / 代替。
```javascript
ctx.redirect('back');
ctx.redirect('back', '/index.html');
ctx.redirect('/login');
ctx.redirect('http://google.com');
```
如果想要修改默認的 [302] 狀態,直接在重定向之前或者之后執行即可。如果要修改 body,需要在重定向之前執行。
```javascript
ctx.status = 301;
ctx.redirect('/cart');
ctx.body = 'Redirecting to shopping cart';
```
#### response.attachment([filename])
設置 "attachment" 的 Content-Disposition,用于給客戶端發送信號來提示下載。filename 為可選參數,用于指定下載文件名。
#### response.headerSent
檢查 response header 是否已經發送,用于在發生錯誤時檢查客戶端是否被通知。
#### response.lastModified
如果存在 Last-Modified,則以 Date 的形式返回。
#### response.lastModified=
以 UTC 格式設置 Last-Modified。您可以使用 Date 或 date 字符串來進行設置。
```javascript
ctx.response.lastModified = new Date();
```
#### response.etag=
設置 包含 "s 的 ETag。注意沒有對應的 res.etag 來獲取其值。
```javascript
ctx.response.etag = crypto.createHash('md5').update(ctx.body).digest('hex');
```
#### response.vary(field)
不同于field.
#### response.flushHeaders()
刷新任何設置的響應頭,并開始響應體。
## 相關資源
以下列出了更多第三方提供的 koa 中間件、完整實例、全面的幫助文檔等。如果有問題,請加入我們的 IRC!
- [GitHub repository](https://github.com/koajs/koa)
- [Examples](https://github.com/koajs/examples)
- [Middleware](https://github.com/koajs/koa/wiki#middleware)
- [Wiki](https://github.com/koajs/koa/wiki)
- [G+ Community](https://plus.google.com/communities/101845768320796750641)
- [Mailing list](https://groups.google.com/forum/#!forum/koajs)
- [Guide](https://github.com/koajs/koa/blob/master/docs/guide.md)
- [FAQ](https://github.com/koajs/koa/blob/master/docs/faq.md)
- #koajs on freenode