仕事で外部サービスに対して、クライアント証明書を指定してクリエストを送信する必要があり調べてみました。
httpsモジュールのAgentのオプションにpfx、passphraseを指定して、FormDataのsubmitの引数に指定するだけです。
証明書は.pfxではなく、.p12だったのですがどっちでもOKぽかったです。
外部サービスの仕様上、multipart/mixedで送らないといけなかったので、axiosなどのクライアントが使用できなかったのでこのような実装になっています。
大体のクライアントはヘッダーをmultipart/form-dataにして送信するので、ちょっと面倒でした。
また、pathが/から始まらないといけないぽくて、read ECONNRESETが出て接続が切られる問題が発生し、原因の特定に時間が少しかかりました。
証明書の問題で接続が切られていると思ってしまったのが良くなかったです。
本番環境ではクライアント証明書や、パスフレーズなどはGCPのSecret Managerなどで管理しておくのが良いと思います。
const fs = require('fs') const https = require('https') const FormData = require('form-data') const pfx = fs.readFileSync("./xyz.p12") const agent = new https.Agent({ pfx, passphrase: '1234' }) const form = new FormData() form.append('param1', '1234') form.append('param2', '1234') form.submit( { host: 'example.com', method: 'post', path: '/path/to', headers: { 'Content-Type': `multipart/mixed; boundary=${form.getBoundary()}`, }, agent, protocol: "https:" }, (err, data) => { console.log(err) } )