10

我目前正在编写一个基于 Python Eventlet 库 (http://eventlet.net/doc/) 的基本调度模型服务器。查看了 Eventlet 上的 WSGI 文档(http://eventlet.net/doc/modules/wsgi.html),我可以看到 eventlet.wsgi.server 函数除了客户端之外还记录了 x-forwarded-for 标头IP地址。

但是,获得这个的方法是附加一个类似文件的对象(默认为 sys.stderr),然后让服务器将其连接到该对象。

我希望能够从应用程序本身(即具有 start_response 和 environ 作为参数的函数)中获取客户端 IP。事实上,环境键将是完美的。有没有办法简单地获取 IP 地址(即通过环境字典或类似的),而不必以某种方式重定向日志对象?

4

1 回答 1

17

你想要的是在 wsgi环境中,特别是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 环境中包含的内容,例如:

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)
于 2011-10-20T17:10:20.540 回答