http-clients について
http-clients は、TypeScript で HTTP クライアントを実装する開発者向けのリファレンススキルです。Axios、Fetch API、ky、ofetch の設定例に加え、本番向けチェック項目とトラブルシューティングを扱います。
主な機能
- 01Axios の設定例
- 02Fetch API のラッパーパターン
- 03ky と ofetch の設定
- 04HTTP クライアントのアンチパターン
- 05本番チェックリストとトラブルシューティング
活用シーン
- 01TypeScript の HTTP クライアントを設定する
- 02掲載されたクライアントパターンから選ぶ
- 03API クライアントの本番準備を確認する
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ claude-dev-suite/ claude-dev-suite --skill http-clientsインストール後、Claude Code で/http-clientsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
advanced.mdquick-ref/axios.mderror-handling.mdfetch.mdinterceptors.mdky-ofetch.md詳細
HTTP クライアントの基礎知識
完全なリファレンス:トークンのリフレッシュフロー、指数バックオフによる再試行、リクエストのキャンセル、型安全な API クライアントのパターンについては、advanced.md を参照してください。
詳細なナレッジ:包括的なドキュメントについては、technology に
http-clientsを指定してmcp__documentation__fetch_docsを使用してください。
Axios のセットアップ
import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios';
const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
timeout: 10000,
headers: { 'Content-Type': 'application/json' },
});
// Request interceptor - add auth token
api.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const token = localStorage.getItem('accessToken');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// Response interceptor - handle errors
api.interceptors.response.use(
(response) => response,
(error: AxiosError) => {
if (error.response?.status === 401) {
window.location.href = '/login';
}
return Promise.reject(error);
}
);
Fetch API ラッパー
class ApiError extends Error {
constructor(public status: number, public statusText: string, public data?: unknown) {
super(`${status}: ${statusText}`);
}
}
async function fetchWithTimeout(url: string, options: RequestInit & { timeout?: number } = {}): Promise<Response> {
const { timeout = 10000, ...fetchOptions } = options;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
return await fetch(url, { ...fetchOptions, signal: controller.signal });
} finally {
clearTimeout(timeoutId);
}
}
export async function apiFetch<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
const token = localStorage.getItem('accessToken');
const headers: HeadersInit = {
'Content-Type': 'application/json',
...(token && { Authorization: `Bearer ${token}` }),
};
const response = await fetchWithTimeout(`${API_URL}${endpoint}`, { ...options, headers });
if (!response.ok) {
throw new ApiError(response.status, response.statusText);
}
return response.json();
}
ky(モダンな Fetch ラッパー)
import ky from 'ky';
const api = ky.create({
prefixUrl: process.env.NEXT_PUBLIC_API_URL,
timeout: 10000,
retry: {
limit: 2,
methods: ['get', 'put', 'delete'],
statusCodes: [408, 429, 500, 502, 503, 504],
},
hooks: {
beforeRequest: [
(request) => {
const token = localStorage.getItem('accessToken');
if (token) {
request.headers.set('Authorization', `Bearer ${token}`);
}
},
],
},
});
// Usage
const users = await api.get('users').json<User[]>();
const user = await api.post('users', { json: newUser }).json<User>();
ofetch(汎用 Fetch)
import { ofetch } from 'ofetch';
const api = ofetch.create({
baseURL: process.env.NUXT_PUBLIC_API_URL,
retry: 2,
retryDelay: 500,
timeout: 10000,
async onRequest({ options }) {
const token = localStorage.getItem('accessToken');
if (token) {
options.headers = { ...options.headers, Authorization: `Bearer ${token}` };
}
},
});
// Works in Node.js and browser
const users = await api<User[]>('/users');
このスキルを使用しないケース
- Axios 固有の設定(
axiosスキルを使用) - GraphQL クライアントのセットアップ(
graphql-codegenスキルを使用) - tRPC クライアントの設定(
trpcスキルを使用) - WebSocket または Server-Sent Events
アンチパターン
| アンチパターン | 問題点 | 解決策 |
|---|---|---|
| タイムアウトが未設定 | リクエストがハングする | すべてのクライアントにタイムアウトを設定する |
| API URL のハードコード | 環境への依存 | 環境変数を使用する |
| 再試行ロジックがない | 一時的な障害で UX が低下する | 指数バックオフを実装する |
| トークンの有効期限を無視する | 401 エラーが発生する | トークンのリフレッシュフローを実装する |
| アンマウント時にキャンセルしない | メモリーリークが発生する | AbortController のクリーンアップを使用する |
| レスポンスに型を指定しない | 実行時エラーが発生する | TypeScript のジェネリクスを使用する |
トラブルシューティング(クイックリファレンス)
| 問題 | 考えられる原因 | 解決策 |
|---|---|---|
| CORS エラー | サーバーの設定ミス | バックエンドで CORS を設定する |
| しばらくすると 401 が発生する | トークンの有効期限切れ | トークンのリフレッシュを実装する |
| メモリーリーク | アンマウント時に中断していない | useEffect にクリーンアップを追加する |
| ネットワークタイムアウト | サーバーの応答が遅い | タイムアウトを延長し、再試行を追加する |
| リフレッシュが無限ループする | リフレッシュが 401 を返す | インターセプターからリフレッシュを除外する |
本番環境向けチェックリスト
- 環境変数でベース URL を設定する
- リクエストのタイムアウトを設定する
- 認証トークンのインターセプターを設定する
- トークンのリフレッシュロジックを実装する
- エラーレスポンスを処理する
- 指数バックオフによる再試行を実装する
- アンマウント時にリクエストをキャンセルする
- 型安全な API メソッドを使用する
リファレンスドキュメント
コメント
Markdown 対応