Axios とは?
Axios とは、自分のサーバーやサードパーティのサーバーに対して、データをフェッチするリクエストを行うことができる Promise ベースの HTTP ライブラリです。GET
、POST
、PUT/PATCH
、DELETE
などのリクエストを、さまざまな方法で行うことができます。このチュートリアルでは、Axios とアプリケーションのやり取りのしくみ、Axios のリクエストと応答の構造、API に対するリクエストを作成する方法、CircleCI を使ったリクエストのテスト作成方法について説明します。
前提条件
このチュートリアルを進めるには、以下の準備が必要です。
- NodeJS をローカルシステムにインストールする
- GitHub アカウントを作成する
- CircleCI アカウントを作成する
- JavaScript と単体テストの基本を理解する
Axios のしくみ
Axios では、NodeJS (サーバー側) と XMLHttpRequest (ブラウザー側) を使って HTTP リクエストを実行します。リクエストが成功すると、リクエストしたデータを含む応答
が返されます。リクエスト
が失敗すると、エラーが返されます。リクエストと応答をインターセプト
し、変換や編集することもできます。詳しくは、このチュートリアルの後半で説明します。
以下の図に、Axios とアプリケーションのやり取りのしくみを示します。
Axios はまず、リクエストがブラウザーと NodeJS のどちら宛てかを判断します。判断に応じて適切な API リクエストの方法を決定し、応答を変換して、サーバーリクエストの送信元のクライアントに返します。
Axios のリクエストと応答の構成
Axios の基本リクエストは、必須オプションが url
だけなので簡単に作成できます。送信するリクエストの種類に応じて、他のオプションも設定します。
以下にリクエストの例を示します。
const axios = require('axios');
const res = await axios.get(url, {
//We can add more configurations in this object
params: {
//This is one of the many options we can configure
}
});
// This is the second configuration option
const res = await axios({
method: 'get',
url://Endpoint goes here,
params:{
}
});
Axios のメリットは、リクエストを非常に柔軟に構成できることです。Axios は、JavaScript のドット区切り表記での呼び出しに対応しています。また、オブジェクトリテラル形式で Axios のリクエストプロパティすべてを 1 つのオブジェクトにバンドルし、Axios リクエストの構成プロパティとして使用することもできます。
Axios では、リクエストの送信メソッドが、以下のように複数サポートされています。
request
get
delete
head
options
post
put
patch
次のコードスニペットでは、Axios を使ってサンプルの GET
リクエストを Todos
というサンプル API に送信しています。
axios({
method: "get",
url: "https://jsonplaceholder.typicode.com/todos",
params: {
_limit: 5,
},
});
Axios の応答
Axios を使ってリクエストを送信したら、当然のことながら応答が返ってきます。以下のスニペットに、Axios の応答のデータ構造を示します。
{
// `data` is the response that was provided by the server
data: {},
// `status` is the HTTP status code from the response
status: 200,
// `statusText` is the status message from the response
statusText: 'OK',
// `headers` are the HTTP headers that the server responded with
headers: {},
// `config` is the config that was provided to `axios` for the request
config: {},
// `request` is the request that generated the response
request: {}
}
この応答には、以下の情報が含まれています。
- リクエストしたデータが含まれるオブジェクト
- サーバーから返されたステータスコード
- statusText
- 応答ヘッダー
- Axios で設定された config オブジェクト
- 応答の生成に使用された request オブジェクト
必要なデータに応じて、クライアント側アプリケーションでこの応答を処理します。
理論の説明ばかりで退屈でしょうか?それでは、次のセクションに進みましょう。Axios を使って HTTP リクエストを行う方法を具体的にご説明します。
Axios を使って HTTP リクエストを実行する
このセクションでは、GET
と POST
リクエストを実行し、同時リクエストを観察します。これには、JSONPlaceholder.という無料の “フェイク” API を利用します。
また、リクエストの実行と、Axios 内部での処理を把握するのに役立つアプリケーションも利用します。
作業を始める前に、チュートリアル用の GitHub リポジトリをクローンしてください。以下のコマンドを実行します。
git clone https://github.com/CIRCLECI-GWP/making-http-requests-axios
cd making-http-requests-axios
これで、このチュートリアルに必要なファイルが手に入りました。次に、依存関係として Axios と Jest の 2 つをインストールします。以下のコマンドを実行します。
npm install
ブラウザーで index.html
ファイルを開き、Axios デモ用 Web ページを確認します。
現時点では、ボタンには何の機能もありません。チュートリアルの後半で、それぞれの機能を作成します。
現状は、各リクエストに対応した 3 つのボタンがあります。ボタンをクリックしたら、Axios リクエストが実行され、ブラウザーにデータが返されて、応答が表示されるようにします。
クローンしたリポジトリの users.js
ファイルに、Axios から返されたデータを表示するためのイベントリスナーがあります。このファイルには、リクエストを行うための関数も含まれています。まず、GET
リクエストから始めましょう。
GET リクエストを実行する
今回は、以下のスニペットに示すリクエストを使用します。
axios
.get("https://jsonplaceholder.typicode.com/users/1")
.then((response) => {
displayOutput(response);
})
.catch((err) => console.log(err));
このコードスニペットでは、まず、GET
リクエストを JSON API に送信します。リクエストから promise が返されるので、応答の処理には .then()
ブロックを使用しています。また、エラーが起きた場合にコンソールに記録するため、.catch()
メソッドも必要です。
上記のコードスニペットを、users.js
ファイルの getUser()
関数に追加して保存します。
その後、ブラウザーに移動し、[GET
] ボタンをクリックしてみましょう。ボタンの下に、応答の詳細を示すコンテンツが表示されれば成功です。
スタイルや表示形式はあらかじめこちらで用意したものです。返される Axios の応答のセクションには、以下のものがあります。
-
Status
セクション: 応答のステータスコードを表示します。今回はステータスコードが200
であり、リクエストが成功したことを意味しています。 Headers
セクション: サーバーからの応答に含まれるすべての HTTP ヘッダーが示されます。Data
セクション: リクエストでサーバーから返されたペイロード (情報) が示されます。この例の場合、user 1
に関するすべての情報です。Config
セクション: このリクエストで Axios に渡されたすべての設定が示されます。
リクエストからわかるように、Axios の動作は従来の fetch-API
ライブラリと同様です。今回は GET
リクエストだったので、リクエストと一緒に本文を渡す必要はありませんでした。次は、Axios を使用して POST
リクエストを実行する方法について説明します。
POST リクエストを実行する
POST リクエストは、サーバーへのリクエストでデータを渡す点で GET リクエストとは少し異なります。ここでは、POST リクエストを使ってユーザーを作成し、そのユーザーに関する詳細情報を渡します。このリクエストのコードスニペットは、以下のとおりです。
axios
.post("https://jsonplaceholder.typicode.com/users", {
id: 11,
name: "Tom Brady",
username: "Brad",
email: "tombrad@asd.com",
})
.then((response) => displayOutput(response))
.catch((err) => console.log(err));
Axios を使った POST リクエストでは、リクエスト URL の後でオブジェクトを使用して、ユーザーの作成に必要なプロパティを定義します。処理が完了すると、サーバーから応答が返ります。作成したコードが機能することを確認するために、デモ用 Web ページに戻って、[POST] ボタンをクリックします。このコードスニペットは、users.js
ファイルの postUser()
関数の一部です。
POST
リクエストでは、GET
リクエストとは異なる以下のような応答が返されます。
-
Status
セクション: リソースが作成されたことを意味する、ステータスコード201
が示されます。この例では、新しいユーザーが作成されました。 -
Headers
セクション: 送信したデータの長さが‘content-length’
プロパティに示されます。また、location
にデータの保存先が示されます。 -
Data
セクション: サーバーに送信した情報が示されます。 -
Config
セクション: リクエストと一緒に送信した設定が含まれます。具体的には、メソッド
、URL
、送信したデータ
などです。
POST
リクエストで定義したデータと、サーバーから受信した応答 (リクエストにより作成されたリソース) が同じであることを確認してください。
このセクションでは、Axios リクエストを実行する方法、Axios リクエストの基本構造、想定される応答について説明しました。次のセクションでは、リクエストをインターセプトして、データがリクエストとして Axios に送信される前に検証する方法について説明します。
Axios のリクエストと応答のインターセプター
Axios でリクエストのインターセプトを行うタイミングは、then()
コードブロックまたは catch()
コードブロックの処理の前です。たとえば、クライアントを経由するすべてのリクエストに、有効な JWT トークンが含まれるかどうかを調べるとしましょう。このためには、リクエストインターセプターを設定して、サーバーに対して行われるすべての呼び出しに有効なトークンが含まれることを確認します。有効なトークンが呼び出しに含まれていない場合は、システムのユーザーをログインページに戻し、再び認証を受けさせます。簡潔に説明するため、現在のアプリケーション用のロガーを作成するという、やや単純なユースケースを使います。
このロガーは、リクエストが実行されたら、リクエストの URL とトリガーされた時間を記録します。以下のコードスニペットを使用します。
axios.interceptors.request.use(
(config) => {
const today = new Date();
console.log(
`${config.method.toUpperCase()} request sent to ${
config.url
} at ${today.getHours()} : ${today.getMinutes()}`
);
return config;
},
(error) => {
console.log(error);
}
);
Axios がリクエストの config
セクションにアクセスして、リクエストのメソッド、URL、時間を表示します。このコードスニペットは、サンプルプロジェクトに含まれる users.js
ファイルの interceptRequests()
関数の一部です。Axios インターセプターの動作を観察するために、Chrome ブラウザーコンソールを開いてください。[GET
] ボタンをクリックして、API の最初のユーザーをフェッチするメソッドを実行しましょう。
インターセプターを機能させるには、jsonplaceholder
API に対する同時リクエストとして呼び出す必要があります。このリクエストと応答を実装する Axios メソッドを、以下のコードスニペットに示します。
const concurrentRequests = () => {
interceptRequests();
axios
.all([
axios.get("https://jsonplaceholder.typicode.com/users?_limit=5"),
axios.get("https://jsonplaceholder.typicode.com/albums?_limit=5"),
])
.then(
axios.spread((users, albums) => {
displayOutput(albums);
})
)
.catch((err) => console.log(err));
};
Chrome の DevTools の画像を見ると、リクエストを実行する際、Axios から API サーバーに送信する前に変更したり、検査したりできることがわかります。Axios インターセプターは、強力なだけではありません。リクエストや応答の動作の制御もできるのです。
インターセプターを使用して Axios のリクエストと応答を変更、検査する方法については以上です。おつかれさまでした!次は、Axios 実装に関するテストを作成しましょう。
Axios 実装をテストする
テストはアプリケーション開発に不可欠なプロセスです。テストを行うことにより、アプリケーションの動作が意図どおりであるかを確認し、常に高い品質を確保できます。チュートリアルの本セクションでは、Axios の node.js
バージョンを使用します。依存関係をインストールしたときに Jest もインストールしたので、すぐにテストの作成を始められます。
ルートディレクトリに、app.js
と app.test.js
という 2 つのファイルを作成します。app.js
はリクエスト、app.test.js
はテストに使用します。index.html
ファイルの script
セクションで定義されているブラウザー版の Axios ではなく、Node.js
版の Axios を使用するメソッドに確実にアクセスできるように、app.js
ファイルを作り直す必要があります。
Node.js
でリクエストを行うには、app.js
ファイルで axios
を使用します。このメソッドのリクエストの構造は、ブラウザー版のメソッドと同じです。
const axios = require("axios");
const getUser = async () => {
const getResponse = await axios
.get("https://jsonplaceholder.typicode.com/users/1")
.then((response) => response)
.catch((err) => console.log(err));
return getResponse;
module.export = { getUser };
};
このスニペットでは、まず、先ほどと同じ URL に対してリクエストを行い、応答を getResponse
変数に格納します。その後、この応答を必要とする他のメソッドや関数 (テストなど) がアクセスできるように、応答を返します。最後に、メソッドを、app.js
ファイル外部でも使用できるようにエクスポートします。
次に、getUser
メソッドに対するテストを作成するため、このメソッドを app.test.js
テストファイルにインポートします。その後、以下に示すとおりにテストを記述します。
const { getUser, postUser, concurrentRequests } = require("./app.js");
describe("Axios requests suite", () => {
test("should get a single user", async () => {
const response = await getUser();
expect(response).not.toBeNull();
expect(response.status).toBe(200);
expect(response.data.address.street).toContain("Kulas");
});
}
このテストとサンプル応答オブジェクトを使用すると、Axios エンドポイントから呼び出されたデータが返され、API 呼び出しに成功したことを検証できます。ターミナルに移動して Jest コマンド npm test
と入力し、このテストを実行しましょう。
PASS ./app.test.js
Axios requests suite
✓ should get a single user (144 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.266 s, estimated 1 s
Ran all test suites.
成功です!次は、Axios を使った POST
リクエストと同時リクエストを検証するためのテストも作成します。
テストファイルに以下のテストを追加します。
test("should post a new user", async () => {
const response = await postUser();
expect(response).not.toBeNull();
expect(response.status).toBe(201);
expect(response.data.username).toBe("Brad");
});
test("should make simultaneous axios requests", async () => {
const response = await concurrentRequests();
expect(response).not.toBeNull();
expect(response.status).toBe(200);
});
完成したら、テストを再実行します。
npm run test
このテストも成功です!
Axios リクエストの作成方法とテスト方法を学んだので、次は CI パイプラインを作成しましょう。CircleCI などの CI/CD ツールでは、変更によってパイプラインに問題が発生し、テストが失敗したときに、関係者に通知することができます。このようなフィードバックループを構築すると、ソフトウェア開発プロセスを順調に進めるうえで欠かせないインサイトと透明性が得られます。
CircleCI との統合
.circleci
フォルダーを作成して、その中に config.yml
ファイルを作成します。これが CircleCI の設定ファイルになります。このファイルに以下の設定を追加します。
version: 2.1
jobs:
build:
working_directory: ~/repo
docker:
- image: cimg/node:19.0.1
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: install dependencies
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
paths:
- ./node_modules
- run:
name: Axios request tests
command: npm run test
- store_artifacts:
path: ~/repo/axios-http-requests
この設定ファイルでは、working_directory
で作業ディレクトリを定義した後、テストの実行に使用する Node イメージを指定しています。その後、プロジェクトに保存済みキャッシュがあるかどうかを確認します。キャッシュがある場合は、復元してから新しい依存関係をインストールします。新しい依存関係をインストールした後は、キャッシュを保存します。その後、テストを実行し、生成されたアーティファクトを保存します。
では、この設定ファイルを保存し、コミットして、自分の GitHub リポジトリに変更をプッシュしましょう。その後、CirclecI ダッシュボードにログインします。[Projects (プロジェクト)] セクションで、このチュートリアルの GitHub リポジトリを探します。今回は、making-http-requests-axios
です。[Set Up Project (プロジェクトをセットアップ)] をクリックします。
プロンプトが表示されたら、config.yml
ファイルを配置したブランチの名前を入力します。このチュートリアルの場合、main
ブランチです。その後、[Set up Project (プロジェクトをセットアップ)] をクリックします。
パイプラインのビルドに成功しました。build
ワークフローをクリックして詳細を確認しましょう。
詳細を確認したいステップをクリックします。たとえば、Axios request tests
ステップを確認してみます。
CircleCI では、GitHub リポジトリの main
ブランチにプッシュが行われるたびに、変更を検出して、パイプラインを実行します。これにより、テストスイートを毎回確実に実行して、継続的インテグレーションプロセスを順調に進められます。
この Axios チュートリアルは作成しがいのあるものでした。みなさんのお役に立てたなら幸いです。