RACK 具体作用是什么,在整个 ruby web 系统中 rack 处于什么位置?rails 是怎么使用 rack 的?
RACK 官网 http://rack.github.io/ RACK spec http://www.rubydoc.info/github/rack/rack/master/file/SPEC Rack: a Ruby Webserver Interface Rack powers web applications Rack provides a minimal interface between webservers that support Ruby and Ruby frameworks.
To use Rack, provide an "app": an object that responds to the call method, taking the environment hash as a parameter, and returning an Array with three elements:
The HTTP response code A Hash of headers The response body, which must respond to each You can handle an app directly:
Rack 只是一个中间件架构的实现,Rails 本身就是基于 Rack + 其他很多中间件组成的,不信?你在 Rails 项目根目录下执行 rake middleware
,就可以看到你的项目当前的中间件列表及其顺序了:
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000105bb4328>
use ActiveRecord::Migration::CheckPending
# ... others
use Rack::ConditionalGet
use Rack::ETag
use Warden::Manager
use Bullet::Rack
run ProjectName::Application.routes
关于 Rack 的介绍,网上其实非常多资料: https://www.amberbit.com/blog/2011/07/13/introduction-to-rack-middleware/ https://vimeo.com/user12143456/review/69109140/c72efbd052 http://guides.rubyonrails.org/rails_on_rack.html
还有一个非常棒的视频叫做《Rebuilding a Ruby web server》,可以了解 Ruby 基于 Rack 的 Application Server 的架构。
我的理解:作为“Ruby Webserver Interface”来讲,Rack 是 Web 应用服务器和 Web 应用之间的一个协议,等价物应该是 CGI/Java Servlet 规范/WSGI
Rack 最基本的含义是:基于 ruby 的最简版的 web server 和 web framework 的 API, 也就是接口协议 (Interface protocol),定义在 (http://www.rubydoc.info/github/rack/rack/master/file/SPEC). 它的很多想法来自于 python 的 WSGI,基本上可以理解为一个 lambda 表达式:
lambda { |env| [200, {}, ['Hello World!']] }
基于上述最小 API 定义上,人们为了日常使用方便,编写了常用库 Rack (https://github.com/rack/rack)。日常编程中,人们通常提到 Rack,指的就是这个库。
require 'rack'
请注意一下 Rack 的定义 (Rack provides an minimal interface between webservers supporting Ruby and Ruby frameworks). 就是说 Rack 不仅仅可以用来定义 web server API,也可以用来定义 framework。这样,可以使用 pipeline 设计模式,将一系列 Rack 协议兼容组件连接起来完成 web server 的功能。这一系列组件就是 Rack middleware。 在 2 中提到的 Rack 库中,提供了 Rack::Builder 来完成这个 pipeline 的组装。
Rails 一开始基于 CGI 的,后来开始逐渐向 Rack 迁移,到 2.3 版形成稳定版 (http://viget.com/extend/rack-support-in-rails-why-it-matters)。 之后,不断的将 ActionController 的功能移植为 Rack 兼容的组件,纳入 ActionDispatch 中,使得可以用于非 Rails 的应用中。 当然到目前,还有大量的其他框架支持 Rack,请参考:(https://github.com/rack/rack)。
Perl 的 PSGI (http://search.cpan.org/~miyagawa/PSGI-1.10/PSGI.pod)
从协议和规范的角度,暂时没有和 Rack 对等的。[servlet 完全是另一个东西 :) 我就不多说了。]
[1] pry(main)> require 'rack'
=> true
[2] pry(main)> Rack::Server.start(app: Rack::Directory.new(''), Port: 9292, server: "webrick")
[2015-06-19 10:12:06] INFO WEBrick 1.3.1
[2015-06-19 10:12:06] INFO ruby 2.2.0 (2014-12-25) [x86_64-darwin14]
[2015-06-19 10:12:06] INFO WEBrick::HTTPServer#start: pid=12041 port=9292
localhost - - [19/Jun/2015:10:12:16 CST] "GET /Downloads/ HTTP/1.1" 200 59390
http://127.0.0.1:9292/ -> /Downloads/
your lambda has been written wrongly.
[4] pry(main)> Rack::Server.start(app: lambda { |env| [200, {}, ["Hello, World :) "]] }, Port: 9292, server: "webrick")
[2015-06-19 23:52:01] INFO WEBrick 1.3.1
[2015-06-19 23:52:01] INFO ruby 2.2.0 (2014-12-25) [x86_64-darwin14]
[2015-06-19 23:52:01] INFO WEBrick::HTTPServer#start: pid=39622 port=9292
localhost - - [19/Jun/2015:23:52:05 CST] "GET / HTTP/1.1" 200 16
- -> /
localhost - - [19/Jun/2015:23:52:05 CST] "GET /favicon.ico HTTP/1.1" 200 16
- -> /favicon.ico