2011-10-20 97 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 –