Ruby on Rack #1 - 与Rack的第一次亲密接触

http://article.yeeyan.org/view/52654/18184

Rack提供了Web服务器和Ruby开发框架之间的接口。它将框架编写者从为每个Web服务器单独编写一个处理模块的繁重负担中解脱出来,可以节省大量重复劳动。

Ruby社区几乎每个星期都会有新的框架出现,但是这些框架里面,Rack 并没有得到足够的关注。它应该被关注。同时,为了全面利用Rack, 在下一个 Rails 稳定版本2.2 之后会有一个更好的公共接口。

Rack 最初的灵感来自于Python的 wsgi ,并且由于它的简单性和准确性,很快在Ruby社区成为了一个实际的web应用/服务器接口。你可能想看看来自于Rack之父-Christian NeukirchenRack介绍

- Rack API Docs

实际上,你可以把"Rack"分成两部分:

Rack 规则

Rack规则指定一个Rack应用和webserver应该如何精确的交互:

- Rack Specification

这只是个简要的说明,你可以在这里看到更详细的内容。

严格的讲,为了写一个Rack ready application你不需要这个rack gem。这样做仅仅是为了规范:

Rack Gem

Rack gem 是一个公共类和辅助类的集合,它可以使每一个Rack app开发者更轻松。它包括了基本的request, response, cookies 以及sessions的实现. 还有相当多有用的中间件。总之,安装rack gem,你只需要这样:

$ sudo gem install rack

总结

  • Rack 是一个支持你自己Ruby框架的框架.
  • Rack 提供一个不同web服务器和你的框架/应用之间的接口。使它可以更容易的让你的框架/应用对任意支持Rack的web服务器兼容– Phusion Passenger, Litespeed, Mongrel, Thin, Ebb, Webrick 仅举几例.
  • Rack消减你的成本.你可以免费的得到request, response, cookies, params 以及sessions .
  • 没有类冲突使得在用一应用使用多个框架成为可能。 Rails 和 sinatra 集成 是个很好的例子。
  • 中间件 ! 想一想Rails的 before_filter/after_filter 可以在支持Rack的不同框架重复使用。例如,在你的Rails应用,Sinatra应用和你自定制的Rack应用里都可以使用同一个Anti-spamming rack中间件。

例子

让我们使用mongrel,从一个可能是最小的rack应用例子来开始。

1


2


3


4


5


6


7


8


9


10


require 'rubygems'


require 'rack'





class HelloWorld


def call(env)


[200, {"Content-Type" => "text/html"}, "Hello Rack!"]


end


end





Rack::Handler::Mongrel.run HelloWorld.new, :Port => 9292

上面的代码传一个HelloWorld对象到mongrel的rack处理器,指定了9292端口。

The HelloWorld object遵循了rack规范 :

  1. call方法仅带一个env参数
  2. call() 方法返回一个数组,包含这三个值 [http_status_code, response_headers_hash, body]

这就够了! 运行脚本,然后浏览器里输入http://localhost:9292, 你就会看到这个耀眼的 “Hello Rack!” 信息。

等等,既然是一个响应call()的ruby过程,为什么不用一个proc来代替呢? 那么,没有理由不这么做:

1


2


3


4


require 'rubygems


require 'rack'





Rack::Handler::Mongrel.run proc {|env| [200, {"Content-Type" => "text/html"}, "Hello Rack!"]}, :Port => 9292

另一种常见的模式是用method(:something), 这会返回一个 Method class 对象:

1


2


3


4


5


6


7


8


require 'rubygems'


require 'rack'





def application(env)


[200, {"Content-Type" => "text/html"}, "Hello Rack!"]


end





Rack::Handler::Mongrel.run method(:application), :Port => 9292

带走你巨慢的“Hello World”表演吧,你不可能再写个比这更快的"Hello World" ruby 应用了。

Rack it up’

如我之前所说,rack gem为rack app开发者带来一大堆有用的东西。 rackup 就是其中之一.在前一个例子里,我直接用了mongrel处理器Rack::Handler::Mongrel ,甚至还有硬编码的端口号。用rackup,这些事情都变得可配置。! 但是用rackup,你需要用一个rackup配置文件来支持它。对于上一个例子,配置文件有点像:

1


2


# config.ru


run Proc.new {|env| [200, {"Content-Type" => "text/html"}, "Hello Rack!"]}

只需要一行,按照约定,你应该使用.ru作为一个rackup配置文件的扩展名。支持它运行一个RackObject 你需要:

$ rackup config.ru

但是默认的,rackup会在9292端口启动一个服务。但是你可以通过一个-p参数来指定这个端口号。你可以看更多的帮助:

$ rackup --help