diff --git a/jupyterhub/app.py b/jupyterhub/app.py index 1acba858..678a96c4 100644 --- a/jupyterhub/app.py +++ b/jupyterhub/app.py @@ -235,11 +235,18 @@ class JupyterHub(Application): ) subdomain_host = Unicode('', config=True, - help="""The public-facing host (domain[:port]) on which the Hub will run. - - Only used when subdomains are involved. - """ - ) + help="""Run single-user servers on subdomains of this host. + + This should be the full https://hub.domain.tld[:port] + + Provides additional cross-site protections for javascript served by single-user servers. + + Requires .hub.domain.tld to resolve to the same host as hub.domain.tld. + + In general, this is most easily achieved with wildcard DNS. + + When using SSL (i.e. always) this also requires a wildcard SSL certificate. + """) def _subdomain_host_changed(self, name, old, new): if new and '://' not in new: # host should include '://' @@ -262,18 +269,6 @@ class JupyterHub(Application): help="Supply extra arguments that will be passed to Jinja environment." ) - use_subdomains = Bool(False, config=True, - help="""Run single-user servers on subdomains. - - Provides additional cross-site protections for client-side js. - - Requires .hub.domain.tld to resolve to the same host as hub.domain.tld. - - In general, this is most easily achieved with wildcard DNS. - - When using SSL (i.e. always) this also requires a wildcard cert. - """) - proxy_cmd = Command('configurable-http-proxy', config=True, help="""The command to start the http proxy. @@ -599,14 +594,14 @@ class JupyterHub(Application): q = self.db.query(orm.Hub) assert q.count() <= 1 self._local.hub = q.first() - if self.use_subdomains and self._local.hub: + if self.subdomain_host and self._local.hub: self._local.hub.host = self.subdomain_host return self._local.hub @hub.setter def hub(self, hub): self._local.hub = hub - if hub and self.use_subdomains: + if hub and self.subdomain_host: hub.host = self.subdomain_host @property @@ -660,7 +655,7 @@ class JupyterHub(Application): server.ip = self.hub_ip server.port = self.hub_port server.base_url = self.hub_prefix - if self.use_subdomains: + if self.subdomain_host: if not self.subdomain_host: raise ValueError("Must specify subdomain_host when using subdomains." " This should be the public domain[:port] of the Hub.") @@ -842,7 +837,7 @@ class JupyterHub(Application): '--api-port', str(self.proxy.api_server.port), '--default-target', self.hub.server.host, ] - if self.use_subdomains: + if self.subdomain_host: cmd.append('--host-routing') if self.debug_proxy: cmd.extend(['--log-level', 'debug']) @@ -952,7 +947,6 @@ class JupyterHub(Application): template_path=self.template_paths, jinja2_env=jinja_env, version_hash=version_hash, - use_subdomains=self.use_subdomains, subdomain_host=subdomain_host, domain=domain, ) diff --git a/jupyterhub/handlers/base.py b/jupyterhub/handlers/base.py index 376b1c9d..9e9f1b1d 100644 --- a/jupyterhub/handlers/base.py +++ b/jupyterhub/handlers/base.py @@ -52,8 +52,8 @@ class BaseHandler(RequestHandler): return self.settings.get('version_hash', '') @property - def use_subdomains(self): - return self.settings.get('use_subdomains', False) + def subdomain_host(self): + return self.settings.get('subdomain_host', '') @property def domain(self): @@ -208,7 +208,7 @@ class BaseHandler(RequestHandler): else: user = self.find_user(name) kwargs = {} - if self.use_subdomains: + if self.subdomain_host: kwargs['domain'] = self.domain if user and user.server: self.clear_cookie(user.server.cookie_name, path=user.server.base_url, **kwargs) @@ -221,7 +221,7 @@ class BaseHandler(RequestHandler): kwargs = {'secure': True} else: kwargs = {} - if self.use_subdomains: + if self.subdomain_host: kwargs['domain'] = self.domain self.log.debug("Setting cookie for %s: %s, %s", user.name, server.cookie_name, kwargs) self.set_secure_cookie( @@ -241,7 +241,7 @@ class BaseHandler(RequestHandler): def set_login_cookie(self, user): """Set login cookies for the Hub and single-user server.""" - if self.use_subdomains and not self.request.host.startswith(self.domain): + if self.subdomain_host and not self.request.host.startswith(self.domain): self.log.warning( "Possibly setting cookie on wrong domain: %s != %s", self.request.host, self.domain) @@ -482,7 +482,7 @@ class UserSpawnHandler(BaseHandler): self.set_login_cookie(current_user) without_prefix = self.request.uri[len(self.hub.server.base_url):] target = url_path_join(self.base_url, without_prefix) - if self.use_subdomains: + if self.subdomain_host: target = current_user.host + target self.redirect(target) else: diff --git a/jupyterhub/tests/mocking.py b/jupyterhub/tests/mocking.py index 0d2f6bef..b3eb763b 100644 --- a/jupyterhub/tests/mocking.py +++ b/jupyterhub/tests/mocking.py @@ -114,9 +114,6 @@ class MockHub(JupyterHub): def _subdomain_host_default(self): return os.environ.get('JUPYTERHUB_TEST_SUBDOMAIN_HOST', '') - def _use_subdomains_default(self): - return bool(self.subdomain_host) - def _ip_default(self): return '127.0.0.1' @@ -181,7 +178,7 @@ class MockHub(JupyterHub): def public_host(app): - if app.use_subdomains: + if app.subdomain_host: return app.subdomain_host else: return app.proxy.public_server.host @@ -192,7 +189,7 @@ def public_url(app): def user_url(user, app): - if app.use_subdomains: + if app.subdomain_host: host = user.host else: host = public_host(app) diff --git a/jupyterhub/tests/test_api.py b/jupyterhub/tests/test_api.py index db2c2a44..bd5408d7 100644 --- a/jupyterhub/tests/test_api.py +++ b/jupyterhub/tests/test_api.py @@ -363,7 +363,7 @@ def test_spawn(app, io_loop): argv = r.json() for expected in ['--user=%s' % name, '--base-url=%s' % user.server.base_url]: assert expected in argv - if app.use_subdomains: + if app.subdomain_host: assert '--hub-host=%s' % app.subdomain_host in argv r = api_request(app, 'users', name, 'server', method='delete') diff --git a/jupyterhub/tests/test_proxy.py b/jupyterhub/tests/test_proxy.py index 5245da37..9947d829 100644 --- a/jupyterhub/tests/test_proxy.py +++ b/jupyterhub/tests/test_proxy.py @@ -35,7 +35,7 @@ def test_external_proxy(request, io_loop): '--api-port', str(proxy_port), '--default-target', 'http://%s:%i' % (app.hub_ip, app.hub_port), ] - if app.use_subdomains: + if app.subdomain_host: cmd.append('--host-routing') proxy = Popen(cmd, env=env) def _cleanup_proxy(): @@ -64,7 +64,7 @@ def test_external_proxy(request, io_loop): routes = io_loop.run_sync(app.proxy.get_routes) user_path = '/user/river' - if app.use_subdomains: + if app.subdomain_host: domain = urlparse(app.subdomain_host).hostname user_path = '/%s.%s' % (name, domain) + user_path assert sorted(routes.keys()) == ['/', user_path] @@ -97,7 +97,7 @@ def test_external_proxy(request, io_loop): '--api-port', str(proxy_port), '--default-target', 'http://%s:%i' % (app.hub_ip, app.hub_port), ] - if app.use_subdomains: + if app.subdomain_host: cmd.append('--host-routing') proxy = Popen(cmd, env=env) wait_for_proxy() diff --git a/jupyterhub/user.py b/jupyterhub/user.py index cf4a91ae..e7b79c07 100644 --- a/jupyterhub/user.py +++ b/jupyterhub/user.py @@ -158,7 +158,7 @@ class User(HasTraits): @property def proxy_path(self): - if self.settings.get('use_subdomains'): + if self.settings.get('subdomain_host'): return url_path_join('/' + self.domain, self.server.base_url) else: return self.server.base_url @@ -183,7 +183,7 @@ class User(HasTraits): Full name.domain/path if using subdomains, otherwise just my /base/url """ - if self.settings.get('use_subdomains'): + if self.settings.get('subdomain_host'): return '{host}{path}'.format( host=self.host, path=self.server.base_url,