はじめに
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.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の実装は、関数のシリーズを通して制御を渡すだけで、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-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の表現ではありません。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.statusCode
res.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.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
オブジェクトは、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
で変更します。
設定されたヘッダーをフラッシュし、ボディを開始します。