Skip to content

Commit 8df8666

Browse files
committed
Change whitelist to allow for list or callable
1 parent d1feb45 commit 8df8666

File tree

3 files changed

+29
-22
lines changed

3 files changed

+29
-22
lines changed

jupyter_server_proxy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def load_jupyter_server_extension(nbapp):
2929
nbapp.web_app.add_handlers('.*', server_handlers)
3030

3131
# Set up default handler
32-
setup_handlers(nbapp.web_app, serverproxy.host_whitelist_hook)
32+
setup_handlers(nbapp.web_app, serverproxy.host_whitelist)
3333

3434
launcher_entries = []
3535
icons = {}

jupyter_server_proxy/config.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Traitlets based configuration for jupyter_server_proxy
33
"""
44
from notebook.utils import url_path_join as ujoin
5-
from traitlets import Any, Dict
5+
from traitlets import Callable, Dict, List, Union
66
from traitlets.config import Configurable
77
from .handlers import SuperviseAndProxyHandler, AddSlashHandler
88
import pkg_resources
@@ -163,24 +163,29 @@ class ServerProxy(Configurable):
163163
config=True
164164
)
165165

166-
host_whitelist_hook = Any(
167-
lambda handler, host: host in ['localhost', '127.0.0.1'],
166+
host_whitelist = Union(
167+
trait_types=[List(), Callable()],
168168
help="""
169-
Verify that a host should be proxied.
169+
List of allowed hosts.
170+
Can also be a function that decides whether a host can be proxied.
170171
171-
This should be a callable that checks whether a host should be proxied
172-
and returns True if so (False otherwise). It could be a very simple
173-
check that the host is present in a list of allowed hosts, or it could
174-
be a more complex verification against a regular expression. It should
175-
probably not be a slow check against an external service. Here is an
176-
example that could be placed in a site-wide Jupyter notebook config:
172+
If implemented as a function, this should return True if a host should
173+
be proxied and False if it should not. Such a function could verify
174+
that the host matches a particular regular expression pattern or falls
175+
into a specific subnet. It should probably not be a slow check against
176+
some external service. Here is an example that could be placed in a
177+
site-wide Jupyter notebook config:
177178
178-
def hook(handler, host):
179+
def host_whitelist(handler, host):
179180
handler.log.info("Request to proxy to host " + host)
180181
return host.startswith("10.")
181-
c.ServerProxy.host_whitelist_hook = hook
182-
183-
The default check is to return True if the host is localhost.
184-
""",
182+
c.ServerProxy.host_whitelist = host_whitelist
183+
184+
Defaults to a list of ["localhost", "127.0.0.1"].
185+
""",
185186
config=True
186187
)
188+
189+
@default("host_whitelist")
190+
def _host_whitelist_default(self):
191+
return ["localhost", "127.0.0.1"]

jupyter_server_proxy/handlers.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ class ProxyHandler(WebSocketHandlerMixin, IPythonHandler):
4242
def __init__(self, *args, **kwargs):
4343
self.proxy_base = ''
4444
self.absolute_url = kwargs.pop('absolute_url', False)
45-
self.host_whitelist_hook = kwargs.pop('host_whitelist_hook',
46-
lambda handler, host: host in ['localhost', '127.0.0.1'])
45+
self.host_whitelist = kwargs.pop('host_whitelist', ['localhost', '127.0.0.1'])
4746
super().__init__(*args, **kwargs)
4847

4948
# Support all the methods that torando does by default except for GET which
@@ -169,7 +168,10 @@ def _build_proxy_request(self, host, port, proxied_path, body):
169168
return req
170169

171170
def _check_host_whitelist(self, host):
172-
return self.host_whitelist_hook(self, host)
171+
if callable(self.host_whitelist):
172+
return self.host_whitelist(self, host)
173+
else:
174+
return host in self.host_whitelist
173175

174176
@web.authenticated
175177
async def proxy(self, host, port, proxied_path):
@@ -520,13 +522,13 @@ def options(self, path):
520522
return self.proxy(self.port, path)
521523

522524

523-
def setup_handlers(web_app, host_whitelist_hook):
525+
def setup_handlers(web_app, host_whitelist):
524526
host_pattern = '.*$'
525527
web_app.add_handlers('.*', [
526528
(url_path_join(web_app.settings['base_url'], r'/proxy/(.*):(\d+)(.*)'),
527-
RemoteProxyHandler, {'absolute_url': False, 'host_whitelist_hook': host_whitelist_hook}),
529+
RemoteProxyHandler, {'absolute_url': False, 'host_whitelist': host_whitelist}),
528530
(url_path_join(web_app.settings['base_url'], r'/proxy/absolute/(.*):(\d+)(.*)'),
529-
RemoteProxyHandler, {'absolute_url': True, 'host_whitelist_hook': host_whitelist_hook}),
531+
RemoteProxyHandler, {'absolute_url': True, 'host_whitelist': host_whitelist}),
530532
(url_path_join(web_app.settings['base_url'], r'/proxy/(\d+)(.*)'),
531533
LocalProxyHandler, {'absolute_url': False}),
532534
(url_path_join(web_app.settings['base_url'], r'/proxy/absolute/(\d+)(.*)'),

0 commit comments

Comments
 (0)