Skip to content

Commit 06b8ea7

Browse files
committed
Add a warning message, move rename open to proxy_open in the
ProxyHandler.
1 parent ccc34a3 commit 06b8ea7

File tree

1 file changed

+53
-49
lines changed

1 file changed

+53
-49
lines changed

jupyter_server_proxy/handlers.py

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -31,60 +31,16 @@ def get(self, *args):
3131
class ProxyHandler(WebSocketHandlerMixin, IPythonHandler):
3232
"""
3333
A tornado request handler that proxies HTTP and websockets from
34-
a given host/port combination.
34+
a given host/port combination. This class is not meant to be
35+
used directly as a means of overriding CORS. This presents significant
36+
security risks, and could allow arbitrary remote code access. Instead, it is
37+
meant to be subclassed and used for proxying URLs from trusted sources.
3538
"""
3639
def __init__(self, *args, **kwargs):
3740
self.proxy_base = ''
3841
self.absolute_url = kwargs.pop('absolute_url', False)
3942
super().__init__(*args, **kwargs)
4043

41-
async def open(self, host, port, proxied_path=''):
42-
"""
43-
Called when a client opens a websocket connection.
44-
45-
We establish a websocket connection to the proxied backend &
46-
set up a callback to relay messages through.
47-
"""
48-
if not proxied_path.startswith('/'):
49-
proxied_path = '/' + proxied_path
50-
51-
client_uri = self.get_client_uri('ws', host, port, proxied_path)
52-
headers = self.request.headers
53-
54-
def message_cb(message):
55-
"""
56-
Callback when the backend sends messages to us
57-
58-
We just pass it back to the frontend
59-
"""
60-
# Websockets support both string (utf-8) and binary data, so let's
61-
# make sure we signal that appropriately when proxying
62-
self._record_activity()
63-
if message is None:
64-
self.close()
65-
else:
66-
self.write_message(message, binary=isinstance(message, bytes))
67-
68-
def ping_cb(data):
69-
"""
70-
Callback when the backend sends pings to us.
71-
72-
We just pass it back to the frontend.
73-
"""
74-
self._record_activity()
75-
self.ping(data)
76-
77-
async def start_websocket_connection():
78-
self.log.info('Trying to establish websocket connection to {}'.format(client_uri))
79-
self._record_activity()
80-
request = httpclient.HTTPRequest(url=client_uri, headers=headers)
81-
self.ws = await pingable_ws_connect(request=request,
82-
on_message_callback=message_cb, on_ping_callback=ping_cb)
83-
self._record_activity()
84-
self.log.info('Websocket connection established to {}'.format(client_uri))
85-
86-
ioloop.IOLoop.current().add_callback(start_websocket_connection)
87-
8844
def on_message(self, message):
8945
"""
9046
Called when we receive a message from our client.
@@ -232,6 +188,54 @@ async def proxy(self, host, port, proxied_path):
232188
if response.body:
233189
self.write(response.body)
234190

191+
async def proxy_open(self, host, port, proxied_path=''):
192+
"""
193+
Called when a client opens a websocket connection.
194+
195+
We establish a websocket connection to the proxied backend &
196+
set up a callback to relay messages through.
197+
"""
198+
if not proxied_path.startswith('/'):
199+
proxied_path = '/' + proxied_path
200+
201+
client_uri = self.get_client_uri('ws', host, port, proxied_path)
202+
headers = self.request.headers
203+
204+
def message_cb(message):
205+
"""
206+
Callback when the backend sends messages to us
207+
208+
We just pass it back to the frontend
209+
"""
210+
# Websockets support both string (utf-8) and binary data, so let's
211+
# make sure we signal that appropriately when proxying
212+
self._record_activity()
213+
if message is None:
214+
self.close()
215+
else:
216+
self.write_message(message, binary=isinstance(message, bytes))
217+
218+
def ping_cb(data):
219+
"""
220+
Callback when the backend sends pings to us.
221+
222+
We just pass it back to the frontend.
223+
"""
224+
self._record_activity()
225+
self.ping(data)
226+
227+
async def start_websocket_connection():
228+
self.log.info('Trying to establish websocket connection to {}'.format(client_uri))
229+
self._record_activity()
230+
request = httpclient.HTTPRequest(url=client_uri, headers=headers)
231+
self.ws = await pingable_ws_connect(request=request,
232+
on_message_callback=message_cb, on_ping_callback=ping_cb)
233+
self._record_activity()
234+
self.log.info('Websocket connection established to {}'.format(client_uri))
235+
236+
ioloop.IOLoop.current().add_callback(start_websocket_connection)
237+
238+
235239
def proxy_request_headers(self):
236240
'''A dictionary of headers to be used when constructing
237241
a tornado.httpclient.HTTPRequest instance for the proxy request.'''
@@ -293,7 +297,7 @@ async def http_get(self, port, proxied_path):
293297
return await self.proxy(port, proxied_path)
294298

295299
async def open(self, port, proxied_path):
296-
return await super().open('localhost', port, proxied_path)
300+
return await self.proxy_open('localhost', port, proxied_path)
297301

298302
def post(self, port, proxied_path):
299303
return self.proxy(port, proxied_path)

0 commit comments

Comments
 (0)