axios について、いくつか記事を書いておきながら導入についての記事を書いていなかったので、導入について記しつつ こちらの記事 で示した構成も作ってみた。
更新情報
- 2018/05/15
- 2018/07/02
-
axios
のインスタンス生成時に指定しているheaders
の内容を修正しました( @dyoshikawa 様、ご指摘ありがとうございました )
-
過去に書いた axios の記事
この記事を実施した環境
-
Windows10 Home 64bitmacOS High Sierra( 10.13.4 ) nodist v0.8.8 ( in Windows10 )- n v2.1.7 ( in macOS High Sierra )
- node
v8.2.1v9.4.0 - npm
v4.0.5v6.1.0 - Express
v4.15.0v4.16.0 - axios
v0.16.2v0.18.0
前提
フロントエンド、バックエンドは Express で実装している。
axios とは
本家 によると
Promise based HTTP client for the browser and node.js
とある。
そのままな訳となるが、ブラウザや node.js で動く Promise ベースの HTTP クライアントである。 REST-API を実行したいときなど、これを使うと実装が簡単にできる。
axios の導入
次のコマンドを実行してインストールする。
一応 --save
で package.json にも反映させておく。
$ npm install axios --save
{
...
"dependencies": {
"axios": "^0.16.2",
...
},
...
}
axios を使ってバックエンド間のやり取りを行う
構成は次の感じ。
- バックエンドA はフロントエンドからのリクエストを受け付ける
- バックエンドA は「1.」を受けてバックエンドB へリクエストを投げる
- バックエンドB は「2.」を受けてレスポンスをバックエンドA へ返す
- バックエンドA は「3.」を受けてレスポンスをフロントエンドへ返す
バックエンドA の実装
- ここでは上記の「1.」「2.」「4.」を担当する
- バックエンドA はバックエンドB に対してリクエストを投げるので、ここが axios を利用する箇所となる
- コード中の
[]
で囲った番号は上述の番号と合わせてある
GET
メソッドだけの例となるが以下に実装例を示す
var express = require('express');
var router = express.Router();
// axios を require してインスタンスを生成する
const axiosBase = require('axios');
const axios = axiosBase.create({
baseURL: 'http://localhost:4000', // バックエンドB のURL:port を指定する
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
responseType: 'json'
});
// [1] フロントエンドからのリクエストを受け付けて
router.get('/', function(req, res, next) {
// [2] バックエンドB に対してリクエストを投げる
axios.get('/title')
.then(function(response) {
// [4] フロントエンドに対してレスポンスを返す
res.render('index', response.data);
})
.catch(function(error) {
console.log('ERROR!! occurred in Backend.')
});
});
module.exports = router;
オプションを指定したい場合、 GET
メソッドでは axios.get(url, option)
として 第2引数 にセットする。
PUT
や POST
メソッドの場合は 第3引数 にセットする。
本家のこちらあたり が参考になるかと。
バックエンドB の実装
- ここでは上記の「3.」を担当する
- こちらは単純にリクエストに対してレスポンスを返すだけなので axios は登場しない
- シンプルに Express だけの実装となる
- コード中の
[]
で囲った番号は上述の番号と合わせてある
var express = require('express');
var router = express.Router();
// [3] フロントエンドA からのリクエストを受けてレスポンスを返す
router.get('/title', function(req, res, next) {
res.json({ title: 'Express. Responded by BackEnd-B.' });
});
module.exports = router;
- なお、バックエンドB ではポート番号を変える必要があるので、忘れずに次の部分を修正しておく
// 15行目
// デフォルトでは 3000 が指定されているが、そのままではバックエンドA とポート番号が重複するので変更する
// (順序が逆になるが) ここではバックエンドA で指定しているポート番号[4000]を設定する
var port = normalizePort(process.env.PORT || '4000');
動作確認
-
バックエンドA、バックエンドB をそれぞれ次のコマンドで起動させる
バックエンドAを起動する$ npm start
バックエンドBを起動する$ npm start
-
バックエンドA に対してブラウザからアクセスする。
-
バックエンドA の URL(http://localhost:3000) にアクセス
-
バックエンドB で返しているレスポンスである 「 Express. Responded BackEnd-B. 」 が表示されていることが確認できる
終わりに
axios を利用すると REST-API を使ってのやり取りが簡単に実装できた。
で、蛇足ながら。。。
使用する REST-API が少ない場合は上記例のように axios.get(url)
のように個別に書くのもいいが、API が増えてくるとちょっと冗長である。
というところで、 REST-API を実行する際の入り口として次のようなヤツを用意するのもアリかと思う。
// axios を require してインスタンスを生成する
const axiosBase = require('axios');
const axios = axiosBase.create({
baseURL: 'http://localhost:4000', // バックエンドB のURL:port を指定する
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
responseType: 'json'
});
/**
* REST-API の GET メソッドを実行する
*
* @param {any} url REST-API のURL
* @param {any} callback 呼び出し元のコールバック処理
* @param {any} [option=null] axios のオプション
*/
function get(url, callback, option = null) {
// axios を使って引数で指定された url に対してリクエストを投げる
axios.get(url, option)
.then(function(response) {
// 返ってきたレスポンスはそのまま加工せずに callback で呼び出し元へ渡す
callback(response);
})
.catch(function(error) {
console.log('ERROR!! occurred in Backend.')
});
}
/**
* コンストラクタ
*/
function RestFacade() {}
// prototype チェインに突っ込む
RestFacade.prototype.get = get;
module.exports = new RestFacade();
const express = require('express');
const router = express.Router();
const restFacade= require('./rest-facade');
router.get('/', function(req, res, next) {
restFacade.get('/title', function(response) {
res.render('index', { title: response.data.title });
});
});
補足
プロキシ関連の設定( Error: getaddrinfo ENOTFOUND の対処 )
プロキシを使用する環境下で、axios で REST-API を実行した際に次のエラーが発生するケースがある。
Error: getaddrinfo ENOTFOUND proxy.host.address(1) proxy.host.address(2):NNNN(3)
# (1), (2) の proxy.host.address は自身の環境におけるプロキシのアドレス
# (3) の NNNN はポート番号
で、axios 経由で REST-API を実行するときにプロキシを経由したくない場合、次の設定を前述のインスタンス生成時にセットしてやれば良い。
const axiosBase = require('axios');
const axios = axiosBase.create({
baseURL: 'http://localhost:4000', // バックエンドB のURL:port を指定する
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
// -------------------------
// プロキシを無視する設定
// -------------------------
proxy: false,
responseType: 'json'
});
プロキシ周りの設定については 本家の Request Config にプロキシについての記述があるので参考にどうぞ。