2012-11-14 34 views
0

我有一個Rails應用程序,我想超載request.remote_ip和request.ip才能使用的CloudFlare頭(HTTP_CF_CONNECTING_IP),如果它是目前... 我已經嘗試了這些,但他們都不工作:我該如何重新定義ruby和rails request.ip和request.remote_ip方法?

module Rack 
    class Request 
    class << self 
     def ip 
     @ip ||= (@env['HTTP_CF_CONNECTING_IP'] || super) 
     end 
    end 
    end 
end 

module ActionDispatch 
    class Request < Rack::Request 
    class << self 
     def remote_ip 
     @remote_ip ||= (@env['HTTP_CF_CONNECTING_IP'] || super) 
     end 
    end 
    end 
end 

我不能在application_controller因爲我一些其他的寶石(如色器件)使用一個額外的方法類似

def connecting_ip 
    @env['HTTP_CF_CONNECTING_IP'] || request.remote_ip 
end 

其使用request.ip

謝謝!

+1

你爲什麼要重新定義這些方法指向一個標頭,不添加到您的application.rb中這

config.middleware.insert_before(0, Rack::CloudFlareFixup) 

你可以看到這個完整的要點通常包含IP地址信息? –

+0

對不起,是我不好(我複製和從代碼我是想看看它是否加載某個值粘貼)...正確的頭值是HTTP_CF_CONNECTING_IP,這是對下CloudFlare的 要求設置我也試着刪除類< mikk1

回答

6

我相信request是一個實例。但是你正在定義類方法。刪除class << self胡說八道,而你正在重新定義實例方法。

只是注意的是,這個聽起來有點瘋狂。在那裏小心點。框架不總是喜歡他們的膽量重新排列。


使用實例方法時出現的錯誤消息意味着其他事情正在發生。 super調用超類的實現。但是當你重新打開一個類並重寫某些東西時,你實際上正在覆蓋原來的實現。由於該方法不存在於超類中,因此super不起作用。

取而代之,您可以使用alias來保存之前的原始實現您聲明瞭將替換它的新方法。

module ActionDispatch 
    class Request < Rack::Request 
    alias :remote_ip_orig :remote_ip 
    def remote_ip 
     @remote_ip ||= (@env['HTTP_CF_CONNECTING_IP'] || remote_ip_orig) 
    end 
    end 
end 
+0

我也試過,問題是當標題值不存在時。它會引發錯誤,因爲「超級」: !!處理請求時出現意外錯誤:super:沒有超類方法'ip'for# mikk1

+0

'super'在這裏不起作用。看我的編輯。 –

+2

不應該有別名之間用逗號:'別名:remote_ip_orig:remote_ip' – Shpigford

3

如果你要使用的CloudFlare和檢測的真實IP像我一樣沒有Ngingx或Apache模塊,這隻猴子修補方法是一種非常糟糕的主意,這將導致在未來出現意外結果。如果使用中間件,你會更好。這是我想出並實施的一個。

module Rack 
    class CloudFlareFixup 
    def initialize(app) 
     @app = app 
    end 

    def call(env) 
     if env['HTTP_CF_CONNECTING_IP'] 
     env['HTTP_X_FORWARDED_FOR'] = env['HTTP_CF_CONNECTING_IP'] 
     env['REMOTE_ADDR'] = env['HTTP_CF_CONNECTING_IP'] 
     end 
     @app.call(env) 
    end 
    end 
end 

只需在https://gist.github.com/mattheworiordan/9024372

+1

不要我把哪個目錄在該模塊? –

+0

您的中間件應該放置在ActionDispatch :: RemoteIp中間件之前,而不是位於機架堆棧頂部。 '使用config.middleware.insert_before(ActionDispatch :: REMOTEIP,機架:: CloudFlareFixup)' 這樣'使用ActionDispatch :: ShowExceptions'和'ActionDispatch :: DebugExceptions'可以捕獲應用程序路徑異常之前的請求之前是由您的中間件處理。 您可以在rails api上閱讀更多關於'ActionDispatch :: RemoteIp'的信息: http://api.rubyonrails.org/classes/ActionDispatch/RemoteIp.html – lmmendes

+0

感謝您的支持! –