使用 Eventlet 从 WSGI 应用程序获取客户端 IP 地址
Posted
技术标签:
【中文标题】使用 Eventlet 从 WSGI 应用程序获取客户端 IP 地址【英文标题】:Obtaining Client IP address from a WSGI app using Eventlet 【发布时间】:2011-12-11 17:04:21 【问题描述】:我目前正在编写一个基于 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 地址(即通过环境字典或类似的方法),而不必以某种方式重定向日志对象?
【问题讨论】:
【参考方案1】:你想要的是 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 环境中包含的内容,例如:
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)
【讨论】:
谢谢Marty,事实上,我的下一步就是按照你在第二个sn-p 中的建议去做。也感谢指出代理信息,如果我在前面放了一个负载均衡器,这肯定会引起一些混乱。查看了 WSGI 规范 link,我发现 REMOTE_ADDR 不是必需变量,这可能是我困惑的根源! 我正在阅读有关此标头的一些文档,在我看来,客户端 IP 将是 X-Forwarded-For 中的第一个 ip。所以第一次返回的最后一点应该是.split(',')[0].strip()
。参考:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/…以上是关于使用 Eventlet 从 WSGI 应用程序获取客户端 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章
WSGI:使用 AJAX 从 python 脚本中获取字符串
如何在 Visual Studio 2017 中将包添加到 python
flask-socketio 在安装了 eventlet 的 aws 上不起作用