Rubyの勉強 02

9月も上旬が終わる。
Rubyの入門書を買って勉強中だが、色々変なことや違うことに手を出していて、
遅々として進まない。

Ruby自体の仕様に目をむくのもある。
思ったよりガッツリ、オブジェクト指向言語になっていて、
この辺のことが頭から飛んでいた私には刺激が凄い。
細かいところでも、イテレータを定義できるとか(やったことがなかった)、
演算子オーバーライド(オーバーロードではなかった)ができるところとか、
気になってしょうがなかった。
ほんとにスクリプト言語なのかこれ…。
# 大昔にC++演算子オーバーロードが出来る事を知った時は画期的だなぁと
# 思ったものだし、Javaでそれが採用されてないのも、まぁしょうがないよね
# と思ってたもんだった。それが最近の言語じゃ普通にできる。
## C11とか、マルチスレッドに対応するとか言うし。もう…あ、これは関係ないか。


今日は先月のHTTPSへのリベンジの機会がやってきたので、書いておこうと思った。
たのしいRuby 第4版のP.168、List 8.13である。
第8章 クラスとモジュールに出てくるオブジェクトの使用例で、HTTPクラスのインスタンスを使って、
Rubyの日本語公式サイトからドキュメントを取得する。

章のタイトルの通りここではクラスとモジュールの説明がメインなので、
HTTPのプロトコルやネットワークプログラミングについての説明は必要最小限に
とどめてある。賢明な書き方だと思う。

しかし、このプログラム、"http_get.rb"だが、残念ながらそのままでは
期待通りには動かない。
先日のサンプルプログラムと同じ問題だ。
"http://www.ruby-lang.org/ja/"からは301 Moved Permanentlyが返される。

D:\pg\ruby-test\hajimete>ruby http_get_.rb
#<Net::HTTPMovedPermanently:0x289261c>

ロケーションヘッダに移動先のURLが示されているとのことだが、
ここでは単純に"https://www.ruby-lang.org/ja/"にアクセス先を変えよう。
すると今度は

D:\pg\ruby-test\hajimete>ruby http_get_.rb
D:/pg/ruby/lib/ruby/2.1.0/net/protocol.rb:153:in `read_nonblock': end of file re
ached (EOFError)
        from D:/pg/ruby/lib/ruby/2.1.0/net/protocol.rb:153:in `rbuf_fill'
        from D:/pg/ruby/lib/ruby/2.1.0/net/protocol.rb:134:in `readuntil'
        from D:/pg/ruby/lib/ruby/2.1.0/net/protocol.rb:144:in `readline'
        from D:/pg/ruby/lib/ruby/2.1.0/net/http/response.rb:39:in `read_status_l
ine'
        from D:/pg/ruby/lib/ruby/2.1.0/net/http/response.rb:28:in `read_new'
        from D:/pg/ruby/lib/ruby/2.1.0/net/http.rb:1408:in `block in transport_r
equest'
        from D:/pg/ruby/lib/ruby/2.1.0/net/http.rb:1405:in `catch'
        from D:/pg/ruby/lib/ruby/2.1.0/net/http.rb:1405:in `transport_request'
        from D:/pg/ruby/lib/ruby/2.1.0/net/http.rb:1378:in `request'
        from D:/pg/ruby/lib/ruby/2.1.0/net/http.rb:1128:in `get'
        from http_get_.rb:5:in `<main>'

と盛大に怒られる。net/httpはHTTPSに対応していないのである。
そういう訳であちこち参考にして書き換えた。http_get.rbがこちら。

require "net/https"
require "uri"
url = URI.parse("https://www.ruby-lang.org/ja/")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
https.ca_file = "D:\\pg\\ruby-test\\hajimete\\cacert.pem"
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
https.start
doc = https.get(url.path)
puts doc.body

Windowsのコンソールのフォントの問題か、若干文字化けしている箇所もあるが、HTMLが正常に読み込めた。これで一応HTTPSへのアクセスとドキュメントの取得はできるようになった。
ただ、問題や疑問点もいくつかある。
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
の行で、個々の値をOpenSSL::SSL::VERIFY_NONEにすると、https.ca_file、つまり証明書のファイルが必要なくなるのだが、それはそれでおっかない。
cacert.pamがなく、最初、どうしたものかと思ったが、同じようなことで悩んでいた人は多いらしく、あちらこちらでファイルの入手法が書いてあった。
曰く、http://curl.haxx.se/ca/cacert.pemからもって来い。
なんじゃそりゃ。そもそもこのサイトはなんなんだ。
しょうがないので調べてみると、
cURL - Wikipediaと言う至極真っ当な
団体であることがわかった。
証明書も安全そうである。
# 不正に書き換えられたとかいうことがなければだが
そういう訳で、その場しのぎでこれを使ったのだが、合点も行かない。
Windowsの保有する最新の証明書が使いたい。
http://q3.snak.org/doc/RootCertificate.html
こちらで紹介されている方法を使えば、証明書のファイルは手に入れられそうだ。
しかし、Rubyでクライアントを作ったとして、毎回ユーザーにこれを作ってもらうのかと思うとかなりしんどい話である。
普通はどうやっているんだろうか?(・ω・ )