2010-11-16 93 views
4

有人可以解釋以下Ruby代碼的工作原理嗎? (從gist: 675667拍攝)通過Web公開任何Ruby對象

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 ---/ 
# 

如果我們運行它,我們就可以通過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 

當然,我們可以運行類似:

GET http://localhost:9292/instance_eval/exec("rm -rf /") 

反正。 .. 它是如何工作的?你能一步一步地通讀代碼嗎?

回答

11

Object是Ruby中所有對象的基類。在此定義了一個新方法webapp,這使得它可以爲所有對象調用。

當調用webapp時,方法self.define_method在對象類上調用(但僅限於該特定對象 - 順便提一句,這叫做meta-class)。這爲其實例(例如對象)定義了一個新方法call

這個新的call方法需要env作爲參數,並將PATH_INFO以正斜槓分隔並存儲在數組中。然後將第一個元素分配給變量func,將其餘分配給變量attrs。然後調用魔術方法send,該方法基本上通過變量func的名稱調用方法。然後它返回一個包含狀態碼(200),空散列和方法調用輸出的數組。

在最後一行創建一個新的數組實例([]Array.new的簡寫)。然後調用方法webapp,如上所述,該方法使用call方法豐富它。 webapp方便返回self。因此,您可以直接將它傳遞給Rack::Handler::Mongrel.run,它將啓動一個Web服務器(Mongrel是Web服務器 - Rack是一個爲不同Web服務器提供統一接口的抽象層)。服務器會將請求傳遞給call方法,並解釋返回值以發回響應。

0

不知道你對Ruby有多熟悉 - 讓我知道什麼是沒有意義的。

第1行和第2行導入啓動Web服務器所需的庫。

然後在第4行中,重新打開基類Object以向其中添加新的方法 - 您可以在Ruby中隨心所欲地執行此操作。所有類都從Object繼承,所以無論您在此定義的方法都可以在任何對象上調用。

第5行開始爲所有對象定義一種新方法,稱爲webapp

第6行和第7行爲實例化的Object的每個實例定義了方法call。我認爲這基本上等同於使用self.call來定義該方法。

線8取URL(例如push/1to_a)的相對部分,並將它分爲兩​​個部分,(即funcattrs可變長度字符串)。

9號線然後返回原始HTTP響應,包含在狀態碼(200),報頭(在這種情況下,空的:{})的,和身體([send(func, *attrs).to_s])

本體由所述對象的所述響應的方法func,參數爲attrs。所以如果請求的URL是push/1,方法push將被調用1參數。這相當於[push(1).to_s]to_s將方法返回的值轉換爲字符串。

最後,第16行,一個網絡服務器上啓動端口9292的對象,該方法webapp上調用爲空數組 - 你可以使用一個String(即'')或Hash(即{})或一個Proc(即Proc.new)或任何你喜歡的ruby類。

然後,您可以通過點擊func/attribute1/attribute2/attribute3...表單的URL來操縱對象,該對象將使用參數attribute1, attribute2, attribute3...的字符串調用方法func

有趣的代碼!

+0

爲什麼downvote? – nfm 2011-06-29 00:56:43