HTTP コンテキスト

HTTPコンテキスト

HTTPコンテキストクラスの新しいインスタンスは、各HTTPリクエストごとに生成され、ルートハンドラ、ミドルウェア、例外ハンドラに渡されます。

HTTPコンテキストには、HTTPリクエストに関連するすべての情報にアクセスできます。例えば:

  • ctx.requestプロパティを使用して、リクエストボディ、ヘッダー、クエリパラメータにアクセスできます。
  • ctx.responseプロパティを使用して、HTTPリクエストに応答できます。
  • ctx.authプロパティを使用して、ログインしているユーザーにアクセスできます。
  • ctx.bouncerプロパティを使用して、ユーザーアクションを承認できます。
  • などなど。

要するに、コンテキストは進行中のリクエストのための情報を保持するリクエスト固有のストアです。

HTTPコンテキストへのアクセス方法

HTTPコンテキストは、ルートハンドラ、ミドルウェア、例外ハンドラに参照として渡され、次のようにアクセスできます。

ルートハンドラ

ルーターハンドラは、HTTPコンテキストを最初のパラメータとして受け取ります。

import router from '@adonisjs/core/services/router'
router.get('/', (ctx) => {
console.log(ctx.inspect())
})
プロパティの分割代入
import router from '@adonisjs/core/services/router'
router.get('/', ({ request, response }) => {
console.log(request.url())
console.log(request.headers())
console.log(request.qs())
console.log(request.body())
response.send('hello world')
response.send({ hello: 'world' })
})

コントローラメソッド

コントローラメソッド(ルーターハンドラと似ています)は、HTTPコンテキストを最初のパラメータとして受け取ります。

import { HttpContext } from '@adonisjs/core/http'
export default class HomeController {
async index({ request, response }: HttpContext) {
}
}

ミドルウェアクラス

ミドルウェアクラスhandleメソッドは、HTTPコンテキストを最初のパラメータとして受け取ります。

import { HttpContext } from '@adonisjs/core/http'
export default class AuthMiddleware {
async handle({ request, response }: HttpContext) {
}
}

例外ハンドラクラス

グローバル例外ハンドラクラスのhandleメソッドとreportメソッドは、HTTPコンテキストを2番目のパラメータとして受け取ります。最初のパラメータはerrorプロパティです。

import {
HttpContext,
HttpExceptionHandler
} from '@adonisjs/core/http'
export default class ExceptionHandler extends HttpExceptionHandler {
async handle(error: unknown, ctx: HttpContext) {
return super.handle(error, ctx)
}
async report(error: unknown, ctx: HttpContext) {
return super.report(error, ctx)
}
}

依存性の注入を使用してHTTPコンテキストを注入する

アプリケーション全体で依存性の注入を使用する場合、HttpContextクラスを型ヒントとしてクラスやメソッドに注入することで、HTTPコンテキストを注入できます。

kernel/start.tsファイル内で#middleware/container_bindings_middlewareミドルウェアが登録されていることを確認してください。このミドルウェアは、コンテナからリクエスト固有の値(つまり、HttpContextクラス)を解決するために必要です。

参照:IoCコンテナガイド

app/services/user_service.ts
import { inject } from '@adonisjs/core'
import { HttpContext } from '@adonisjs/core/http'
@inject()
export default class UserService {
constructor(protected ctx: HttpContext) {}
all() {
// メソッドの実装
}
}

自動的な依存関係の解決が機能するためには、コントローラ内でUserServiceをインジェクトする必要があります。覚えておいてください、コントローラメソッドの最初の引数は常にコンテキストであり、残りの引数はIoCコンテナを使用して注入されます。

import { inject } from '@adonisjs/core'
import { HttpContext } from '@adonisjs/core/http'
import UserService from '#services/user_service'
export default class UsersController {
@inject()
index(ctx: HttpContext, userService: UserService) {
return userService.all()
}
}

以上です!UserServiceは今や自動的に進行中のHTTPリクエストのインスタンスを受け取るようになりました。同じプロセスをネストされた依存関係に対しても繰り返すことができます。

アプリケーション内のどこからでもHTTPコンテキストにアクセスする

依存性の注入は、クラスのコンストラクタやメソッドの依存関係としてHTTPコンテキストを受け入れ、コンテナに解決させる方法の1つです。

ただし、アプリケーションを再構築して依存性の注入を使用することは必須ではありません。Node.jsが提供するAsyncローカルストレージを使用して、アプリケーション内のどこからでもHTTPコンテキストにアクセスすることもできます。

Asyncローカルストレージの動作方法とAdonisJSがHTTPコンテキストへのグローバルアクセスを提供するためにそれを使用する方法については、専用のガイドを参照してください。

次の例では、UserServiceクラスはHttpContext.getOrFailメソッドを使用して、進行中のリクエストのHTTPコンテキストインスタンスを取得しています。

app/services/user_service.ts
import { HttpContext } from '@adonisjs/core/http'
export default class UserService {
all() {
const ctx = HttpContext.getOrFail()
console.log(ctx.request.url())
}
}

次のコードブロックは、UsersController内でUserServiceクラスを使用する例を示しています。

import { HttpContext } from '@adonisjs/core/http'
import UserService from '#services/user_service'
export default class UsersController {
index(ctx: HttpContext) {
const userService = new UserService()
return userService.all()
}
}

HTTPコンテキストのプロパティ

以下は、HTTPコンテキストを介してアクセスできるプロパティのリストです。新しいパッケージをインストールすると、追加のプロパティがコンテキストに追加される場合があります。

ctx.request

HTTPリクエストクラスのインスタンスへの参照。

ctx.response

HTTPレスポンスクラスのインスタンスへの参照。

ctx.logger

HTTPリクエストごとに作成されるロガーのインスタンスへの参照。

ctx.route

現在のHTTPリクエストにマッチしたルート。routeプロパティはStoreRouteNode型のオブジェクトです。

ctx.params

ルートパラメータのオブジェクト

ctx.subdomains

ルートが動的サブドメインの一部である場合にのみ存在するルートサブドメインのオブジェクト

ctx.session

現在のHTTPリクエストに作成されたセッションのインスタンスへの参照。

ctx.auth

Authenticatorクラスのインスタンスへの参照。認証について詳しくはこちらをご覧ください。

ctx.view

Edgeレンダラーのインスタンスへの参照。ビューとテンプレートガイドでEdgeについて詳しく学びましょう。

ctx.ally

アプリケーションでソーシャルログインを実装するためのAlly Managerクラスのインスタンスへの参照。Allyについて詳しくはこちらをご覧ください。

ctx.bouncer

Bouncerクラスのインスタンスへの参照。認可について詳しくはこちらをご覧ください。

ctx.i18n

I18nクラスのインスタンスへの参照。Internationalizationガイドでi18nについて詳しく学びましょう。

HTTPコンテキストの拡張

マクロやゲッターを使用して、HTTPコンテキストクラスにカスタムプロパティを追加できます。マクロの概念については、AdonisJSの拡張ガイドを読んでから進めるようにしてください。

import { HttpContext } from '@adonisjs/core/http'
HttpContext.macro('aMethod', function (this: HttpContext) {
return value
})
HttpContext.getter('aProperty', function (this: HttpContext) {
return value
})

マクロとゲッターは実行時に追加されるため、モジュール拡張を使用してその型をTypeScriptに伝える必要があります。

import { HttpContext } from '@adonisjs/core/http'
declare module '@adonisjs/core/http' {
export interface HttpContext {
aMethod: () => ValueType
aProperty: ValueType
}
}
HttpContext.macro('aMethod', function (this: HttpContext) {
return value
})
HttpContext.getter('aProperty', function (this: HttpContext) {
return value
})

テスト中にダミーコンテキストを作成する

テスト中にダミーのHTTPコンテキストを作成するには、testUtilsサービスを使用できます。

コンテキストインスタンスはどのルートにも関連付けられていないため、ctx.routectx.paramsの値は未定義になります。ただし、テスト対象のコードで必要な場合は、これらのプロパティを手動で割り当てることもできます。

import testUtils from '@adonisjs/core/services/test_utils'
const ctx = testUtils.createHttpContext()

デフォルトでは、createHttpContextメソッドはreqresオブジェクトに対してダミーの値を使用します。ただし、次の例に示すように、これらのプロパティにカスタム値を定義することもできます。

import { createServer } from 'node:http'
import testUtils from '@adonisjs/core/services/test_utils'
createServer((req, res) => {
const ctx = testUtils.createHttpContext({
req,
res
})
})

HttpContextファクトリの使用

testUtilsサービスはAdonisJSアプリケーション内でのみ利用可能です。したがって、パッケージをビルドしてテスト中にダミーのHTTPコンテキストにアクセスする必要がある場合は、HttpContextFactoryクラスを使用できます。

import { HttpContextFactory } from '@adonisjs/core/factories/http'
const ctx = new HttpContextFactory().create()