はじめに
Koaは、Expressの開発チームによって設計された新しいWebフレームワークです。WebアプリケーションとAPIのための、より小さく、より表現力豊かで、より堅牢な基盤を目指しています。非同期関数を利用することで、コールバックを排除し、エラー処理を大幅に改善できます。Koaはコアにミドルウェアをバンドルしておらず、サーバーの記述を迅速かつ快適にするためのエレガントなメソッド群を提供します。
Koaは、Expressの開発チームによって設計された新しいWebフレームワークです。WebアプリケーションとAPIのための、より小さく、より表現力豊かで、より堅牢な基盤を目指しています。非同期関数を利用することで、コールバックを排除し、エラー処理を大幅に改善できます。Koaはコアにミドルウェアをバンドルしておらず、サーバーの記述を迅速かつ快適にするためのエレガントなメソッド群を提供します。
KoaはES2015と非同期関数サポートのために、**Node v12**以降が必要です。
お好みのバージョンマネージャーを使用して、サポートされているバージョンのNodeを簡単にインストールできます。
$ nvm install 7
$ npm i koa
$ node my-koa-app.jsKoaアプリケーションは、ミドルウェア関数の配列を含むオブジェクトです。これらの関数は、リクエスト時にスタックのような方法で合成され、実行されます。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の実装は、関数のシリーズを通して制御を渡すだけで、1つが返されるまで続けますが、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 署名付きクッキーキーの配列app.proxy trueの場合、プロキシヘッダーフィールドが信頼されます。app.subdomainOffset 無視する.subdomainsのオフセット、デフォルトは2app.proxyIpHeader プロキシIPヘッダー、デフォルトはX-Forwarded-Forapp.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の表現ではありません。1つ以上のKoaアプリケーションをマウントして、単一のHTTPサーバーを持つより大きなアプリケーションを形成できます。
与えられた引数をServer#listen()に渡してHTTPサーバーを作成および返します。これらの引数は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()メソッドに適したコールバック関数を返し、リクエストを処理します。このコールバック関数を使用して、KoaアプリをConnect/Expressアプリにマウントすることもできます。
このアプリケーションに指定されたミドルウェア関数を追加します。app.use()はthisを返し、チェーン可能です。
app.use(someMiddleware)
app.use(someOtherMiddleware)
app.listen(3000)これは以下と同じです。
app.use(someMiddleware)
.use(someOtherMiddleware)
.listen(3000)詳細はMiddlewareを参照してください。
署名付きクッキーキーを設定します。
これらはKeyGripに渡されますが、独自のKeyGripインスタンスを渡すこともできます。たとえば、以下は許容されます。
app.keys = ['OEK5zjaAMPc3L6iK7PyUjCOziUH3rsrMKB9u8H07La1SkfwtuBoDnHaaPCkG5Brg', 'MNKeIebviQnCPo38ufHcSfw3FFv8EtnAe1xE02xkN1wkCV1B2z126U44yk2BQVK7'];
app.keys = new KeyGrip(['OEK5zjaAMPc3L6iK7PyUjCOziUH3rsrMKB9u8H07La1SkfwtuBoDnHaaPCkG5Brg', 'MNKeIebviQnCPo38ufHcSfw3FFv8EtnAe1xE02xkN1wkCV1B2z126U44yk2BQVK7'], 'sha256');セキュリティ上の理由から、キーが十分な長さでランダムであることを確認してください。
これらのキーはローテーションでき、{ signed: true }オプションでクッキーに署名する際に使用されます。
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の多くのプロパティは、ゲッター、セッター、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)
});エラーが発生し、クライアントにまだレスポンスできる場合(ソケットにデータが書き込まれていない場合)、Koaは適切に500「Internal Server Error」でレスポンスします。どちらの場合も、ログ記録のためにアプリレベルの「error」が発行されます。
Koaコンテキストは、Nodeの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
});コンテキストのアクセサーとメソッドの多くは、便宜上、ctx.requestまたはctx.responseの同等のものに対応するだけです。たとえば、ctx.typeとctx.lengthはresponseオブジェクトに対応し、ctx.pathとctx.methodはrequestに対応します。
Context固有のメソッドとアクセサー。
Nodeのrequestオブジェクト。
Nodeのresponseオブジェクト。
Koaのレスポンス処理をバイパスすることは**サポートされていません**。以下のNodeプロパティの使用は避けてください。
res.statusCoderes.writeHead()res.write()res.end()KoaのRequestオブジェクト。
KoaのResponseオブジェクト。
ミドルウェアとフロントエンドビューを通して情報を渡すための推奨ネームスペース。
ctx.state.user = await User.find(id);アプリケーションインスタンスへの参照。
Koaアプリケーションは内部のEventEmitterを拡張します。ctx.app.emitは、最初の引数で定義されたタイプを持つイベントを発行します。各イベントに対して、「リスナー」を接続できます。これは、イベントが発行されたときに呼び出される関数です。詳細はエラー処理のドキュメントを参照してください。
optionsでクッキーnameを取得します。
signed 要求されたクッキーは署名されている必要があります。Koaはcookiesモジュールを使用し、オプションはそのまま渡されます。
optionsでクッキーnameをvalueに設定します。
maxAge: 期限までのミリ秒数をDate.now()から表す数値。expires: クッキーの有効期限を示すDateオブジェクト(デフォルトではセッション終了時に期限切れ)。path: クッキーのパスを示す文字列(デフォルトは/)。domain: クッキーのドメインを示す文字列(デフォルトなし)。secure: クッキーがHTTPS経由でのみ送信されるかどうかを示すブール値(HTTPの場合はデフォルトでfalse、HTTPSの場合はデフォルトでtrue)。このオプションの詳細はこちら。httpOnly: クッキーがHTTP(S)経由でのみ送信され、クライアントのJavaScriptで使用できないかどうかを示すブール値(デフォルトはtrue)。sameSite: クッキーが「same site」クッキーかどうかを示すブール値または文字列(デフォルトはfalse)。これは'strict'、'lax'、'none'、またはtrue('strict'にマップ)に設定できます。signed: クッキーに署名するかどうかを示すブール値(デフォルトはfalse)。これがtrueの場合、同じ名前で.sigサフィックスが付いた別のクッキーも送信され、最初のKeygripキーに対してcookie-name=cookie-valueのハッシュを表す27バイトのURLセーフなbase64 SHA1値が含まれます。この署名キーは、次回クッキーが受信されたときに改ざんを検出するために使用されます。overwrite: 同じ名前の以前に設定されたクッキーを上書きするかどうかを示すブール値(デフォルトはfalse)。これがtrueの場合、同じリクエスト中に同じ名前で設定されたすべてのクッキー(パスまたはドメインに関係なく)は、このクッキーを設定するときにSet-Cookieヘッダーから除外されます。Koaはcookiesモジュールを使用し、オプションはそのまま渡されます。
.statusプロパティ(デフォルトは500)を持つエラーをスローするヘルパーメソッドで、Koaが適切にレスポンスできるようにします。次の組み合わせが許可されます。
ctx.throw(400);
ctx.throw(400, 'name required');
ctx.throw(400, 'name required', { user: user });たとえば、ctx.throw(400, 'name required')は以下と同等です。
const err = new Error('name required');
err.status = 400;
err.expose = true;
throw err;これらはユーザーレベルのエラーであり、err.exposeでフラグが付けられていることに注意してください。つまり、メッセージはクライアントレスポンスに適しています。これは、通常、エラーメッセージの場合には当てはまりません。失敗の詳細を漏らしたくないためです。
必要に応じて、エラーにそのままマージされるpropertiesオブジェクトを渡すことができます。これは、アップストリームのリクエスターに報告されるマシンフレンドリーなエラーを装飾するのに役立ちます。
ctx.throw(401, 'access_denied', { user: user });Koaはhttp-errorsを使用してエラーを作成します。statusは最初の引数としてのみ渡す必要があります。
!valueの場合に.throw()と同様のエラーをスローするヘルパーメソッド。Nodeのassert()メソッドに似ています。
ctx.assert(ctx.state.user, 401, 'User not found. Please login!');Koaはhttp-assertをアサーションに使用します。
Koaの組み込みレスポンス処理をバイパスするには、明示的にctx.respond = false;を設定できます。Koaがレスポンスを処理する代わりに、生のresオブジェクトに書き込む場合は、これを使用します。
これはKoaでは**サポートされていません**。KoaミドルウェアやKoa自体の意図した機能を壊す可能性があります。このプロパティの使用はハックとみなされ、従来のfn(req, res)関数とミドルウェアをKoaで使用したいユーザーのための便宜的なものです。
以下のアクセッサとエイリアスはRequestと同等です。
ctx.headerctx.headersctx.methodctx.method=ctx.urlctx.url=ctx.originalUrlctx.originctx.hrefctx.pathctx.path=ctx.queryctx.query=ctx.querystringctx.querystring=ctx.hostctx.hostnamectx.freshctx.stalectx.socketctx.protocolctx.securectx.ipctx.ipsctx.subdomainsctx.is()ctx.accepts()ctx.acceptsEncodings()ctx.acceptsCharsets()ctx.acceptsLanguages()ctx.get()以下のアクセッサとエイリアスはResponseと同等です。
ctx.bodyctx.body=ctx.statusctx.status=ctx.messagectx.message=ctx.length=ctx.lengthctx.type=ctx.typectx.headerSentctx.redirect()ctx.attachment()ctx.set()ctx.append()ctx.remove()ctx.lastModified=ctx.etag=KoaのRequestオブジェクトは、Nodeの標準的なリクエストオブジェクトの上位に構築された抽象化レイヤーであり、日常的なHTTPサーバー開発に役立つ追加機能を提供します。
リクエストヘッダーオブジェクト。これはNodeのheadersフィールド(http.IncomingMessage)と同じです。
リクエストヘッダーオブジェクトを設定します。
リクエストヘッダーオブジェクト。request.headerのエイリアスです。
リクエストヘッダーオブジェクトを設定します。request.header=のエイリアスです。
リクエストメソッド。
リクエストメソッドを設定します。methodOverride()などのミドルウェアの実装に役立ちます。
存在する場合、リクエストのContent-Lengthを数値で返し、存在しない場合はundefinedを返します。
リクエストURLを取得します。
リクエストURLを設定します。URLの書き換えに役立ちます。
リクエストの元のURLを取得します。
URLのオリジン(プロトコルとホストを含む)を取得します。
ctx.request.origin
// => http://example.com完全なリクエストURL(プロトコル、ホスト、URLを含む)を取得します。
ctx.request.href;
// => http://example.com/foo/bar?q=1リクエストのパス名を取得します。
リクエストのパス名を設定し、クエリ文字列が存在する場合は保持します。
?を除いた生のクエリ文字列を取得します。
生のクエリ文字列を設定します。
?を含む生のクエリ文字列を取得します。
生のクエリ文字列を設定します。
存在する場合、ホスト(ホスト名:ポート)を取得します。app.proxyがtrueの場合、X-Forwarded-Hostをサポートします。それ以外の場合は、Hostを使用します。
存在する場合、ホスト名を取得します。app.proxyがtrueの場合、X-Forwarded-Hostをサポートします。それ以外の場合は、Hostを使用します。
ホストがIPv6の場合、KoaはWHATWG URL APIにパース処理を委任します。注意 パフォーマンスに影響する可能性があります。
WHATWGでパースされたURLオブジェクトを取得します。
"charset"などのパラメータを除いたリクエストのContent-Typeを取得します。
const ct = ctx.request.type;
// => "image/png"存在する場合、リクエストのcharsetを返し、存在しない場合はundefinedを返します。
ctx.request.charset;
// => "utf-8"パースされたクエリ文字列を取得します。クエリ文字列が存在しない場合は空のオブジェクトを返します。このゲッターはネストされたパースをサポート**しません**。
例:"color=blue&size=small"
{
color: 'blue',
size: 'small'
}指定されたオブジェクトにクエリ文字列を設定します。このセッターはネストされたオブジェクトをサポート**しません**。
ctx.query = { next: '/login' };リクエストキャッシュが「新鮮」であるかどうか(つまり、コンテンツが変更されていないかどうか)を確認します。このメソッドは、If-None-Match / ETagとIf-Modified-SinceとLast-Modifiedの間のキャッシュネゴシエーション用です。これらのレスポンスヘッダーの1つ以上を設定した後に参照する必要があります。
// 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は['forged', 'client', 'proxy1', 'proxy2']になります。
Koaは回避策を2つ提供しています。
リバースプロキシを制御できる場合は、設定を調整することで回避策を回避するか、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' ];サブドメインを配列として返します。
サブドメインとは、アプリのメインドメインの前にあるホストのドット区切り部分です。デフォルトでは、アプリのドメインはホストの最後の2つの部分と見なされます。これはapp.subdomainOffsetを設定することで変更できます。
例えば、ドメインが"tobi.ferrets.example.com"の場合:app.subdomainOffsetが設定されていない場合、ctx.subdomainsは["ferrets", "tobi"]です。app.subdomainOffsetが3の場合、ctx.subdomainsは["tobi"]です。
着信リクエストに"Content-Type"ヘッダーフィールドが含まれており、そのフィールドに指定されたMIMEtypeのいずれかが含まれているかどうかを確認します。リクエストボディがない場合は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)が許容されるかどうかを確認し、trueの場合は最適な一致を返し、それ以外の場合はfalseを返します。type値は、"application/json"などの1つ以上のMIMEタイプ文字列、"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文を使用することもできます。
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が許容されるかどうかを確認し、trueの場合は最適な一致を返し、それ以外の場合はfalseを返します。identityをエンコーディングの1つとして含める必要があります!
// 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が許容されるかどうかを確認し、trueの場合は最適な一致を返し、それ以外の場合は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"引数が指定されていない場合、すべての許容charsetが配列として返されます。
// 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が許容されるかどうかを確認し、trueの場合は最適な一致を返し、それ以外の場合は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"]リクエストがべき等であるかどうかを確認します。
リクエストソケットを返します。
大文字と小文字を区別しないfieldを使用してリクエストヘッダーを返します。
KoaのResponseオブジェクトは、Nodeの標準的なレスポンスオブジェクトの上位に構築された抽象化レイヤーであり、日常的なHTTPサーバー開発に役立つ追加機能を提供します。
レスポンスヘッダーオブジェクト。
レスポンスヘッダーオブジェクト。response.headerのエイリアスです。
レスポンスソケット。request.socketと同様にnet.Socketインスタンスを指します。
レスポンスステータスを取得します。デフォルトでは、Nodeのres.statusCodeが200をデフォルトとするのに対し、response.statusは404に設定されます。
数値コードでレスポンスステータスを設定します。
注記: これらの文字列を暗記する必要はありません。タイプミスがあればエラーがスローされ、このリストが表示されて修正できます。
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 JSON文字列化null || undefined コンテンツなしのレスポンスresponse.status が設定されていない場合、Koa は response.body に応じてステータスを 200 または 204 に自動的に設定します。具体的には、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 イベントのリスナーとして自動的に追加されます。さらに、リクエストが閉じられると(早期に閉じられた場合でも)、ストリームは破棄されます。これらの2つの機能を必要としない場合は、ストリームをボディに直接設定しないでください。たとえば、プロキシでボディを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');値 val を持つ追加のヘッダー field を追加します。
ctx.append('Link', '<http://127.0.0.1/>');オブジェクトを使用して、いくつかのレスポンスヘッダー fields を設定します。
ctx.set({
'Etag': '1234',
'Last-Modified': date
});これは、setHeader に委譲され、指定されたキーでヘッダーを設定または更新し、ヘッダー全体をリセットしません。
ヘッダー field を削除します。
"charset"などのパラメータのないレスポンスContent-Typeを取得します。
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" は、参照元が存在しない場合、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 として返します。
適切なUTC文字列としてLast-Modifiedヘッダーを設定します。Dateまたは日付文字列として設定できます。
ctx.response.lastModified = new Date();ラップされた"を含むレスポンスのETagを設定します。対応するresponse.etagゲッターはありません。
ctx.response.etag = crypto.createHash('md5').update(ctx.body).digest('hex');field で変更します。
設定されたヘッダーをフラッシュし、ボディを開始します。