Skip to content

Commit ccc34a3

Browse files
committed
Allow for other hosts than localhost to be proxied.
1 parent f12a090 commit ccc34a3

File tree

1 file changed

+60
-23
lines changed

1 file changed

+60
-23
lines changed

jupyter_server_proxy/handlers.py

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@ def get(self, *args):
2828
dest = src._replace(path=src.path + '/')
2929
self.redirect(urlunparse(dest))
3030

31-
class LocalProxyHandler(WebSocketHandlerMixin, IPythonHandler):
32-
31+
class ProxyHandler(WebSocketHandlerMixin, IPythonHandler):
32+
"""
33+
A tornado request handler that proxies HTTP and websockets from
34+
a given host/port combination.
35+
"""
3336
def __init__(self, *args, **kwargs):
3437
self.proxy_base = ''
3538
self.absolute_url = kwargs.pop('absolute_url', False)
3639
super().__init__(*args, **kwargs)
3740

38-
async def open(self, port, proxied_path=''):
41+
async def open(self, host, port, proxied_path=''):
3942
"""
4043
Called when a client opens a websocket connection.
4144
@@ -45,7 +48,7 @@ async def open(self, port, proxied_path=''):
4548
if not proxied_path.startswith('/'):
4649
proxied_path = '/' + proxied_path
4750

48-
client_uri = self.get_client_uri('ws', port, proxied_path)
51+
client_uri = self.get_client_uri('ws', host, port, proxied_path)
4952
headers = self.request.headers
5053

5154
def message_cb(message):
@@ -141,7 +144,7 @@ def _get_context_path(self, port):
141144
else:
142145
return url_path_join(self.base_url, 'proxy', str(port))
143146

144-
def get_client_uri(self, protocol, port, proxied_path):
147+
def get_client_uri(self, protocol, host, port, proxied_path):
145148
context_path = self._get_context_path(port)
146149
if self.absolute_url:
147150
client_path = url_path_join(context_path, proxied_path)
@@ -150,7 +153,7 @@ def get_client_uri(self, protocol, port, proxied_path):
150153

151154
client_uri = '{protocol}://{host}:{port}{path}'.format(
152155
protocol=protocol,
153-
host='localhost',
156+
host=host,
154157
port=port,
155158
path=client_path
156159
)
@@ -159,11 +162,11 @@ def get_client_uri(self, protocol, port, proxied_path):
159162

160163
return client_uri
161164

162-
def _build_proxy_request(self, port, proxied_path, body):
165+
def _build_proxy_request(self, host, port, proxied_path, body):
163166

164167
headers = self.proxy_request_headers()
165168

166-
client_uri = self.get_client_uri('http', port, proxied_path)
169+
client_uri = self.get_client_uri('http', host, port, proxied_path)
167170
# Some applications check X-Forwarded-Context and X-ProxyContextPath
168171
# headers to see if and where they are being proxied from.
169172
if not self.absolute_url:
@@ -177,7 +180,7 @@ def _build_proxy_request(self, port, proxied_path, body):
177180
return req
178181

179182
@web.authenticated
180-
async def proxy(self, port, proxied_path):
183+
async def proxy(self, host, port, proxied_path):
181184
'''
182185
This serverextension handles:
183186
{base_url}/proxy/{port([0-9]+)}/{proxied_path}
@@ -205,7 +208,7 @@ async def proxy(self, port, proxied_path):
205208

206209
client = httpclient.AsyncHTTPClient()
207210

208-
req = self._build_proxy_request(port, proxied_path, body)
211+
req = self._build_proxy_request(host, port, proxied_path, body)
209212
response = await client.fetch(req, raise_error=False)
210213
# record activity at start and end of requests
211214
self._record_activity()
@@ -242,27 +245,27 @@ def proxy_request_options(self):
242245
# Support all the methods that torando does by default except for GET which
243246
# is passed to WebSocketHandlerMixin and then to WebSocketHandler.
244247

245-
async def http_get(self, port, proxy_path=''):
248+
async def http_get(self, host, port, proxy_path=''):
246249
'''Our non-websocket GET.'''
247-
return await self.proxy(port, proxy_path)
250+
return await self.proxy(host, port, proxy_path)
248251

249-
def post(self, port, proxy_path=''):
250-
return self.proxy(port, proxy_path)
252+
def post(self, host, port, proxy_path=''):
253+
return self.proxy(host, port, proxy_path)
251254

252255
def put(self, port, proxy_path=''):
253-
return self.proxy(port, proxy_path)
256+
return self.proxy(host, port, proxy_path)
254257

255-
def delete(self, port, proxy_path=''):
256-
return self.proxy(port, proxy_path)
258+
def delete(self, host, port, proxy_path=''):
259+
return self.proxy(host, port, proxy_path)
257260

258-
def head(self, port, proxy_path=''):
259-
return self.proxy(port, proxy_path)
261+
def head(self, host, port, proxy_path=''):
262+
return self.proxy(host, port, proxy_path)
260263

261-
def patch(self, port, proxy_path=''):
262-
return self.proxy(port, proxy_path)
264+
def patch(self, host, port, proxy_path=''):
265+
return self.proxy(host, port, proxy_path)
263266

264-
def options(self, port, proxy_path=''):
265-
return self.proxy(port, proxy_path)
267+
def options(self, host, port, proxy_path=''):
268+
return self.proxy(host, port, proxy_path)
266269

267270
def check_xsrf_cookie(self):
268271
'''
@@ -280,6 +283,40 @@ def select_subprotocol(self, subprotocols):
280283
return super().select_subprotocol(subprotocols)
281284

282285

286+
class LocalProxyHandler(ProxyHandler):
287+
"""
288+
A tornado request handler that proxies HTTP and websockets
289+
from a port on the local system. Same as the above ProxyHandler,
290+
but specific to 'localhost'.
291+
"""
292+
async def http_get(self, port, proxied_path):
293+
return await self.proxy(port, proxied_path)
294+
295+
async def open(self, port, proxied_path):
296+
return await super().open('localhost', port, proxied_path)
297+
298+
def post(self, port, proxied_path):
299+
return self.proxy(port, proxied_path)
300+
301+
def put(self, port, proxied_path):
302+
return self.proxy(port, proxied_path)
303+
304+
def delete(self, port, proxied_path):
305+
return self.proxy(port, proxied_path)
306+
307+
def head(self, port, proxied_path):
308+
return self.proxy(port, proxied_path)
309+
310+
def patch(self, port, proxied_path):
311+
return self.proxy(port, proxied_path)
312+
313+
def options(self, port, proxied_path):
314+
return self.proxy(port, proxied_path)
315+
316+
def proxy(self, port, proxied_path):
317+
return super().proxy('localhost', port, proxied_path)
318+
319+
283320
# FIXME: Move this to its own file. Too many packages now import this from nbrserverproxy.handlers
284321
class SuperviseAndProxyHandler(LocalProxyHandler):
285322
'''Manage a given process and requests to it '''

0 commit comments

Comments
 (0)