2008年12月25日木曜日

cgiライブラリを使ってみました。

こんにちは、モリモルです。

RubyのCGI支援ライブラリのcgiを使ってみました。

CGIクラスのインスタンス経由で、HTTPリクエストとHTTPレスポンスを扱うようです。

---------------------------------------------
HTTPレスポンス
---------------------------------------------
cgi = CGI.new
print cgi.header(レスポンスヘッダ)
print "ボディ"

cgi = CGI.new
cgi.out(レスポンスヘッダ){"ボディ"}

---------------------------------------------
HTTPリクエストを取得
---------------------------------------------
環境変数を取得
cgi = CGI.new
cgi.accept_encoding <---- ENV{"ACCEPT_ENCODING"}と同じ。
cgi.raw_cookie <---- ENV{"COOKIE"}と同じ。


編集中....

2008年12月24日水曜日

ERBを使ってみました。

こんにちはモリモルです。
クリスマスイブですね。

今回は、erbライブラリのERBクラスを使ってみます。
ERBは、eRubyのRubyによる実装です。
eRubyスクリプトはテキストファイルにRubyスクリプトを埋め込めるのでPHPみたいな感じで使えるようです。




1、ERB.new(eRubyスクリプト, セーフレベル, トリムモード) で生成してから、
2、ERB#run(bind) ---> 標準出力
  ERB#result(bind) ---> String

で、eRubyスクリプトを実行できます。

トリムモードは、"-"、"%"などがあります。
eRubyスクリプトは改行やインデントなどはそのまま出力されるので、
整形したい場合に使います。

引数のbindは、Kernel.bindingで得られるBindingオブジェクトです。
これで何処のコンテキストで実行するかというのを指定できます。
デフォルトはKernel::TOPLEVEL_BINDINGなので、指定ないとコンテキストはトップレベルになるようです。

では、HTMLにRubyスクリプトを埋め込んでみます。



foo.erb

1 <html>
2 <table>
3 % 3.times do |num|
4 <tr>
5 <td><%= num %></td>
6 </tr>
7 % end
8 </table>
9 </html>



foo.rb

1 #! /usr/local/bin/ruby
2
3 require "erb"
4 erb = ERB.new(File.read("foo.erb"), nil, "%")
5 erb.run



出力結果
<html>
<table>
<tr>
<td>0</td>
</tr>
<tr>
<td>1</td>
</tr>
<tr>
<td>2</td>
</tr>
</table>
</html>

2008年12月23日火曜日

WEBrick::HTTPServlet::AbstractServletでサーブレットを作ってみました。

こんにちは。モリモルです。
2008年もあと1週間ほど。1年が早く感じます。

前回使ったHTTPFileHandlerが継承している、AbstractServletで簡単なサーブレットを作ってみようと思います。
※実行環境は1.8ですが、今後は参照するリファレンスはRuby1.9にしました(見やすいので。。)



まず、頭の中を整理。。



さて、今回作成するサーブレットにはPOSTメソッドのみ実装します。
(実装されていないHTTPメソッドが送られてくると例外を発生するようです)
サーブレットに送られるHTTPリクエストのBodyには、JPEGファイルが1つだけ添付されます。
サーブレットは、リクエストBodyからJPEGデータを抽出し、HTTPレスポンスのBodyに付けて返します。

まとめると、「フォームからPOSTで画像ファイルを送ると、サーブレットがその画像を返す」という単純なものです。



index.html(フォームページ)

<html>
<body>
<form action="/my_servlet" method="post" enctype="multipart/form-data">
<input type="file" name="img1">
<input type="submit">
</form>
</body>
</html>



server.rb(サーバー用スクリプト)

1 #!/usr/local/bin/ruby
2
3 require 'webrick'
4 include WEBrick
5
6 class MyServlet < HTTPServlet::AbstractServlet
7
8 def do_POST(req, res)
9 p req.query["img1"]
10 res.content_type = "image/jpeg"
11 res.body = req.query["img1"]
12 end

13
14 end
15
16 server = HTTPServer.new(
17 :DocumentRoot => "/var2/www/html",
18 :Port => 20080,
19 :BindAddress => "192.168.207.128")
20
21 server.mount("/my_servlet", MyServlet)
22
23 trap("INT"){server.stop}
24
25 server.start



9行目:HTTPリクエストBodyから画像を抽出して標準出力してます。やる意味はありませんが試しにいれました。
10行目:HTTPレスポンスヘッダのContent-Typeを指定。
11行目:HTTPレスポンスのBodyに画像データを代入。

では、ブラウザから"/my_servlet"へJPEGファイルをPOSTしてみます。





画像が表示されました。

9行目の標準出力の結果です。
文字列に変換するとつぎのようになります。
10行目のContent-Typeを適切に指定しないと、ブラウザ側はJPEGとして認識してくれません。

このデータをFile.open("foo.jpg", "w"){|file| file.write(req.query["img1"])}とかでサーバーに保存できるようです。

2008年12月22日月曜日

WEBrick::HTTPServlet::FileHandlerでエイリアス?を加えてみました。

こんにちは。モリモルです。

前回はWEBrick::Logでログをファイルに出力しました。
今回は、WEBrick::HTTPServlet::FileHandlerクラスで、Apacheでのエイリアスっぽいものを加えてみようと思います。

FileHandlerは、「通常のファイルサーバとしての機能を提供するためのサーブレット。 」とのことですので、こんな使い方はしないのかもしれませんが、、とりあえずやってみます。

前回からディレクトリ構成を変更しました。
------------------------------------------------------------

var2
`-- www
|-- html
| `-- index.html <----DocumentRoot
|-- image
| `-- foo.jpg
`-- logs
`-- log

------------------------------------------------------------
DocumentRootをwww/htmlにして、画像フォルダwww/imageを/imageでエイリアスしてみたいと思います。



www/html/index.html
------------------------------------------------------------

1 <html>
2 <body>
3 <img src="/image/foo.jpg"> <----/imageでアクセス
4 </body>
5 </html>

------------------------------------------------------------

server.rb
------------------------------------------------------------

1 #!/usr/local/bin/ruby
2
3 require 'webrick'
4 include WEBrick
5
6 logger = Log.new("/var2/www/logs/log", BasicLog::DEBUG)
7
8 server = HTTPServer.new(
9 :DocumentRoot => "/var2/www/html",
10 :Port => 20080,
11 :BindAddress => "192.168.207.128",
12 :Logger => logger )
13
14 server.mount("/image", HTTPServlet::FileHandler, "/var2/www/image")
15
16 trap("INT"){server.stop}
17
18 server.start

------------------------------------------------------------
青色の部分が今回追記した箇所です。
その他ログなどのパスは、適宜変更してあります。
HTTPServer#mountの第一引数で指定したディレクトリで、FileHandlerオブジェクトをマウントしています。
このFileHandlerオブジェクトですが、
/imageにアクセスがあるたびに、HTTPServerオブジェクトがFileHandler.newを呼び出し生成するようです。
その際に、FileHandler.newには、引数としてHTTPServer#mountの第三引数"/var2/www/image"が渡されます。

では、ブラウザからアクセスしてみます。


エイリアスのパスで、画像が表示できました。

WEBrick::HTTPServletには、ほかにも、CGIHandler、ERBHandlerなどがあるようですので、
次回はそちらを試してみようと思います。
ではでは。

2008年12月21日日曜日

WEBrick::Logでロギングしてみました。

こんにちは、モリモルです。

前回はWEBrickでHTTPサーバーを書きました。
今日は、WEBrick::Logクラスを使って、ロギング機能を追加したいと思います。

ディレクトリ構成
------------------------------------------------------------
/var2
|-- logs
 |-- log <----ログを記録するファイル
|-- www
 |-- index.html
------------------------------------------------------------
logsディレクトリ以下は、server.rbを実行するユーザーが書き込める権限が必要です。

前回書いたスクリプトにロギング機能を追記します。

server.rb
------------------------------------------------------------

1 #!/usr/local/bin/ruby
2
3 require 'webrick'
4 include WEBrick
5
6 begin
7 log = File.open("/var2/logs/log", "a")
8 rescue
9 puts "ERROR #{$!.message}"
10 log.close unless log.closed?
11 end
12
13 logger = Log.new(log, BasicLog::DEBUG)

14
15 server = HTTPServer.new(
16 :DocumentRoot => "/var2/www",
17 :Port => 20080,
18 :BindAddress => "192.168.207.128",
19 :Logger => logger )
20
21 trap("INT"){server.stop}
22
23 server.start

------------------------------------------------------------
青い部分が追記した箇所になります。

6~11行目で、ログを記録するファイルオブジェクトを生成。
13行目で、Logクラスのコンストラクタにファイルオブジェクトを渡してLogファイルオブジェクトを生成します。引数の2つ目はどのよなログを記録するかを指定しています。
今回は一番レベルの低い(DEBUG)を指定しました。
19行目で、HTTPServerクラスのコンストラクタに、Logオブジェクトを渡します。


では、サーバーを起動してみましょう。
------------------------------------------------------------

$ > ./server.rb &
$ > tail /var2/logs/log
[2008-12-19 12:30:30] INFO WEBrick 1.3.1
[2008-12-19 12:30:30] INFO ruby 1.8.7 (2008-06-09) [i686-linux]

------------------------------------------------------------
WEBrickの起動がログとして出力されました。

この後、ブラウザからアクセスしてログが出力されるか確認したのですが、出力はされませんでした。

おかしいなぁ。と思い、WEBrickを終了すると一気にログを吐き出しました。
------------------------------------------------------------

$> fg
./server.rb
【ctl + C】で停止
$> tail -20 /var2/logs/log
[2008-12-19 12:30:30] INFO WEBrick 1.3.1
[2008-12-19 12:30:30] INFO ruby 1.8.7 (2008-06-09) [i686-linux]
[2008-12-19 18:13:45] INFO WEBrick 1.3.1
[2008-12-19 18:13:45] INFO ruby 1.8.7 (2008-06-09) [i686-linux]
[2008-12-19 18:13:55] DEBUG TCPServer.new(192.168.207.128, 20080)
[2008-12-19 18:13:55] DEBUG WEBrick::HTTPServlet::FileHandler is mounted on /.
[2008-12-19 18:13:55] INFO WEBrick::HTTPServer#start: pid=2262 port=20080
[2008-12-19 18:46:31] DEBUG accept: 192.168.207.1:2994
[2008-12-19 18:46:51] DEBUG WEBrick::HTTPServlet::FileHandler is invoked.
[2008-12-19 18:47:11] DEBUG WEBrick::HTTPServlet::FileHandler is invoked.
[2008-12-19 18:47:11] ERROR `/favicon.ico' not found.
[2008-12-19 18:47:11] DEBUG close: 192.168.207.1:2994
[2008-12-19 18:47:21] DEBUG accept: 192.168.207.1:3011
[2008-12-19 18:47:41] DEBUG WEBrick::HTTPServlet::FileHandler is invoked.
[2008-12-19 18:47:41] ERROR `/favicon.ico' not found.
[2008-12-19 18:47:41] DEBUG close: 192.168.207.1:3011
[2008-12-19 18:48:25] INFO going to shutdown ...
[2008-12-19 18:48:25] INFO WEBrick::HTTPServer#start done.

------------------------------------------------------------
どうやら、ログの出力がFileオブジェクトに溜まったままで、WEBrickを終了しないとファイルに出力されなかったようです。
リファレンスにLog.new演算子の第一引数には、「メソッド << が定義されたオブジェクト。普通は String オブジェクトか IO オブジェクト。」と書いてあったので、Fileオブジェクトでいいのかな。と勘違いしていました。
単純にログファイルへのパスを指定すればOKのようです。

13行目を書き直します。(6~11行目は削除)
------------------------------------------------------------

13 logger = Log.new(log, BasicLog::DEBUG)

13 logger = Log.new("/var2/logs/log", BasicLog::DEBUG)

------------------------------------------------------------

これで、再度WEBrickを起動すると、tail -fでログのリアルタイム出力が確認できました。
めでたし。めでたし。

次回は、WEBrick上で、CGIを動かしてみようと思います。

2008年12月20日土曜日

WEBrickでHTTPサーバーを書いてみました。

こんにちは。モリモルです。

今回はRubyに標準添付されている、WEBrickモジュールを使って、HTTPサーバーを作ってみます。

公式リファレンスでは、
「汎用HTTPサーバーフレームワーク。HTTPサーバを簡単に作ることができます。」
とのことです。

WEBrickモジュールを使うと、一般的なHTTPサーバーが提供する多くの機能を実装できますが、今回はとりあえず、静的なHTMLファイルを表示するところまでやってみます。

以下の環境で行いました。
------------------------------------------------------------
クライアント:Windows Xp /IP:192.168.207.1
サーバー:CentOS release 5 (Final)/IP:192.168.207.128/ruby 1.8.7
------------------------------------------------------------

ディレクトリ構成は次のとおり
------------------------------------------------------------
/var2
|-- www <---DocumentRoot
 |-- index.html
------------------------------------------------------------
wwwディレクトリ以下は、サーバー用スクリプトを実行するユーザーがアクセスできるように、
権限を設定してください。

スクリプトを書いてみます。
server.rb
------------------------------------------------------------

1 #!/usr/local/bin/ruby
2
3 require 'webrick'
4 include WEBrick
5
6 server = HTTPServer.new(
7 :DocumentRoot => "/var2/www",
8 :Port => 20080,
9 :BindAddress => "192.168.207.128")
10
11 trap("INT"){server.stop}
12
13 server.start

------------------------------------------------------------


では、動かしてみます。
------------------------------------------------------------
$ > chmod 744 server.rb
$ > ./server.rb &
[1] 5035
$ > ps
5035 pts/1 00:00:00 server.rb
------------------------------------------------------------
psコマンドで起動が確認できました。

では、ブラウザからIP:192.168.207.128の20080番ポートに接続してみます。



はい。繋がりません。。

iptablesのフィルタにひっかかっていました。。

20080番ポートへの接続を許可します。
------------------------------------------------------------

$ > sudo iptables -t filter -A INPUT -p tcp --dport 20080 -j ACCEPT
$ > sudo /etc/init.d/iptables save
$ > sudo service iptables restart

------------------------------------------------------------

で、
フィルタはこうなりました。
------------------------------------------------------------

$ > sudo iptables -t filter -L INPUT
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT icmp -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT tcp -- anywhere anywhere tcp dpt:ftp
ACCEPT tcp -- anywhere anywhere tcp dpt:pop3
ACCEPT tcp -- anywhere anywhere tcp dpt:smtp
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:20080

------------------------------------------------------------

再度、アクセスしてみます。



接続確認ができました!
ただ、反応が激遅いです。。VMware上で動いているサーバーからでしょうか。

今回のスクリプトでは、HTTPサーバーのログ情報は、標準エラー出力としてターミナルの画面に表示されていますので、次回は、ログをファイルに出力してみようと思います。
ではでは、

ブログをはじめてみました。

こんにちはモリモルです。

WEB業界に7年以上いますが、何かを配信したことがありませんでした。
特に配信するような内容がなかったので。。
このブログではオブジェクト指向スクリプトRubyを中心に、色々と書いていきます。
(続くかな・・)