axios-fluentで型安全なHTTPクライアントをメソッドチェーンで構築する

axios-fluentで型安全なHTTPクライアントをメソッドチェーンで構築する

axios-fluent を使って、メソッドチェーンで型安全なHTTPクライアントを構築する方法を紹介します。イミュータブルな設計や .data() / .ok() 等の便利メソッド、AxonError によるエラーハンドリングなど、実践的な使い方をコード例とともに解説します。
2026.07.24

はじめに

HTTPクライアントのコードを書いていると、設定の組み立てが冗長になりがちです。ベースURL、認証ヘッダー、Content-Type、タイムアウト...これらを毎回 axios.create() のオプションオブジェクトで管理するのは、コードの見通しが悪くなります。

axios-fluent は、Axiosをラップしてメソッドチェーンで設定を組み立てられるようにしたTypeScript製のHTTPクライアントライブラリです。Fluent Interface パターンにより、リクエストの構築から結果の取得までを一連のチェーンで書けます。

今回はこのライブラリを使って、実際にAPIクライアントを構築してみました。

https://www.npmjs.com/package/axios-fluent

前提・環境

  • Node.js 20以上
  • TypeScript 5.x
  • axios 1.x(peerDependency)
  • axios-fluent 2.1.1

インストール

pnpm add axios-fluent

axiosは peerDependency として定義されているため、プロジェクトにaxiosがまだない場合は一緒にインストールします。

pnpm add axios axios-fluent

基本的な使い方

クライアントの作成とGETリクエスト

import Axon from "axios-fluent";

const client = Axon.new();

// 従来のAxiosと同じように使える
const response = await client.get("https://api.example.com/users");
console.log(response.data);

Axon.new() でインスタンスを作成し、get() でリクエストを送ります。ここまでは普通のAxiosと変わりません。

.data() で結果を直接取得する

axios-fluent の便利な点は、レスポンスから必要な部分だけを取り出すメソッドが用意されていることです。

interface User {
  id: number;
  name: string;
  email: string;
}

// .data() でレスポンスボディだけを取得
const users = await client.get<User[]>("https://api.example.com/users").data();
console.log(users); // User[] 型として取得できる

従来の response.data を取り出すパターンと比べて、コードがすっきりします。

axios-fluent-type-safe-http-client-response

他にも以下のメソッドが使えます。

// baseUrl 設定済みのクライアントの場合
// ステータスコードだけ取得
const status = await client.get("/users").status(); // 200

// レスポンスヘッダーだけ取得
const headers = await client.get("/users").headers();

// 2xx かどうかを確認
const isOk = await client.delete("/users/123").ok(); // true

メソッドチェーンで設定を組み立てる

このライブラリの中心的な機能がメソッドチェーンです。リクエストの設定を宣言的に積み重ねていけます。

const users = await Axon.new()
  .baseUrl("https://api.example.com")
  .bearer("your-jwt-token")
  .json()
  .timeout(5000)
  .params({ page: 1, limit: 20 })
  .get<User[]>("/users")
  .data();

設定メソッドはすべて新しい Axon インスタンスを返します。つまりイミュータブルです。ベースとなるクライアントを作っておき、リクエストごとに設定を追加する使い方ができます。

axios-fluent-type-safe-http-client-immutable

// 共通設定を持つベースクライアント
const base = Axon.new()
  .baseUrl("https://api.example.com")
  .json()
  .timeout(10000);

// 認証が必要なリクエスト用
const authed = base.bearer("your-token");

// 認証なしのリクエスト用(base は変更されない)
const publicData = await base.get<PublicInfo>("/public/info").data();

// 認証ありのリクエスト用
const privateData = await authed.get<PrivateInfo>("/me").data();

設定が副作用を持たないので、クライアントの使い回しが安全に行えます。

設定メソッド一覧

主な設定メソッドをまとめます。

認証

client.bearer("jwt-token");        // Authorization: Bearer xxx
client.basic(btoa("user:pass"));   // Authorization: Basic xxx

Content-Type

client.json();       // application/json
client.multipart();  // multipart/form-data
client.encodeUrl();  // application/x-www-form-urlencoded
client.octet();      // application/octet-stream

その他

client.setHeader("X-API-Key", "secret"); // カスタムヘッダー
client.params({ page: 1 });              // クエリパラメータ
client.timeout(5000);                    // タイムアウト (ms)
client.responseType("blob");             // レスポンスタイプ

エラーハンドリング

axios-fluent では、Axiosのエラーが自動的に AxonError にラップされます。エラーの主要な情報に5つのプロパティでアクセスできます。

import Axon, { AxonError } from "axios-fluent";

try {
  await Axon.new()
    .baseUrl("https://api.example.com")
    .get("/users/999")
    .data();
} catch (error) {
  if (error instanceof AxonError) {
    console.log(error.status);       // 404
    console.log(error.statusText);   // "Not Found"
    console.log(error.url);          // "/users/999"
    console.log(error.method);       // "GET"
    console.log(error.responseData); // レスポンスボディ

    // toString() でフォーマット済みメッセージを取得
    console.log(error.toString());
    // AxonError: Request failed with status code 404
    //   Request: GET /users/999
    //   Status: 404 Not Found
    //   Response: {"message":"User not found"}
  }
}

ステータスコードに応じた分岐も直感的です。

if (error instanceof AxonError) {
  if (error.status === 401) {
    // トークンのリフレッシュ処理
  } else if (error.status && error.status >= 500) {
    // サーバーエラー - リトライ処理
  }
}

実践例: APIクライアントクラスを作る

実際のプロジェクトで使う形で、APIクライアントクラスを組んでみます。

import Axon, { AxonError } from "axios-fluent";

interface User {
  id: number;
  name: string;
  email: string;
}

class UserApiClient {
  private client: Axon;

  constructor(baseUrl: string, token: string) {
    this.client = Axon.new()
      .baseUrl(baseUrl)
      .bearer(token)
      .json()
      .timeout(10000);
  }

  async getUser(id: number): Promise<User> {
    return this.client.get<User>(`/users/${id}`).data();
  }

  async listUsers(page = 1, limit = 20): Promise<User[]> {
    return this.client
      .params({ page, limit })
      .get<User[]>("/users")
      .data();
  }

  async createUser(user: Omit<User, "id">): Promise<User> {
    return this.client.post<User>("/users", user).data();
  }

  async deleteUser(id: number): Promise<boolean> {
    return this.client.delete(`/users/${id}`).ok();
  }
}
// 使い方
const api = new UserApiClient("https://api.example.com", "your-token");

const user = await api.getUser(1);
console.log(user.name);

const deleted = await api.deleteUser(1);
console.log(deleted); // true

設定メソッドのイミュータブル性のおかげで、listUsers のように params() を呼んでも、this.client の状態は変わりません。各メソッドが独立して動作します。

ファイルアップロード

multipart() とFormDataを組み合わせてファイルアップロードも可能です。

import Axon from "axios-fluent";
import FormData from "form-data";

const formData = new FormData();
formData.append("file", fileBuffer, "document.pdf");

await Axon.new()
  .baseUrl("https://api.example.com")
  .bearer("token")
  .multipart()
  .post("/upload", formData);

開発用モード

開発環境で自己署名証明書を使う場合は、Axon.dev() でSSL検証を無効化できます。

// 開発環境用 - 自己署名証明書を許可
const devClient = Axon.dev();

// 本番環境ではデフォルトのまま(SSL検証有効)
const prodClient = Axon.new();

Axon.dev()Axon.new({ allowInsecure: true }) のショートカットです。本番環境では絶対に使わないよう注意してください。

設計上の特徴

実装を読んで気づいた設計上のポイントをいくつか挙げます。

イミュータブルな設定

各設定メソッドは内部で新しい Axon インスタンスを生成して返します。元のインスタンスは変更されないため、ベースクライアントを安全に再利用できます。

後方互換性

get()post() の戻り値は AxonResponse<T> というラッパーですが、PromiseLike を実装しています。そのため await client.get("/url") とすれば従来通り AxiosResponse が返ります。.data() などの新しいメソッドはオプトインで使えるので、既存コードを壊しません。

AxonErrorによる構造化エラー

Axiosのエラーオブジェクトから必要な情報だけを抽出した5プロパティ(status, statusText, url, method, responseData)に絞ることで、エラーハンドリングのコードがシンプルになります。

まとめ

axios-fluent を使ってHTTPクライアントを構築してみました。

  • メソッドチェーンにより、リクエストの設定を宣言的かつ読みやすく書ける
  • .data() / .status() / .ok() でレスポンスの必要な部分だけを簡潔に取り出せる
  • イミュータブルな設計で、ベースクライアントの安全な再利用が可能
  • AxonError によるエラーハンドリングの簡素化
  • 既存のAxiosコードとの後方互換性あり

Axiosを使っていてボイラープレートが気になっている方や、型安全なHTTPクライアントを手軽に構築したい方におすすめです。

https://github.com/oharu121/axios-fluent

この記事をシェアする

関連記事