有人可以解释下面的Ruby代码是如何工作的吗?(取自要点:675667)
require 'rubygems'
require 'rack'
class Object
def webapp
class << self
define_method :call do |env|
func, *attrs = env['PATH_INFO'].split('/').reject(&:empty?)
[200, {}, [send(func, *attrs).to_s]]
end
end
self
end
end
Rack::Handler::Mongrel.run [].webapp, :Port => 9292
# ^^^^^^^^^^^
# | (x)
# ROFLSCALE DB ---/
#
Run Code Online (Sandbox Code Playgroud)
如果我们运行它,我们可以通过Web访问它:
GET http://localhost:9292/push/1 -> 1
GET http://localhost:9292/push/2 -> 12
GET http://localhost:9292/push/3 -> 123
GET http://localhost:9292/to_a -> 123
GET http://localhost:9292/pop -> 3
GET http://localhost:9292/shift -> 1
Run Code Online (Sandbox Code Playgroud)
当然,我们可以运行如下:
GET http://localhost:9292/instance_eval/exec("rm -rf /")
Run Code Online (Sandbox Code Playgroud)
无论如何......它是如何工作的?你能逐步指导我完成代码吗?
tro*_*skn 11
该类Object是Ruby中所有对象的基类.webapp在此定义了一个新方法,使其可以对所有对象进行调用.
在调用时webapp,在self.define_method对象类上调用该方法(但仅针对该特定对象 - 顺便说一下,这称为元类).这call为其实例定义了一个新方法(例如,对象).
这个新call方法env作为参数,并PATH_INFO通过正斜杠和存储在数组中进行拆分.然后将第一个元素分配给变量func,将余数分配给变量attrs.然后send调用magic方法,它基本上通过变量的名称调用方法func.然后它返回一个数组,由一个状态代码(200),一个空哈希和方法调用的输出组成.
在最后一行,创建一个新的数组实例([]是简写Array.new).然后在其webapp上调用该call方法,如上所述,该方法用该方法对其进行了丰富.webapp方便回报self.因此,您可以将其直接传递给它Rack::Handler::Mongrel.run,这将启动Web服务器(Mongrel是Web服务器 - Rack是一个抽象层,为不同的Web服务器提供统一的接口).服务器将请求传递给call方法,并解释返回值以发回响应.