概要は下記参照のこと。
https://qiita.com/sy250f/items/1e9f5e71a6aac5756f5c
企業内にはインターネット環境に出ていく際に、Proxyサーバ経由の場合がある。
Proxyが間にいると開発する際にいろいろ問題が出てくるが、Node環境からkintoneへのリクエストにkintone rest-api-clientを利用した際に普通にパラメーターにProxyサーバの設定を入れただけでは動作しないことがあったので、備忘録として記載する。
問題点
kintone rest-api-clientを利用したプログラムから、企業Proxyを通してkintoneサーバにリクエストすると以下のエラーが発生した。
400: Bad Request
問題点の切り分け
問題の切り分けのために、下記の通り3つのケースにて簡単なプログラムを実行して結果を確認した。
- curlにてProxyサーバ設定をしてリクエスト実施
- kintone rest-api-clientにProxyサーバ設定をしてリクエスト実施
- axiosにてProxyサーバ設定をしてリクエスト実施
結果
- curlにてProxyサーバ設定をしてリクエスト実施 → OK
- kintone rest-api-clientにProxyサーバ設定をしてリクエスト実施 → NG
- AxiosにてProxyサーバ設定をしてリクエスト実施 → NG
上記の結果より、Axiosが原因なことが判明。
さらに詳細の原因を調査すると下記の情報を発見。
つまり、Axiosの仕様によりプロキシサーバからkintoneサーバへリクエストする際に、kintoneサーバが受け取ることができないリクエストになっていることで、400番のエラーが発生している模様。
対応方法
前段のissueにもあるとおり、AxiosはHTTPエージェントを切り替えることができるため、ここに別のHTTPエージェントを設定するようにする。
Axios
直接Axiosを利用した場合。
HTTPエージェントにはhttps-proxy-agent
を利用。
const axios = require('axios');
require('dotenv').config({debug: true});
const { HttpsProxyAgent } = require('https-proxy-agent');
(async () => {
try {
const API_TOKEN = process.env.API_TOKEN;
const APP_ID = process.env.APP_ID;
const agent = new HttpsProxyAgent(`http:${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`);
const config = {
headers: {
'X-Cybozu-API-Token': API_TOKEN,
},
params: {
'app': APP_ID,
'id': 1,
},
httpsAgent: agent,
}
await axios.get(`https://${process.env.KINTONE_SUBDOMAIN}.cybozu.com/k/v1/record.json`, config)
.then(response => {
console.log(response);
})
.catch(e => {
throw e;
})
} catch (error) {
console.log(error);
}
})();
HTTPエージェントにhpagent
を利用した場合は下記の通り。
const axios = require('axios');
require('dotenv').config({debug: true});
const { HttpsProxyAgent } = require('hpagent');
(async () => {
try {
const API_TOKEN = process.env.API_TOKEN;
const APP_ID = process.env.APP_ID;
const agent = new HttpsProxyAgent({
proxy: `http:${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`,
});
const config = {
headers: {
'X-Cybozu-API-Token': API_TOKEN,
},
params: {
'app': APP_ID,
'id': 1,
},
httpsAgent: agent,
}
await axios.get(`https://${process.env.KINTONE_SUBDOMAIN}.cybozu.com/k/v1/record.json`, config)
.then(response => {
console.log(response);
})
.catch(e => {
throw e;
})
} catch (error) {
console.log(error);
}
})();
kintone rest-api-client
rest-api-clientではコンストラクタのhttpsAgent
パラメータに、HTTPエージェントを設定する。
const { KintoneRestAPIClient } = require("@kintone/rest-api-client");
require('dotenv').config({debug: true});
const { HttpsProxyAgent } = require('https-proxy-agent');
(async () => {
try {
const API_TOKEN = process.env.API_TOKEN;
const APP_ID = process.env.APP_ID;
const params = {
'app': APP_ID,
'id': 1,
}
const agent = new HttpsProxyAgent(`http:${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`);
const client = new KintoneRestAPIClient({
baseUrl: `https://${process.env.KINTONE_SUBDOMAIN}.cybozu.com`,
auth: { apiToken: API_TOKEN },
httpsAgent: agent,
});
await client.record.getRecord(params)
.then(response => {
console.log(response);
})
.catch(e => {
throw e;
})
} catch (error) {
console.log(error);
}
})();
後書き
上記はあくまで一つの例なので、企業プロキシごとに対応方法は異なるかと思う。
ケースにより、HTTPエージェントは切り替える必要がある。
通信の状況によりHTTPエージェントの設定も、デフォルトではなくて細かな設定が必要な場面もあるので、都度対応が必要。