Ractorの中からnet/httpsでHTTPSリクエストを送る

2025/5/6

Ractor (non-main Ractor) からHTTPSリクエストを送る例。Faradayのような便利なライブラリは内部でクラスインスタンス変数 @@nanika を多用している都合、コードの変更なしではRactorの中から使うことができない(Faradayに限らず、世の中のgemのかなりの部分がこの制約で阻まれる)。net/http (net/https) ならぎりぎり Ractor.make_shareable で対応できる。

require 'openssl'
require 'net/https'

# net/http が使う定数を事前に deep freeze しておく
Ractor.make_shareable OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
Ractor.make_shareable Net::HTTP::SSL_IVNAMES
Ractor.make_shareable Net::HTTP::SSL_ATTRIBUTES
Ractor.make_shareable Net::HTTPResponse::CODE_TO_OBJ

Ractor.new {
  http = Net::HTTP.new('example.com', 443)
  http.use_ssl = true

  # OpenSSL::SSL::SSLContext::DEFAULT_CERT_STORE は shareable にできないので、同等のものをつくる
  # https://github.com/ruby/openssl/issues/521
  cert_store = OpenSSL::X509::Store.new
  cert_store.set_default_paths
  cert_store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
  http.cert_store = cert_store

  # Timeout::TIMEOUT_THREAD_MUTEX (Ractor unshareable) に触れないようにする
  http.open_timeout = nil

  res = http.get('/')
  p res.body
}.take