インターセプター
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')を使用してInternalAxiosRequestConfigにmetadata?: { 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箇所で実行します。複数のファイルに分散して登録しません。