読者です 読者をやめる 読者になる 読者になる

おさかな日誌

魚類がプログラミング

ワンライナーで Rack app 走らせる and Rack のメモ

Rack、雑にワンライナーで走らせれて便利だった。

rackup -s webrick -b 'run(Proc.new { |env| ["200", {"Content-Type" => "text/html"}, ["hello"]] })'

use したい場合は -b オプションのスクリプトuse Foo; use Bar とか書いておくとよさそう。ライブラリ読む時は -r オプションで読んでくれる。

rackup -r rack/contrib -s webrick -b 'use Rack::Runtime; use Rack::ProcTitle; run(Proc.new { |env| ["200", {}, ["hello"]] })'

REAME にあるように Rack::Handler を使う場合、app を生成するのには Rack::Builer#to_app を使う。

ruby -rrack -e 'Rack::Handler::WEBrick.run(Rack::Builder.new { run Proc.new { |env| ["200", {"Content-Type" => "text/html"}, ["hello"]] } }.to_app)'

Ruby ラインタイムからサーバーを走らせたい場合だとRack::Server.startインターフェイスきれいでよさそう。

ruby -rrack -e 'Rack::Server.start(server: "webrick", app: proc { ["200", {}, ["hello"]] })'

今回の調査で人類が得たもの

  • Rack::Server.start 便利
  • config.ru に "#-p8080 -s weblick" とか書いておくとコマンドラインオプションとして Rack に渡せる
  • config.ru で warmup という app を走らせる前に一度だけ評価できる block を登録できる誰得メソッドが使える。

「今回の調査で我々は・・くっ・・何の成果も得られませんでしたぁぁ!!私が無能なばかりにただいたずらに兵を死なせ、Rack の正体を突き止めることが、できませんでしたぁぁ!!」


以下 rack のサーバー立ち上げるまでを読んだメモ

  • rackup はなにをしている?
  • config.ru はどう扱われている?

bin/rackup

Rack::Server.start を呼ぶだけ

Rack::Server.start

インターフェイス

Rack::Server.start(
  :app => lambda {|e| [200, {}, ['hello world']] },
  :server => 'cgi'
)

渡せるオプション

  • :app - a rack application to run (overrides :config)
  • :config - a rackup configuration file path to load (.ru)
  • :environment - this selects the middleware that will be wrapped around your application. Default options available are:
    • development: CommonLogger, ShowExceptions, and Lint
    • deployment: CommonLogger
    • none: no extra middleware
  • :server - choose a specific Rack::Handler, e.g. cgi, fcgi, webrick
  • :daemonize - if true, the server will daemonize itself (fork, detach, etc)
  • :pid - path to write a pid file after daemonize
  • :Host - the host address to bind to (used by supporting Rack::Handler)
  • :Port - the port to bind to (used by supporting Rack::Handler)
  • :AccessLog - webrick access log options (or supporting Rack::Handler)
  • :debug - turn on debug output ($DEBUG = true)
  • :warn - turn on warnings ($-w = true)
  • :include - add given paths to $LOAD_PATH
  • :require - require the given libraries

Rack::Server#app: app の生成

もし app オプションが渡されなかったら builder オプションを eval する。builder オプションもなかったら config スクリプト(config.ru のようなスクリプト) を探して eval する。

builder や config スクリプトから app を生成するときは Rack::Builder.new_from_stringRack::Builder.parse_file を使う。

Rack::Builder.new_from_string

config.ru で使う use とかを持ってるクラス。スクリプトを instance_eval しているかと思ったら違って .new_from_string

eval(
  "Rack::Builder.new {\n" + builder_script + "\n}.to_app",
  TOPLEVEL_BINDING,
  file,
  0
)

で builder 生成スクリプトから app を生成している。

Rack::Builder#parse_file

最後は new_from_string を呼ぶ。builder スクリプト文字列を取得するのにいくつ処理がある。

config オプションのファイル名が *.ru だったら

  • そのまま config ファイルをbuilder script として扱う
  • .ru ファイルの最初に出てくる #\-p8080 -s weblick のような行をコマンドラインオプションとして扱う
  • Ruby っぽく __END__ 以降は無視する

config オプションのファイル名が *.ru じゃなかったら

  • require してファイル名と同じコンスタントが app として扱う

Rack::Builder#warmup

builder で warmup {|app| p app } のようなやつが使える。名前の通り、app を走らせる前 (正確には to_app の時) に一度だけ評価できるスクリプトを登録できるみたい。インターネット探しても特に言及されてないし誰得メソッドだ...


おわり