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コンテナガイド
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コンテキストインスタンスを取得しています。
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.routeとctx.paramsの値は未定義になります。ただし、テスト対象のコードで必要な場合は、これらのプロパティを手動で割り当てることもできます。
import testUtils from '@adonisjs/core/services/test_utils'
const ctx = testUtils.createHttpContext()
デフォルトでは、createHttpContextメソッドはreqとresオブジェクトに対してダミーの値を使用します。ただし、次の例に示すように、これらのプロパティにカスタム値を定義することもできます。
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()