[英]Accessing RPC caller's IP and HTTP connect headers inside ApplicationSession's registered endpoint
我正在使用带有asyncio的Python 3.4的Autobahn 0.9.2。
问题:使用WAMP,是否可以从RPC端点内部访问作为呼叫者的IP和HTTP连接头的对等体? 建立连接时,此信息是否仍然存在? 如果没有,我将如何开始扩展一些工厂来支持这个?
我的目标很简单:我希望有一个RPC端点来对连接对等体(调用者)的IP进行地理定位,并将增强数据中继到Redis。 我已经阅读了源代码并知道信息传递的位置(autobahn.websocket.protocol.WebSocketServerProtocol - > onConnect(request))但是从onJoin回调中定义的ApplicationSession的RPC端点向下钻取它时遇到了麻烦。 我尝试遍历传输/路由器/路由器会话链,但没有设法到达那里。 我对初始连接请求中的Peer的IP和HTTP头感兴趣。
这是蒸馏成分:
class IncomingComponent(ApplicationSession):
def __init__(self, **params):
super().__init__()
self.redis = StrictRedis(host=config["redis"]["host"], port=config["redis"]["port"], db=config["redis"]["databases"]["ailytics"])
def onConnect(self):
self.join("abc")
@asyncio.coroutine
def onJoin(self, details):
def geolocalize_and_store_event(event, detail):
# Geolocalize here! Have access to caller ID through detail
self.redis.rpush("abc:events", json.dumps(event))
yield from self.register(
geolocalize_and_store_event,
"abc.geolocalize_and_store_event",
options=RegisterOptions(details_arg='detail', discloseCaller = True)
)
并初始化服务器:
router_factory = wamp.RouterFactory()
session_factory = wamp.RouterSessionFactory(router_factory)
session_factory.add(IncomingComponent())
transport_factory = websocket.WampWebSocketServerFactory(session_factory, debug=False, debug_wamp=False)
loop = asyncio.get_event_loop()
coro = loop.create_server(transport_factory, '0.0.0.0', 7788)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
server.close()
loop.close()
您至少可以通过crossbar.io中的wamp.session.get
meta-API访问额外的会话/传输信息:
@inlineCallbacks
def onJoin(self, ign):
@inlineCallbacks
def method(details):
session = yield self.call('wamp.session.get', details.caller)
peer = session['transport']['peer']
print "peer's address", peer
headers = session['transport']['http_headers_received']
print "headers:"
print '\n'.join(['{}: {}'.format(k, v) for (k, v) in headers.items()])
yield self.register(
method, 'some_method',
types.RegisterOptions(details_arg='details'),
)
功能还没有像@oberstet所说的那样,但是由于使用工厂模式的高速公路/ WAMP,我能够在不更改库代码的情况下提出解决方案。
子类有3个组件:
首先,我们将一个ipAddress实例变量添加到wamp.RouterSession的子类中
class IncomingServerSession(wamp.RouterSession):
def __init__(self, routerFactory):
super().__init__(routerFactory)
self.ipAddress = None
然后我们使wamp.RouterSessionFactory子类使用IncomingServerSession
class IncomingServerSessionFactory(wamp.RouterSessionFactory):
session = IncomingServerSession
最后,我们将websocket.WampWebSocketServerProtocol子类化并设置ipAddress实例变量。 由于我们处于onOpen回调中,因此我们可以访问对等和HTTP标头。 我的服务器是反向代理的,所以我正在寻找对等的自定义HTTP头。
class IncomingServerProtocol(websocket.WampWebSocketServerProtocol):
def onOpen(self):
try:
self._session = self.factory._factory()
# Use your own header or just the peer if not reverse-proxied
self._session.ipAddress = (self.http_headers.get('x-real-ip') or self.peer)
self._session.onOpen(self)
except Exception as e:
if self.factory.debug_wamp:
traceback.print_exc()
# # Exceptions raised in onOpen are fatal ..
reason = "WAMP Internal Error ({})".format(e)
self._bailout(protocol.WebSocketProtocol.CLOSE_STATUS_CODE_INTERNAL_ERROR, reason=reason)
以下是我们如何在RPC调用中访问对等方的IP:
@asyncio.coroutine
def onJoin(self, details):
def event(e, details):
caller_session_id = details.caller
caller_session = self._transport._router._dealer._session_id_to_session[caller_session_id]
print(caller_session.ipAddress)
#discloseCaller needs to be True
yield from self.register(event, "abc.event", options=RegisterOptions(details_arg='details', discloseCaller=True))
最后,我们需要更新我们的初始化代码以使用我们的子类:
router_factory = wamp.RouterFactory()
session_factory = IncomingServerSessionFactory(router_factory)
session_factory.add(IncomingComponent())
transport_factory = websocket.WampWebSocketServerFactory(session_factory, debug=False, debug_wamp=False)
transport_factory.protocol = IncomingServerProtocol
loop = asyncio.get_event_loop()
coro = loop.create_server(transport_factory, '0.0.0.0', 7788)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
server.close()
loop.close()
这是你如何做到这一点,直到有官方支持!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.