diff --git a/jupyterhub/app.py b/jupyterhub/app.py index 8e5b3df1..c4434ad1 100644 --- a/jupyterhub/app.py +++ b/jupyterhub/app.py @@ -937,8 +937,23 @@ class JupyterHub(Application): handlers[i] = tuple(lis) return handlers - extra_handlers = List(help="Register extra page handlers for jupyterhub, should be of the form (,handler)").tag(config=True) - default_url = Any(default_value=None, help='specify default URL for "next_url" (e.g. when user directs to "/"').tag(config=True) + extra_handlers = List( + help=""" + Register extra tornado Handlers for jupyterhub. + + Should be of the form ``("", Handler)`` + + The Hub prefix will be added, so `/my-page` will be served at `/hub/my-page`. + """, + ).tag(config=True) + + default_url = Unicode( + help=""" + The default URL for users when they arrive (e.g. when user directs to "/") + + By default, redirects users to their own server. + """, + ).tag(config=True) def init_handlers(self): h = [] @@ -1541,6 +1556,7 @@ class JupyterHub(Application): authenticator=self.authenticator, spawner_class=self.spawner_class, base_url=self.base_url, + default_url=self.default_url, cookie_secret=self.cookie_secret, cookie_max_age_days=self.cookie_max_age_days, redirect_to_server=self.redirect_to_server, diff --git a/jupyterhub/handlers/base.py b/jupyterhub/handlers/base.py index 658735e6..1e556c0d 100644 --- a/jupyterhub/handlers/base.py +++ b/jupyterhub/handlers/base.py @@ -61,6 +61,10 @@ class BaseHandler(RequestHandler): def base_url(self): return self.settings.get('base_url', '/') + @property + def default_url(self): + return self.settings.get('default_url', '') + @property def version_hash(self): return self.settings.get('version_hash', '') @@ -428,12 +432,15 @@ class BaseHandler(RequestHandler): self.log.warning("Redirecting %s to %s. For sharing public links, use /user-redirect/", self.request.uri, next_url, ) - if not next_url and self.config.JupyterHub.get('default_url'): - next_url = self.config.JupyterHub['default_url'] + + if not next_url: + # custom default URL + next_url = self.default_url if not next_url: # default URL after login - # if self.redirect_to_server, default login URL initiates spawn + # if self.redirect_to_server, default login URL initiates spawn, + # otherwise send to Hub home page (control panel) if user and self.redirect_to_server: next_url = user.url else: diff --git a/jupyterhub/handlers/pages.py b/jupyterhub/handlers/pages.py index f6c57c69..467967f4 100644 --- a/jupyterhub/handlers/pages.py +++ b/jupyterhub/handlers/pages.py @@ -31,7 +31,9 @@ class RootHandler(BaseHandler): """ def get(self): user = self.get_current_user() - if user: + if self.default_url: + url = self.default_url + elif user: url = self.get_next_url(user) else: url = self.settings['login_url'] diff --git a/jupyterhub/tests/test_pages.py b/jupyterhub/tests/test_pages.py index 95507c93..cc4e8fc4 100644 --- a/jupyterhub/tests/test_pages.py +++ b/jupyterhub/tests/test_pages.py @@ -53,6 +53,30 @@ def test_root_redirect(app): assert path == ujoin(app.base_url, 'user/%s/test.ipynb' % name) +@pytest.mark.gen_test +def test_root_default_url_noauth(app): + with mock.patch.dict(app.tornado_settings, + {'default_url': '/foo/bar'}): + r = yield get_page('/', app, allow_redirects=False) + r.raise_for_status() + url = r.headers.get('Location', '') + path = urlparse(url).path + assert path == '/foo/bar' + + +@pytest.mark.gen_test +def test_root_default_url_auth(app): + name = 'wash' + cookies = yield app.login_user(name) + with mock.patch.dict(app.tornado_settings, + {'default_url': '/foo/bar'}): + r = yield get_page('/', app, cookies=cookies, allow_redirects=False) + r.raise_for_status() + url = r.headers.get('Location', '') + path = urlparse(url).path + assert path == '/foo/bar' + + @pytest.mark.gen_test def test_home_no_auth(app): r = yield get_page('home', app, allow_redirects=False)