簡介
Koa 是由 Express 團隊設計的新 Web 框架,旨在成為更精簡、更具表達力且更強大的 Web 應用程式和 API 基礎。藉由利用非同步函式,Koa 讓您可以放棄回呼,並大幅提升錯誤處理。Koa 的核心不包含任何中間件,並提供一套優雅的方法,讓撰寫伺服器變得快速又令人愉快。
Koa 是由 Express 團隊設計的新 Web 框架,旨在成為更精簡、更具表達力且更強大的 Web 應用程式和 API 基礎。藉由利用非同步函式,Koa 讓您可以放棄回呼,並大幅提升錯誤處理。Koa 的核心不包含任何中間件,並提供一套優雅的方法,讓撰寫伺服器變得快速又令人愉快。
Koa 需要 node v12 或更高版本才能支援 ES2015 和非同步函式。
您可以使用您最愛的版本管理員快速安裝支援的 node 版本
$ nvm install 7
$ npm i koa
$ node my-koa-app.js
Koa 應用程式是一個包含中間件函式陣列的物件,這些函式以堆疊的方式組成並在請求時執行。Koa 類似於您可能曾接觸過的許多其他中間件系統,例如 Ruby 的 Rack、Connect 等 - 但一個關鍵的設計決策是在低階中間件層提供高階的「糖衣」。這改善了互操作性、穩健性,並讓撰寫中間件變得更令人愉快。
這包括用於內容協商、快取新鮮度、代理支援和重新導向等常見任務的方法。儘管提供了相當大量的有用方法,但 Koa 仍維持精簡的體積,因為沒有捆綁任何中間件。
必要的 hello world 應用程式
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
Koa 中間件以更傳統的方式串接,就像您可能習慣於使用類似工具一樣 - 以前很難使用 node 的回呼讓使用者使用起來更友善。然而,透過非同步函式,我們可以實現「真正的」中間件。與 Connect 的實作形成對比,Connect 的實作只是將控制權傳遞給一系列函式,直到其中一個函式傳回,而 Koa 會呼叫「下游」,然後控制權再流回「上游」。
以下範例會回應「Hello World」,但首先,請求會流經 x-response-time
和 logging
中間件,以標記請求開始的時間,然後透過回應中間件傳遞控制權。當中間件呼叫 next()
時,函式會暫停並將控制權傳遞給定義的下一中間件。當沒有更多中間件要執行下游時,堆疊會解開,每個中間件都會繼續執行其上游行為。
const Koa = require('koa');
const app = new Koa();
// logger
app.use(async (ctx, next) => {
await next();
const rt = ctx.response.get('X-Response-Time');
console.log(`${ctx.method} ${ctx.url} - ${rt}`);
});
// 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`);
});
// response
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
應用程式設定是 app
執行個體上的屬性,目前支援下列設定
app.env
預設為 NODE_ENV 或「development」app.keys
已簽署的 cookie 金鑰陣列app.proxy
為 true 時,會信任代理標頭欄位app.subdomainOffset
忽略 .subdomains
的偏移量,預設為 2app.proxyIpHeader
代理 IP 標頭,預設為 X-Forwarded-For
app.maxIpsCount
從代理 IP 標頭讀取的最大 IP 數,預設為 0(表示無限大)
您可以將設定傳遞給建構函式
const Koa = require('koa');
const app = new Koa({ proxy: true });
或動態傳遞
const Koa = require('koa');
const app = new Koa();
app.proxy = true;
Koa 應用程式並非 HTTP 伺服器的 1 對 1 表示。一個或多個 Koa 應用程式可以一起掛載,以形成具有單一 HTTP 伺服器的較大應用程式。
建立並傳回一個 HTTP 伺服器,將給定的引數傳遞給 Server#listen()
。這些引數記錄在 nodejs.org 上。以下是繫結到埠 3000
的無用 Koa 應用程式
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);
這表示您可以將相同的應用程式同時作為 HTTP 和 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);
傳回適合 http.createServer()
方法的回呼函式,以處理要求。您也可以使用這個回呼函式在 Connect/Express 應用程式中掛載您的 Koa 應用程式。
將給定的中間件函式新增到這個應用程式。app.use()
傳回 this
,因此可以串接。
app.use(someMiddleware)
app.use(someOtherMiddleware)
app.listen(3000)
與下列相同
app.use(someMiddleware)
.use(someOtherMiddleware)
.listen(3000)
請參閱 中間件 以取得更多資訊。
設定已簽署的 Cookie 金鑰。
這些金鑰會傳遞給 KeyGrip,但您也可以傳遞您自己的 KeyGrip
實例。例如,下列為可接受的
app.keys = ['OEK5zjaAMPc3L6iK7PyUjCOziUH3rsrMKB9u8H07La1SkfwtuBoDnHaaPCkG5Brg', 'MNKeIebviQnCPo38ufHcSfw3FFv8EtnAe1xE02xkN1wkCV1B2z126U44yk2BQVK7'];
app.keys = new KeyGrip(['OEK5zjaAMPc3L6iK7PyUjCOziUH3rsrMKB9u8H07La1SkfwtuBoDnHaaPCkG5Brg', 'MNKeIebviQnCPo38ufHcSfw3FFv8EtnAe1xE02xkN1wkCV1B2z126U44yk2BQVK7'], 'sha256');
基於安全考量,請確保金鑰夠長且隨機。
這些金鑰可以輪替,並在使用 { signed: true }
選項簽署 Cookie 時使用
ctx.cookies.set('name', 'tobi', { signed: true });
app.context
是 ctx
建立的原型。您可以透過編輯 app.context
,將其他屬性新增到 ctx
。這對於在 ctx
中新增屬性或方法,以在整個應用程式中使用,非常有用,這可能會提升效能(無中間件)和/或更容易(較少的 require()
),但缺點是更依賴 ctx
,這可能會被視為反模式。
例如,從 ctx
中新增資料庫參考
app.context.db = db();
app.use(async ctx => {
console.log(ctx.db);
});
注意
ctx
上的許多屬性是使用 getter、setter 和 Object.defineProperty()
定義的。您只能使用 app.context
上的 Object.defineProperty()
編輯這些屬性(不建議)。請參閱 https://github.com/koajs/koa/issues/652。ctx
和設定。因此,已掛載的應用程式實際上只是中間件的群組。 預設情況下,除非 app.silent
為 true
,否則會將所有錯誤輸出至 stderr。當 err.status
為 404
或 err.expose
為 true
時,預設錯誤處理常式也不會輸出錯誤。若要執行自訂錯誤處理邏輯(例如集中式記錄),您可以新增一個「error」事件監聽器
app.on('error', err => {
log.error('server error', err)
});
如果錯誤在 req/res 循環中,而且無法回應客戶端,則也會傳遞 Context
執行個體
app.on('error', (err, ctx) => {
log.error('server error', err, ctx)
});
當錯誤發生且仍有可能回應客戶端(也就是尚未將資料寫入 socket)時,Koa 會適當地回應 500「內部伺服器錯誤」。在任一種情況下,都會發出應用程式層級的「error」以進行記錄。
Koa Context 將 Node.js 的 request
和 response
物件封裝成一個單一物件,提供許多有用的方法來撰寫 Web 應用程式和 API。這些操作在 HTTP 伺服器開發中使用非常頻繁,因此會在此層級而非較高層級的架構中新增,這將強迫中間件重新實作此常見功能。
每個要求都會建立一個 Context
,並在中間件中參考為接收器或 ctx
識別碼,如下列程式碼片段所示
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
。
Context
特定的方法和存取器。
Node.js 的 request
物件。
Node.js 的 response
物件。
不支援繞過 Koa 的回應處理。避免使用下列 Node.js 屬性
res.statusCode
res.writeHead()
res.write()
res.end()
Koa Request
物件。
Koa Response
物件。
建議的命名空間,用於透過中間件和前端檢視傳遞資訊。
ctx.state.user = await User.find(id);
應用程式執行個體參考。
Koa 應用程式延伸內部 EventEmitter。ctx.app.emit
會發出一個事件,其類型由第一個引數定義。對於每個事件,您可以串接「監聽器」,這是一個在事件發出時呼叫的函式。請參閱 錯誤處理文件 以取得更多資訊。
取得 cookie name
和 options
signed
要求的 cookie 應簽署Koa 使用 cookies 模組,其中選項會直接傳遞。
設定 cookie name
為 value
和 options
maxAge
:表示從 Date.now()
到到期時間的毫秒數。expires
:表示 cookie 到期日期的 Date
物件(預設為在工作階段結束時到期)。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
(對應到 'strict'
)。signed
:表示 cookie 是否要簽署的布林值(預設為 false
)。如果為 true,也會傳送另一個具有相同名稱的 cookie,其附加上 .sig
字尾,並包含一個 27 位元組的 URL 安全 base64 SHA1 值,表示針對第一個 Keygrip 金鑰的 cookie-name=cookie-value 雜湊。這個簽章金鑰用於在下次收到 cookie 時偵測竄改。overwrite
:表示是否覆寫先前設定的相同名稱 cookie 的布林值(預設為 false
)。如果為 true,則在設定此 cookie 時,會在 Set-Cookie 標頭中濾除在同一次要求中設定的所有具有相同名稱的 cookie(不論路徑或網域)。Koa 使用 cookies 模組,其中選項會直接傳遞。
輔助方法,用於擲回預設為 500
的 .status
屬性的錯誤,這將允許 Koa 適當地回應。允許以下組合
ctx.throw(400);
ctx.throw(400, 'name required');
ctx.throw(400, 'name required', { user: user });
例如,ctx.throw(400, '需要名稱')
等同於
const err = new Error('name required');
err.status = 400;
err.expose = true;
throw err;
請注意,這些是使用者層級錯誤,並標記為 err.expose
,表示訊息適合於客戶端回應,這通常不適用於錯誤訊息,因為您不希望洩漏失敗詳細資料。
您也可以傳遞 屬性
物件,它會合併到錯誤中,這對於裝飾報告給上游請求者的機器友善錯誤很有用。
ctx.throw(401, 'access_denied', { user: user });
Koa 使用 http-errors 來建立錯誤。狀態
只能傳遞為第一個參數。
當 !值
時,輔助方法會擲回類似於 .throw()
的錯誤。類似於 Node 的 assert() 方法。
ctx.assert(ctx.state.user, 401, 'User not found. Please login!');
Koa 使用 http-assert 進行斷言。
若要繞過 Koa 內建的回應處理,您可以明確設定 ctx.respond = false;
。如果您想要寫入原始 res
物件,而不是讓 Koa 為您處理回應,請使用此方法。
請注意,Koa 不 支援使用此方法。這可能會破壞 Koa 中介軟體和 Koa 本身的預期功能。使用此屬性被視為一種破解,而且僅方便於那些希望在 Koa 中使用傳統 fn(req, res)
函式和中介軟體的人。
下列存取器和別名 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 等效項
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=
Koa Request
物件是節點原生請求物件的抽象,提供對日常 HTTP 伺服器開發有用的額外功能。
請求標頭物件。這與節點的 headers
欄位相同 http.IncomingMessage
。
設定請求標頭物件。
請求標頭物件。別名為 request.header
。
設定請求標頭物件。別名為 request.header=
。
請求方法。
設定請求方法,用於實作中介軟體,例如 methodOverride()
。
如果存在,則傳回請求內容長度作為數字,否則傳回 undefined
。
取得請求 URL。
設定請求 URL,用於 URL 改寫。
取得請求原始 URL。
取得 URL 起始位置,包括 protocol
和 host
。
ctx.request.origin
// => http://example.com
取得完整請求 URL,包括 protocol
、host
和 url
。
ctx.request.href;
// => http://example.com/foo/bar?q=1
取得請求路徑名稱。
設定請求路徑名稱並保留現有的查詢字串。
取得不含 ?
的原始查詢字串。
設定原始查詢字串。
取得包含 ?
的原始查詢字串。
設定原始查詢字串。
如果存在,取得主機 (hostname:port)。當 app.proxy
為 true 時,支援 X-Forwarded-Host
,否則使用 Host
。
如果存在,取得主機名稱。當 app.proxy
為 true 時,支援 X-Forwarded-Host
,否則使用 Host
。
如果主機是 IPv6,Koa 會委派解析至 WHATWG URL API,注意 這可能會影響效能。
取得 WHATWG 解析的 URL 物件。
取得請求 Content-Type
,不含參數,例如「charset」。
const ct = ctx.request.type;
// => "image/png"
如果存在,取得請求字元集,否則傳回 undefined
ctx.request.charset;
// => "utf-8"
取得已解析的查詢字串,如果沒有查詢字串,則傳回空物件。請注意,此 getter 不 支援巢狀解析。
例如「color=blue&size=small」
{
color: 'blue',
size: 'small'
}
將查詢字串設定為指定的物件。請注意,此 setter 不 支援巢狀物件。
ctx.query = { next: '/login' };
檢查請求快取是否「新鮮」,亦即內容未變更。此方法用於 If-None-Match
/ ETag
與 If-Modified-Since
和 Last-Modified
之間的快取協商。應該在設定其中一個或多個這些回應標頭之後參照它。
// 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.fresh
的反向。
傳回請求協定,為「https」或「http」。當 app.proxy
為 true 時,支援 X-Forwarded-Proto
。
ctx.protocol == "https"
的簡寫,用於檢查請求是否透過 TLS 發出。
請求遠端位址。當 app.proxy
為 true 時,支援 X-Forwarded-For
。
當 X-Forwarded-For
存在且 app.proxy
已啟用時,會傳回這些 IP 的陣列,由上游 -> 下游排序。當停用時,會傳回空陣列。
例如,如果值為「client, proxy1, proxy2」,你會收到陣列 ["client", "proxy1", "proxy2"]
。
大部分的反向代理程式 (nginx) 會透過 proxy_add_x_forwarded_for
設定 x-forwarded-for,這會造成一定的安全性風險。惡意攻擊者可以透過偽造 X-Forwarded-For
請求標頭來偽造客戶端的 IP 位址。客戶端發出的請求有一個 X-Forwarded-For
請求標頭為「偽造」。在反向代理程式轉發後,request.ips
會變成 ['偽造', '客戶端', 'proxy1', 'proxy2']。
Koa 提供兩個選項來避免被繞過。
如果你可以控制反向代理程式,你可以透過調整設定來避免被繞過,或使用 koa 提供的 app.proxyIpHeader
來避免讀取 x-forwarded-for
來取得 IP。
const app = new Koa({
proxy: true,
proxyIpHeader: 'X-Real-IP',
});
如果你確實知道伺服器前面有幾個反向代理程式,你可以透過設定 app.maxIpsCount
來避免讀取使用者偽造的請求標頭。
const app = new Koa({
proxy: true,
maxIpsCount: 1, // only one proxy in front of the server
});
// request.header['X-Forwarded-For'] === [ '127.0.0.1', '127.0.0.2' ];
// ctx.ips === [ '127.0.0.2' ];
傳回子網域作為陣列。
子網域是應用程式主網域之前的點分隔主機部分。預設情況下,應用程式的網域假設是主機的最後兩個部分。這可以透過設定 app.subdomainOffset
來變更。
例如,如果網域是「tobi.ferrets.example.com」:如果未設定 app.subdomainOffset
,ctx.subdomains
會是 ["ferrets", "tobi"]
。如果 app.subdomainOffset
是 3,ctx.subdomains
會是 ["tobi"]
。
檢查傳入請求是否包含「Content-Type」標頭欄位,以及是否包含任何給定的 MIME type
。如果沒有請求主體,會傳回 null
。如果沒有內容類型,或比對失敗,會傳回 false
。否則,會傳回比對的內容類型。
// 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
例如,如果您想要確保只有影像會傳送到給定的路由
if (ctx.is('image/*')) {
// process
} else {
ctx.throw(415, 'images only!');
}
Koa 的 request
物件包含由 accepts 和 negotiator 提供的實用內容協商工具。這些工具是
request.accepts(types)
request.acceptsEncodings(types)
request.acceptsCharsets(charsets)
request.acceptsLanguages(langs)
如果沒有提供類型,將傳回所有可接受的類型。
如果提供了多個類型,將傳回最佳相符項。如果找不到相符項,將傳回 false
,您應該傳送 406 "Not Acceptable"
回應給客戶端。
在缺少接受標頭且任何類型都可接受的情況下,將傳回第一個類型。因此,您提供的類型的順序很重要。
檢查給定的 type(s)
是否可接受,如果為真則傳回最佳相符項,否則為 false
。type
值可以是一個或多個 MIME 類型字串,例如「application/json」,副檔名,例如「json」,或陣列 ["json", "html", "text/plain"]
。
// 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"
您可以多次呼叫 ctx.accepts()
,或使用開關
switch (ctx.accepts('json', 'html', 'text')) {
case 'json': break;
case 'html': break;
case 'text': break;
default: ctx.throw(406, 'json, html, or text only');
}
檢查 encodings
是否可接受,如果為真則傳回最佳相符項,否則為 false
。請注意,您應該將 identity
納入編碼之一!
// Accept-Encoding: gzip
ctx.acceptsEncodings('gzip', 'deflate', 'identity');
// => "gzip"
ctx.acceptsEncodings(['gzip', 'deflate', 'identity']);
// => "gzip"
當沒有給定引數時,所有可接受的編碼都會傳回為陣列
// Accept-Encoding: gzip, deflate
ctx.acceptsEncodings();
// => ["gzip", "deflate", "identity"]
請注意,如果客戶端明確傳送 identity;q=0
,則 identity
編碼(表示沒有編碼)可能會不可接受。儘管這是一個極端情況,但您仍應該處理此方法傳回 false
的情況。
檢查 charsets
是否可接受,如果為真則傳回最佳相符項,否則為 false
。
// 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"
當沒有給定引數時,所有可接受的字元集都會傳回為陣列
// Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5
ctx.acceptsCharsets();
// => ["utf-8", "utf-7", "iso-8859-1"]
檢查 langs
是否可接受,如果為真則傳回最佳相符項,否則為 false
。
// Accept-Language: en;q=0.8, es, pt
ctx.acceptsLanguages('es', 'en');
// => "es"
ctx.acceptsLanguages(['en', 'es']);
// => "es"
當沒有給定引數時,所有可接受的語言都會傳回為陣列
// Accept-Language: en;q=0.8, es, pt
ctx.acceptsLanguages();
// => ["es", "pt", "en"]
檢查請求是否冪等。
傳回請求 Socket。
傳回不區分大小寫的 field
的請求標頭。
Koa Response
物件是建立在 Node 的香草回應物件之上的抽象化,提供對日常 HTTP 伺服器開發有用的額外功能。
回應標頭物件。
回應標頭物件。別名為 response.header
。
回應 socket。指向 net.Socket 實例,如同 request.socket
。
取得回應狀態。預設情況下,response.status
設為 404
,這與 node 的 res.statusCode
預設為 200
不同。
透過數字代碼設定回應狀態
注意:不用太擔心記住這些字串,如果你打錯字,會擲出錯誤,顯示此清單,以便你可以更正。
由於 response.status
預設設為 404
,因此要傳送沒有主體且狀態不同的回應,請執行下列動作
ctx.response.status = 200;
// Or whatever other status
ctx.response.status = 204;
取得回應狀態訊息。預設情況下,response.message
與 response.status
關聯。
將回應狀態訊息設定為指定值。
將回應 Content-Length 設定為指定值。
在存在時,以數字形式傳回回應 Content-Length,或在可能時從 ctx.body
推論,或 undefined
。
取得回應主體。
將回應主體設定為下列其中一項
string
Buffer
Stream
Object
|| Array
null
|| undefined
如果尚未設定 response.status
,Koa 會自動將狀態設定為 200
或 204
,具體取決於 response.body
。特別是,如果尚未設定 response.body
或已設定為 null
或 undefined
,Koa 會自動將 response.status
設定為 204
。如果您真的想要傳送沒有內容的回應,但狀態不同,您應該以下列方式覆寫 204
狀態
// This must be always set first before status, since null | undefined
// body automatically sets the status to 204
ctx.body = null;
// Now we override the 204 status with the desired one
ctx.status = 200;
Koa 沒有防範所有可能作為回應主體的內容 -- 函式無法有意義地序列化,傳回布林值可能根據您的應用程式有意義,而錯誤雖然有效,但可能無法如預期般運作,因為錯誤的某些屬性不可列舉。我們建議在您的應用程式中新增中間件,以宣告每個應用程式的主體類型。範例中間件可能是
app.use(async (ctx, next) => {
await next()
ctx.assert.equal('object', typeof ctx.body, 500, 'some dev did something wrong')
})
Content-Type 預設為 text/html 或 text/plain,兩者預設字元集為 utf-8。Content-Length 欄位也已設定。
Content-Type 預設為 application/octet-stream,Content-Length 也已設定。
Content-Type 預設為 application/octet-stream。
每當串流設定為回應主體時,.onerror
會自動新增為 error
事件的監聽器,以捕捉任何錯誤。此外,每當要求關閉(甚至過早關閉)時,串流都會被銷毀。如果您不想要這兩個功能,請不要直接將串流設定為主體。例如,在代理中將主體設定為 HTTP 串流時,您可能不想要這樣做,因為這會銷毀基礎連線。
請參閱:https://github.com/koajs/koa/pull/612 以取得更多資訊。
以下是串流錯誤處理的範例,不會自動銷毀串流
const PassThrough = require('stream').PassThrough;
app.use(async ctx => {
ctx.body = someHTTPStream.on('error', (err) => ctx.onerror(err)).pipe(PassThrough());
});
Content-Type 預設為 application/json。這包括一般物件 { foo: 'bar' }
和陣列 ['foo', 'bar']
。
取得不區分大小寫的 field
的回應標頭欄位值。
const etag = ctx.response.get('ETag');
如果名稱所識別的標頭目前在傳出的標頭中設定,則傳回 true
。標頭名稱比對不區分大小寫。
const rateLimited = ctx.response.has('X-RateLimit-Limit');
將回應標頭 field
設定為 value
ctx.set('Cache-Control', 'no-cache');
附加標頭 field
,其值為 val
。
ctx.append('Link', '<http://127.0.0.1/>');
使用物件設定多個回應標頭 fields
ctx.set({
'Etag': '1234',
'Last-Modified': date
});
這會委派給 setHeader,它會透過指定的鍵設定或更新標頭,而不重設整個標頭。
移除標頭 field
。
取得回應的 Content-Type
,不含參數,例如「charset」。
const ct = ctx.type;
// => "image/png"
透過 MIME 字串或檔案副檔名設定回應的 Content-Type
。
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')
直接將回應標頭欄位設定為值。
與 ctx.request.is()
非常類似。檢查回應類型是否為所提供類型之一。這對於建立用於處理回應的中介軟體特別有用。
例如,這是一個中介軟體,它會壓縮所有 HTML 回應,但串流除外。
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);
});
對 url
執行 [302] 重新導向。
字串「back」是特殊情況,用於提供 Referrer 支援,當 Referrer 不存在時,會使用 alt
或「/」。
ctx.redirect('back');
ctx.redirect('back', '/index.html');
ctx.redirect('/login');
ctx.redirect('http://google.com');
若要變更預設狀態 302
,只需在此呼叫之前或之後指定狀態。若要變更主體,請在此呼叫之後指定。
ctx.status = 301;
ctx.redirect('/cart');
ctx.body = 'Redirecting to shopping cart';
將 Content-Disposition
設定為「attachment」,以提示客戶端進行下載。選擇性地指定下載的 filename
和一些 選項。
檢查是否已傳送回應標頭。對於查看客戶端是否會在發生錯誤時收到通知很有用。
如果存在,則傳回 Last-Modified
標頭作為 Date
。
設定 Last-Modified
標頭為適當的 UTC 字串。你可以將其設定為 Date
或日期字串。
ctx.response.lastModified = new Date();
設定回應的 ETag 包括包覆的 "
。請注意,沒有對應的 response.etag
getter。
ctx.response.etag = crypto.createHash('md5').update(ctx.body).digest('hex');
在 field
上變化。
清除任何設定的標頭,並開始主體。