例えば、独自の仕組みで DNS キャッシュをする社内ライブラリがあった場合に、すべての名前解決を ruby 標準のものから、そのライブラリ経由に置き換えたい。

Ruby には標準で resolv-replace.rb というものがあって、これを使うと libc の resolver を Ruby で実装している Resolv クラスに置き換えることができる。

というわけで、これを参考に、すきな Resolver にすげかえられる gem を作った。 名前になやんだけれど、resolver_replace ぐらいにしておいた。名前かぶっとる\(^o^)/

使い方はこんなかんじで、ここでは例として、ruby 標準にある Resolv::DNS を使うようにすげかえている。

require 'resolv' # Resolve::DNS
require 'resolver_replace' # ResolverReplace

resolver = Resolv::DNS.new(:nameserver => ['210.251.121.21'],
                           :search => ['ruby-lang.org'],
                           :ndots => 1)

ResolverReplace.register!(
  getaddress: Proc.new {|host| resolver.getaddress(host) },
  getaddresses: Proc.new {|host| resolver.getaddresses(host) },
  error_class: Resolv::ResolvError,
)

これで net/http など大体はOK。

「大体」と言っているのは、mysql2 などの ruby ライブラリを使わずに C 拡張で実装しているような gem には効かないため。 そこでそういう gem のために plugin 機構を用意した。今のところ mysql2 だけ用意していて、以下のようにして適用できる。

ResolverReplace.load_plugin('mysql2')

まとめ

Resolver をすげかえるには、https://github.com/sonots/resolver_replace を利用できる。

後記: 今だと(?)標準機能の Resolve::DefaultResolver.replace_resolvers で置き換えられそう