二日間 Wikiクッキング その1 webrick編

今回、madeleineをページの保存に使いたかったので、プロセス常駐型なのは決定。webインターフェイスにはwebrickを利用。
servletにしたら軽くできるんでねえの?と甘く考えて、まずwebrickservletの使い方を調べよう。

http://www.webrick.org/のサンプルをじーっと眺める。HTTPServlet::FileHandlerの内容の中身をちらっと見てみることにする。
ライブラリの中をあさって、webrick/httpservlet/filehandler.rbを発見。
と思ったら、サンプルの中にHello Servletってサンプルがあるじゃん。これだな。ははーん、procでもservletになっちゃうわけですね。

s.mount_proc("/hello/again"){|req, res|
  res.body = "<HTML>hello (again)</HTML>"
  res['Content-Type'] = "text/html"
}

要は、HTTPServer(ソース中でのs)に、procを登録すればよい、と。
WEBrick::HTTPServlet::AbstractServletを継承したクラスでは、do_GET(req,res)ってメソッドをオーバーライドすればいいのだな。どちらにしても、ブラウザからの入力情報はreqでとれて、ブラウザへの出力はresに文字列を設定することでOKと。
とりあえず、reqとresが何者かわからないので、内容を表示させてみるprocを追加して、HelloWorldサンプルを実行。
追加したのはこんな感じ

s.mount_proc("/arg"){|req,res|
  res.body = "<HTML>#{req.inspect}<hr/>#{res.inspect}</HTML>"
  res['Content-Type'] = "text/html"
}

http://ホスト名:2000/arg にアクセスすれば、req,resがインスペクトされたものが見えるはず。さあどうだ。
おっとでたでた、めちゃいっぱい中身が表示されました。こんなに出されても覚えきれないので、クラスも表示させておぼえておく。WEBrick::HTTPRequestとWEBrick::HTTPResponseというクラスだったらしい。まんますぎてちょっと馬鹿にされた気分。めげずに次へ。
普通にGETされたときはこれでいけるとして、フォームで引数わたされたときはどうなるんだろ。WEBrick::HTTPRequestの中身にいかにもそれらしい、@query,@query_stringなどというのが見えるので、最悪これをひっぱれば取れるだろう。
でも、なんか楽に取得する方法があると期待してしばしぐぐる
結局、HTTPRequestのリファレンス(http://shogo.homelinux.org/~ysantoso/webrickguide/html/HTTPRequest.html)を読んでも直接@queryをひっぱれと書いてあるような気がするのでそれに従う。@query_stringは渡された引数の文字列がそのままはいってる、@queryはハッシュになってる。でも、URIの引数は同じKeyで複数の値がわたせるので、ハッシュのvalueはたんなるStringではなくて、FromDataというものらしい。
ひきつづき FromData(http://shogo.homelinux.org/~ysantoso/webrickguide/html/HTTPUtils_FormData.html)のリファレンスを読む。複数の文字列を格納できるようなデータ構造らしいということはわかったが、それ以上はいまいちわからず。実際にテストしてみるか。
こんなのを書いた。

class HelloServlet < WEBrick::HTTPServlet::AbstractServlet
  def do_GET(req,res)
    do_mes(req,res)
  end
  def do_POST(req,res)
    do_mes(req,res)
  end
  def do_mes(req,res)
    res['Content-Type'] = "text/html"
    res.body =<<EOS
<html>
  <form action="./" method="post">
  <input type="text" name="name" size="15" /> #{req.query['name']}<br/>
  <input type="text" name="name1" size="15" />#{req.query['name1']}<br/>
  <input type="text" name="name1" size="15" />#{req.query['name1']}<br/>
  #{req.query['name1'].list.inspect if req.query['name1']}
  <input type="submit"/>
  </form>
</html>
EOS
  end
end

@queryはドキュメント通りハッシュだが、値が複数あっても文字列を持つハッシュのように最初の要素を返してくれる。複数ある場合はlistを呼べば配列が帰ってくる、と。これで多い日も安心。

と、ここまでで、ブラウザとのインターフェイス部分の書き方が確認できたのでしばし手をとめて全体のデザインを考える。