2011-10-20 98 views
7

我目前正在基於Python Eventlet庫(http://eventlet.net/doc/)編寫一個基本的調度模型服務器。查看了Eventlet(http://eventlet.net/doc/modules/wsgi.html)上的WSGI文檔後,我發現除了客戶端之外,eventlet.wsgi.server函數還記錄了x-forwarded-for頭IP地址。使用Eventlet從WSGI應用程序獲取客戶端IP地址

但是,獲取這種方法的方法是附加一個類似文件的對象(默認爲sys.stderr),然後將該服務器管道連接到該對象。

我希望能夠從應用程序本身(即具有start_response和environ作爲參數的函數)中獲取客戶端IP。事實上,一個環境關鍵將是完美的。有沒有辦法簡單地(即通過environ字典或類似的)獲取IP地址,而不必訴諸重定向日誌對象?

回答

14

你想要的是在wsgi environ,特別是environ['REMOTE_ADDR']

但是,如果涉及代理,則REMOTE_ADDR將是代理的地址,並且客戶端地址將被包含(最有可能)在HTTP_X_FORWARDED_FOR中。

下面是應該做你想做的,在大多數情況下(所有信貸Sævar)功能:

def get_client_address(environ): 
    try: 
     return environ['HTTP_X_FORWARDED_FOR'].split(',')[-1].strip() 
    except KeyError: 
     return environ['REMOTE_ADDR'] 

你可以很容易地看到通過編寫一個簡單的WSGI什麼是包含在WSGI ENVIRON應用程序,並指着它的瀏覽器,例如:

from eventlet import wsgi 
import eventlet 

from pprint import pformat 

def show_env(env, start_response): 
    start_response('200 OK', [('Content-Type', 'text/plain')]) 
    return ['%s\r\n' % pformat(env)] 

wsgi.server(eventlet.listen(('', 8090)), show_env) 

並結合兩...

from eventlet import wsgi 
import eventlet 

from pprint import pformat 

def get_client_address(environ): 
    try: 
     return environ['HTTP_X_FORWARDED_FOR'].split(',')[-1].strip() 
    except KeyError: 
     return environ['REMOTE_ADDR'] 

def show_env(env, start_response): 
    start_response('200 OK', [('Content-Type', 'text/plain')]) 
    return ['%s\r\n\r\nClient Address: %s\r\n' % (pformat(env), get_client_address(env))] 

wsgi.server(eventlet.listen(('', 8090)), show_env) 
+1

感謝馬蒂,事實上,我的下一步行動就是像你在第二段中所建議的那樣。還要感謝指出代理信息,如果我在前面放置負載平衡器,這肯定會造成一些混淆。 查看了WSGI規範[鏈接](http://www.python.org/dev/peps/pep-0333/#environ-variables),我看到REMOTE_ADDR不是必需的變量,可能是我的困惑之源! –

+0

我正在閱讀關於此頭文件的一些文檔,在我看來,客戶端IP將成爲X-Forwarded-For中的第一個IP。因此,第一次返回的最後一位應該是'.split(',')[0] .strip()'。參考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For –