Skip to content

インターセプター

14.2.1. リクエストインターセプター

  • リクエストインターセプターは、すべてのAPIリクエストがサーバーに送信される前に実行されます。
  • 認証トークンはリクエストインターセプターでAuthorizationヘッダーに自動注入します。
  • トークン注入ロジックはsrc/api/interceptors/auth.tsに分離して管理します。
typescript
// src/api/interceptors/auth.ts
import type { InternalAxiosRequestConfig } from 'axios'
import { useAuthStore } from '@/stores/useAuthStore'

export function attachAuthToken(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
  const authStore = useAuthStore()
  const token = authStore.accessToken

  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }

  return config
}

14.2.2. レスポンスインターセプター

  • レスポンスインターセプターは、サーバーレスポンスをコンポーネントに渡す前に実行されます。
  • エラーレスポンスはインターセプターで標準形式に変換します。
typescript
// src/api/interceptors/error.ts
import type { AxiosError } from 'axios'
import type { ApiError } from '@/types/api'

export function handleResponseError(error: AxiosError<ApiError>): Promise<never> {
  if (!error.response) {
    return Promise.reject({
      status: 0,
      message: 'ネットワーク接続を確認してください。',
      code: 'NETWORK_ERROR',
    })
  }

  const { status, data } = error.response

  return Promise.reject({
    status,
    message: data?.message ?? '不明なエラーが発生しました。',
    code: data?.code ?? 'UNKNOWN_ERROR',
  })
}

14.2.3. ロギングインターセプター

  • 開発環境ではリクエストおよびレスポンス情報をコンソールに出力します。
  • プロダクション環境ではロギングインターセプターを登録しません。
typescript
// src/api/interceptors/logger.ts
import type { InternalAxiosRequestConfig, AxiosResponse } from 'axios'

export function logRequest(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
  config.metadata = { startTime: Date.now() }
  console.log(`[API Request] ${config.method?.toUpperCase()} ${config.url}`)
  return config
}

export function logResponse(response: AxiosResponse): AxiosResponse {
  const duration = Date.now() - (response.config.metadata?.startTime ?? 0)
  console.log(`[API Response] ${response.config.url} → ${response.status} (${duration}ms)`)
  return response
}
  • config.metadataの型はモジュール拡張(declare module 'axios')を使用してInternalAxiosRequestConfigmetadata?: { startTime: number }プロパティを追加して宣言します。
  • 条件付き登録にはimport.meta.env.DEVを使用します。

14.2.4. インターセプターの構成順序

  • リクエストインターセプターは後に登録されたものが先に実行されます(LIFO)。レスポンスインターセプターは先に登録されたものが先に実行されます(FIFO)。順序がロジックに影響するため、必ず意図した順序で登録しなければなりません。
区分実行順序推奨登録順序
リクエストインターセプターLIFO(後入先出)ロギング → 認証トークン注入
レスポンスインターセプターFIFO(先入先出)エラー変換 → ロギング
typescript
// src/api/client.ts(最終登録順序)
if (import.meta.env.DEV) {
  apiClient.interceptors.request.use(logRequest)
}
apiClient.interceptors.request.use(attachAuthToken)

apiClient.interceptors.response.use((res) => res, handleResponseError)
if (import.meta.env.DEV) {
  apiClient.interceptors.response.use(logResponse)
}
  • インターセプターファイルはsrc/api/interceptors/ディレクトリに機能別に分離します。
  • インターセプターの登録はsrc/api/client.tsの1箇所で実行します。複数のファイルに分散して登録しません。

TIENIPIA QUALIFIED STANDARD