ipython-notebook-proxyに触発され、ipydraに基づいており、後者を拡張して、より複雑なユーザー認証とプロキシをサポートします。私の使用例では、ポート 80 のみを公開できるためです。
ワーカーにフラスコ ソケットを使用してgunicorn
いますが、WebSocket のプロキシに問題があります。IPython は/shell
、/stdin
、およびの 3 つの異なる WebSockets 接続を使用しますが、最初の 2/iopub
つのみしか取得できません。101 Switching Protocols
と/stdin
すぐConnection Close Frame
に作成されます。
問題の抜粋コードは次のとおりです。
# Flask imports...
from werkzeug import LocalProxy
from ws4py.client.geventclient import WebSocketClient
# I use my own LocalProxy because flask-sockets does not support Werkzeug Rules
websocket = LocalProxy(lambda: request.environ.get('wsgi.websocket', None))
websockets = {}
PROXY_DOMAIN = "127.0.0.1:8888" # IPython host and port
methods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH",
"CONNECT"]
@app.route('/', defaults={'url': ''}, methods=methods)
@app.route('/<path:url>', methods=methods)
def proxy(url):
with app.test_request_context():
if websocket:
while True:
data = websocket.receive()
websocket_url = 'ws://{}/{}'.format(PROXY_DOMAIN, url)
if websocket_url not in websockets:
client = WebSocketClient(websocket_url,
protocols=['http-only', 'chat'])
websockets[websocket_url] = client
else:
client = websockets[websocket_url]
client.connect()
if data:
client.send(data)
client_data = client.receive()
if client_data:
websocket.send(client_data)
return Response()
また、独自の WebSocket プロキシ クラスを作成しようとしましたが、どちらも機能しません。
class WebSocketProxy(WebSocketClient):
def __init__(self, to, *args, **kwargs):
self.to = to
print(("Proxy to", self.to))
super(WebSocketProxy, self).__init__(*args, **kwargs)
def opened(self):
m = self.to.receive()
print("<= %d %s" % (len(m), str(m)))
self.send(m)
def closed(self, code, reason):
print(("Closed down", code, reason))
def received_message(self, m):
print("=> %d %s" % (len(m), str(m)))
self.to.send(m)
通常のリクエストとレスポンスのサイクルは魅力的なので、そのコードを削除しました。興味がある場合は、完全なコードがhidraにホストされています。
サーバーを実行します
$ gunicorn -k flask_sockets.worker hidra:app