雑記

2000|01|
2003|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|
2007|01|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|09|11|
2009|02|03|05|06|07|08|10|11|12|
2010|01|03|04|05|06|07|08|09|10|
2011|05|06|09|10|
2012|03|07|09|12|
2013|01|02|04|05|07|08|10|11|
2014|04|05|08|10|12|
2015|01|05|
2016|09|

2010-10-01 [長年日記]

[Ruby][Sinatra] Sinatra+WEBrickでSSLを使う方法 - もしくはRack::Handlerに任意のオプションを渡すためのパッチ -

WEBrickはSSLに対応していますが、Sinatraから利用する方法を探しても見つからなかったので、ソース見てモンキーパッチを書いてみました。

ソース:

上記ファイルを$LOAD_PATHの通っている場所に保存してアプリのコードに以下を追加します。

$LOAD_PATH.unshift './lib'  # ./libにbase_ext.rbを保存した場合
require 'base_ext'
 :
set :server, "webrick"
set :rack_handler_options, {
      :SSLEnable   => true,
      :SSLCertName => [ [ "CN", WEBrick::Utils::getservername ] ],
    }

これでアプリを実行すれば、オレオレSSL証明書を自動生成してアプリケーションが起動します。

% ruby start.rb
== Sinatra/1.0 has taken the stage on 4567 for development with backup from WEBrick
[2010-10-02 01:12:06] INFO  WEBrick 1.3.1
[2010-10-02 01:12:06] INFO  ruby 1.8.7 (2009-12-24) [i386-freebsd7]
............++++++
.....++++++
[2010-10-02 01:12:06] INFO
Certificate:
    Data:
        Version: 4 (0x3)
        Serial Number: 0 (0x0)
        Signature Algorithm: sha1WithRSAEncryption
 :
[2010-10-02 01:12:06] INFO  WEBrick::HTTPServer#start: pid=38059 port=4567

起動後、https://sample-host:4567/ にアクセスすると、SSL証明書の警告が表示されます。オレオレ証明書は起動のたびに生成されるので、Firefoxでうっかり保存すると2回目以降証明書エラーでまったくアクセスできなくなります。そうなったらSinatraアプリの起動時に表示されるSSL証明書のCNを見て、該当する証明書を削除します。

発行済みの証明書を利用したい場合は、:rack_handler_optionsを以下のように修正します。

ssl_crt = open('path/to/server.crt').read
ssl_key = open('path/to/server.key').read

set :rack_handler_options, {
      :SSLEnable   => true,
      :SSLCertificate => OpenSSL::X509::Certificate.new(ssl_crt),
      :SSLPrivateKey  => OpenSSL::PKey::RSA.new(ssl_key),
    }

その他、WEBrick::Config::SSLWEBrick::Config::HTTPに書いてあるオプションを指定することもできるはずです。

解説

.../gems/sinatra-1.0/lib/sinatra/base.rb の946行目の

handler.run self, :Host => bind, :Port => port do |server|

と言う行を

handler.run self, { :Host => bind, :Port => port }.merge(rack_handler_options) do |server|

と書き換え、ハンドラに渡されるオプションをマージするようにしただけです。

ちなみに、

set :server, "webrick"

を消して試しにMongrelで起動するとちゃんと無視してくれました。 Rack::Handlerのソースを読む限りはThinでも副作用は無いと思います。