Axiosのプロキシ設定でユーザ名/パスワードを設定したい!
こんにちは。クラウドソリューショングループのkaneko.kです。
ServerlessFramework(TypeScript)を使ってAWS Lambdaからバッチ実行していたシステムがあるのですが、ある日会社のプロキシにユーザ名/パスワードを追加する必要が出てきたためその対応をしました。
プロキシにユーザ名/パスワードを設定するのは簡単だろうと思っていたのですが、思いの外詰まったので知見共有をしたいと思います。
もし、同じように詰まっている方の参考になれば幸いです。
0.環境
・Serverless Framework:v3系
・TypeScript:v4系
・Axios:1.3.3
・Node.js:v18系のLambda上で実行
1.結論
結果としては下記のようにHTTPヘッダーにProxy-Authenticationを設定することで通信が通るようになりました。
修正前
const proxyUrl = 'http://<proxy.host>:<port>';
const axiosConfig: AxiosRequestConfig = {
proxy: false,
httpAgent: new HttpProxyAgent(proxyUrl),
httpsAgent: new HttpsProxyAgent(proxyUrl),
};
※ URL等のところは実際はAWS Secret Managerから取得するように作っていますが、説明のためにべた書きに変更しています。
修正後
const proxyUrl = 'http://<proxy.host>:<port>';
const axiosConfig: AxiosRequestConfig = {
proxy: false,
httpAgent: new HttpProxyAgent(proxyUrl),
httpsAgent: new HttpsProxyAgent(proxyUrl),
headers: {
'Proxy-Authentication': `Basic ${Buffer.from('<username>:<password>').toString('base64')}`,
},
};
2.ダメだったパターン:URLに直設定
まず初めに試したのが、下記のようなコードです。
const proxyUrl = 'http://<username>:<password>@<proxy.host>:<port>;
const axiosConfig: AxiosRequestConfig = {
proxy: false,
httpAgent: new HttpProxyAgent(proxyUrl),
httpsAgent: new HttpsProxyAgent(proxyUrl),
};
ERROR error reason AxiosError: getaddrinfo ENOTFOUND <username>
というエラーになりました。
ユーザ名部分をhostとして解釈してしまっているようで、「そんなアドレスは見つからない」と怒られてるようです。
ちなみに、URLエンコードも試しましたが、エラーは変わらず。。。
3.ダメだったパターン:urlクラスのauthに設定
次に試したのが、URLクラスに一度かませるやり方です。
const proxyOpts = url.parse('http://<proxy.host>:<port>');
proxyOpts.auth = '<username>:<password>';
const axiosConfig: AxiosRequestConfig = {
proxy: false,
httpAgent: new HttpProxyAgent(proxyOpts),
httpsAgent: new HttpsProxyAgent(proxyOpts),
};
こちらは
SSL routines:ssl3_get_record:wrong version number
というエラーになりました。
恐らくですが、スキーマがhttpなので非TLS通信で試みるも、ユーザ/パスワードのかかったTLS通信として解釈されエラーになったと思われます。
それならばと思い、スキーマ周りを見直そう思いましたが、ログをよくよく見ると
proxy: {
host: '<proxy.host>',
port: '<port>',
auth: '<username>:<password>'
},
がっつりユーザ名とパスワードがログに吐かれてました。
デバッグ用のログレベルならまだしも、がっつりAXIOSエラーのスタックトレースに出てしまっているので、
これではさすがに使い物になりません。(何かあってスタックトレースを吐き出したときに全部ログに残ってしまう・・・)
※ 余談ですが、スキーマをhttpsに変更したところでエラーでした(ポートの指定が443ではないので)
そして何とか最初の結論にたどり着いたという感じです。
最後に
案外簡単そうな変更でも、実際に試してみないと分からないことがこの業界にはしばしばあります。
今回はまさにその事例に当たってしまったわけですが、この苦労を苦労のままにしておくのは勿体ないなと。
色々な記事や公式ドキュメントを漁り・組み合わせ・試行錯誤してたどり着いた知見を困っている方に届けられたら幸いです。