3.4.5 Ruby
Ruby也是一门通用编程语言,由松本行弘(Yukihiro Matsumoto)发明,并在1996年达到了1.0版。它的主要特征包括开放类定义(open class)、混合器(mixin)和code block等。
对于Ruby语言的学习,我推荐OReilly出版的《The Ruby Programming Language》,其作者之一正是松本行弘。
Ruby在服务器端的编程基于Rack,它是Ruby的一个规范,定义了服务器跟应用程序交互的接口,跟Python的WSGI类似。同样地,这里“服务器”是指接受客户端(如浏览器)HTTP请求的程序,而“应用程序”是指(由你编写的)响应HTTP请求的程序。Ruby所有的Web编程框架都基于Rack,包括Rails在内。因此了解、掌握它十分必要1。
一个Rack的“Hello,world”程序如下:
require 'rack'
app = proc do |env|
['200', {'Content-Type' => 'text/html'}, ['<p>Hello, Rack!</p>']]
end
Rack::Handler::WEBrick.run(app, :Port => 8090, :Host => '0.0.0.0')
其中,app就是我们的Rack应用程序。按照Rack规范:
- Rack应用程序可以是任何具有“call”方法的对象。在这里它是一个proc。
- 它带有一个参数,env,包含了与CGI环境变量类似的输入。
- 它返回一个数组,包含三个元素,分别是HTTP状态代码,应答头(response header)以及消息主体(message body)。
要运行这个程序首先要安装rack(一个Ruby Gem,包含用于构建Rack程序的辅助工具,相当于Python的wsgiref包):
gem install rack
然后在命令行执行(假设程序保存在文件hello.rb中):
ruby hello.rb
在浏览器中访问http://localhost:8090/
,即可看到结果。
与Python WSGI相同,Rack也支持中间件(middleware)。一个简单的例子如下(包含三个文件,文件名在首行注释):
# app.rb
class App
def call(env)
['200', {'Content-Type' => 'text/html'}, ['<p>Hello, Rack!</p>']]
end
end
# middleware.rb
class Middleware
def initialize(app)
@app = app
end
def call(env)
status, headers, body = @app.call(env)
body.each {|line| line.upcase! }
return [status, headers, body]
end
end
# config.ru
require './app'
require './middleware'
use Middleware
run App.new
我们已经说过“Rack应用程序可以是任何具有“call”方法的对象”。在这个例子中,它是一个App类的对象。
中间件也是一个Rack应用程序,但是它“含有”另一个Rack应用程序。Rack服务器调用中间件,传递给它一个env参数,并接受它返回的状态代码、应答头部和消息主体。这样,中间件可以检查、修改env,并把它传递给“内含”的Rack应用程序。它还可以检查、修改内含的Rack应用程序的返回结果,并返回给上级服务器(也可能是另一个中间件!)。在这个例子中,我们把内部App返回的消息主体字符都转化成大写。
虽然简单,但这是一个产品级的配置:我们使用了config.ru来组装我们的Rack应用程序和中间件。config.ru是Rack应用程序的标准配置:它指定了Rack应用程序(通过run
)及中间件(通过use
),把它们组装在一起,形成了一个完整的Rack应用。
要运行这个应用程序,在命令行上执行:
rackup -p 8090 -o 0.0.0.0
然后就可以在浏览器中通过http://localhost:8090/
访问它。
关于Rack的更多信息,可参考:https://github.com/rack/rack。
关于Ruby的Web编程框架,除了著名的Ruby on Rails,还有Sinatra(一个小型轻量级框架)等,它们都基于Rack。
1. 限于篇幅,这里对Rack只做了简单的介绍。若想进一步了解Rack,请看我的博文Ruby Rack及其应用(上)。 ↩