ぱろっと・すたじお

技術メモなどをまったりと / my site : http://parrot-studio.com/

さくらのレンタルサーバでSinatraを動かす

ここ数年、Webの開発はほとんどRubyのRack系フレームワークを使っていますが、
久々に「CGIしか動かない環境」での開発を強いられまして


・・・まあ、さくらのレンタルサーバなんですがΣ(・ω・ノ)ノ


たいした規模のシステムでもないので、
当初は久々に「普通のCGI」で書こうと思ったのですが、
開発環境構築の時点でだるくなったという・・・


そもそも「普通のCGI」で書こうとすると、
Rackの強力なライブラリ群やノウハウが使えないので、
セキュリティ等の面でも心配です


そこで、どうにかRack・・・というか、
Sinatraを動かす手段を探したところ、
うまいこと記事が見つかりましたヽ(`・ω・´)ノ

基本的には上記の記事通りなのですが、
実際に試してみた手順をメモしておきます...φ(・ω・`)

環境

  • さくらのレンタルサーバ
    • ユーザ名:hoge
    • Ruby1.8.7
      • /usr/local/bin/ruby
      • 共有サーバのため、単純実行ではgemがインストールできない
    • CGIの実行はwww以下全域で許可されている

Sinatraのインストール


単純に「gem install sinatra」とかできないので、
まずローカルにgemをインストールしないといけません
というわけで、先ほどのサイトに従いこんな感じに

cd ~
mkdir lib
mkdir lib/ruby
mkdir lib/ruby/gem

vi .cshrc

###
# 末尾に以下を追加
setenv GEM_HOME $HOME/lib/ruby/gem
###

source .cshrc
gem install sinatra # 2012/01/18時点では1.3.2


なお、先ほどのサイトではどちらもRackのコードを修正していますが、
Sinatra1.3.2と一緒に入ってきたRack1.4.0はそのまま動作しています
実アプリで問題が出る可能性はありますが、現時点ではそのままで良いかと

Sinatraの動作テスト


これも先ほどのサイトにあった通りです

cd ~/www
mkdir testapp
cd testapp
vi index.cgi # この名前が重要
chmod +x index.cgi
vi start.rb
# index.cgi

#!/usr/local/bin/ruby

# 本来はbundlerとGemfileを経由する形にすべき
# 今回は動かすことだけが目的なのでそのままで

load 'start.rb'

set :run, false

Rack::Handler::CGI.run Sinatra::Application
# Sinatra::Baseを継承したAppでももちろんOK
# start.rb

#!/usr/local/bin/ruby

# ライブラリPATHとgemの読み込みPATH設定
$LOAD_PATH.unshift '/home/hoge/lib'
$LOAD_PATH.unshift '/home/hoge/lib/ruby'
ENV['GEM_HOME'] ||= '/home/hoge/lib/ruby/gem'

require 'rubygems' # 1.8.7環境なので必須
require 'sinatra'

get '/?' do # '?'は正規表現のと同じ '/'の有無を気にしない定義
  'Hello Sinatra World!'
end

get '/test' do
  'Hello Sakura World!!'
end


index.cgiにするのが重要な理由の一つは、
さくらのレンタルサーバApacheの「Option Indexs」がデフォルトでOnのため、
index.[html|cgi|php|etc...]を置いておくと、ファイルリスト流出を防げるからです*1


この状態で「 http://[さくらのサーバ名]/testapp/index.cgi 」にアクセスすると、
「 get '/' 」に相当する文字列が見えるはずです
「 /testapp/ 」とindex.cgiを省略しても見えるはず


問題は、「 get '/test' 」へのアクセスで、
これに該当するのは「 /testapp/index.cgi/test 」と、
非常に気持ち悪いURIになってしまいます(´-ω-)

Rewriteでリダイレクトする


当然ながら、先ほどのケースでは「 /testapp/test 」でアクセスしたいので、
.htaccessを使ってリダイレクトを設定します

# ~/www/testapp/.htaccess の場合

RewriteEngine On
RewriteBase /testapp/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.cgi/$1 [L]


こうすると、「 /testapp/test 」へのアクセスが、
内部的に「 /test/index.cgi/test 」に書き換わるので、
見かけ上のURIを綺麗にできるのです


ちなみに、当初は「index.cgi」ではなく、「test.cgi」で試したのですが、
そうすると「 /testapp/ 」にアクセスした時にリダイレクトされず、
ファイルリストが見えてしまいましたΣ(゚Д゚)ガーン


なので、「ファイルリストを見せない」、
「ディレクトリのルートでもSinatraを呼ぶ」という二点で、
「index.cgi」という名前を推奨します




今回はざっと動作確認しただけなので、
実際にアプリを動作させる時にいろいろあるかもしれませんが、
それはまた次の機会に(`・ω・´)ノ




<おまけ>


同じ原理でRailsもいけるとは思いますが、
あくまでCGIとして動くことを考えると、
相当重くなって使い物にならない気がします(´-ω-)


Sinatraなら速いというわけではないですが、
呼び出されるコードの規模を考えるとまだましかなと


あと、Sinatra(やRails)をバックエンドで起動しておいて、
Apacheからproxyする手も一応考えました


でも、ほんの数ページ程度の規模のシステムなのと、
そこまでやるならVPSを借りる方が・・・ということで、
今回は見送りました(´・ω・`)

*1: .htaccessで防ぐのが一番だとは思いますが、念のため置いておけば安心