node.jsでrequest-promiseを使用してHTTPリクエストを投げる際に証明書関連のエラーが出ることがあります。
エラーが出た際の対応方法です。
エラー内容
[2046-13-32T26:78:67.997] [ERROR] default - Error: certificate has expired
https://www.stock.future/market/price/rate_2076.csv
Error: Error: certificate has expired
https://www.stock.future/market/price/rate_2076.csv
at rp.catch.err (/home/react/future/stock/lib/ImportFutureStockPrices.js:83542:7854)
at tryCatcher (/home/react/future/stock/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/react/future/stock/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/react/future/stock/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/react/future/stock/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/react/future/stock/node_modules/bluebird/js/release/promise.js:690:18)
at _drainQueueStep (/home/react/future/stock/node_modules/bluebird/js/release/async.js:138:12)
at _drainQueue (/home/react/future/stock/node_modules/bluebird/js/release/async.js:131:9)
at Async._drainQueues (/home/react/future/stock/node_modules/bluebird/js/release/async.js:147:5)
at Immediate.Async.drainQueues (/home/react/future/stock/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:810:20)
at tryOnImmediate (timers.js:768:5)
at processImmediate [as _immediateCallback] (timers.js:745:5)
certificate has expired
これは「証明書の有効期限が切れている」という意味です。
しかし、有効期限内でも無効の証明書に対しても出ます。
エラー原因
下記のエラーが考えられます。
- 証明書の有効期限切れ
- 証明書チェーンが途切れた
- ルートCA証明書が更新されてない
ちょっと前に「Let’s Encrypt」でルートCA証明書の更新がありましたね。
古いバージョンのサーバでは更新されたルートCA証明書が入ってなくてエラーになっていました。
証明書の更新
SSLの証明書の有効期限が切れている場合は、証明書を更新しましょう。
CA証明書更新
ルートCA証明書が原因の場合はCA証明書を更新します。
# dnf search ca-certificates
================= 名前 完全一致: ca-certificates =================
ca-certificates.noarch : The Mozilla CA root certificate bundle
# dnf install -y ca-certificates
有効期限を無視する
相手のサーバのSSLの有効期限切れで証明書の更新なんてできない。
でもHTTPリクエストでスクレイピングしたい!ってときもあると思います。
SSLの証明書が切れているサイトの情報なんて信用性は薄いですが。
request-promiseにSSLの有効性を無視するオプション「strictSSL: false」を追加します。
import request from 'request-promise';
let options = {
method: 'GET',
uri: url,
strictSSL: false, // SSLの有効性を無視
headers: {
'Content-Type': 'text/csv; charset=Shift_JIS',
}
};
let response = await request(options)
これでウェブスクレイピングできます。