Merge branch 'master' into remove-unused-imports

This commit is contained in:
Erik Sundell
2020-10-01 12:07:37 +02:00
90 changed files with 2005 additions and 1110 deletions

View File

@@ -635,8 +635,15 @@ class BaseHandler(RequestHandler):
)
if not next_url:
# custom default URL
next_url = default or self.default_url
# custom default URL, usually passed because user landed on that page but was not logged in
if default:
next_url = default
else:
# As set in jupyterhub_config.py
if callable(self.default_url):
next_url = self.default_url(self)
else:
next_url = self.default_url
if not next_url:
# default URL after login
@@ -651,8 +658,42 @@ class BaseHandler(RequestHandler):
next_url = url_path_join(self.hub.base_url, 'spawn')
else:
next_url = url_path_join(self.hub.base_url, 'home')
next_url = self.append_query_parameters(next_url, exclude=['next'])
return next_url
def append_query_parameters(self, url, exclude=None):
"""Append the current request's query parameters to the given URL.
Supports an extra optional parameter ``exclude`` that when provided must
contain a list of parameters to be ignored, i.e. these parameters will
not be added to the URL.
This is important to avoid infinite loops with the next parameter being
added over and over, for instance.
The default value for ``exclude`` is an array with "next". This is useful
as most use cases in JupyterHub (all?) won't want to include the next
parameter twice (the next parameter is added elsewhere to the query
parameters).
:param str url: a URL
:param list exclude: optional list of parameters to be ignored, defaults to
a list with "next" (to avoid redirect-loops)
:rtype (str)
"""
if exclude is None:
exclude = ['next']
if self.request.query:
query_string = [
param
for param in parse_qsl(self.request.query)
if param[0] not in exclude
]
if query_string:
url = url_concat(url, query_string)
return url
async def auth_to_user(self, authenticated, user=None):
"""Persist data from .authenticate() or .refresh_user() to the User database
@@ -673,9 +714,10 @@ class BaseHandler(RequestHandler):
raise ValueError("Username doesn't match! %s != %s" % (username, user.name))
if user is None:
new_user = username not in self.users
user = self.user_from_username(username)
user = self.find_user(username)
new_user = user is None
if new_user:
user = self.user_from_username(username)
await maybe_future(self.authenticator.add_user(user))
# Only set `admin` if the authenticator returned an explicit value.
if admin is not None and admin != user.admin:
@@ -874,7 +916,7 @@ class BaseHandler(RequestHandler):
self.log.error(
"Stopping %s to avoid inconsistent state", user_server_name
)
await user.stop()
await user.stop(server_name)
PROXY_ADD_DURATION_SECONDS.labels(status='failure').observe(
time.perf_counter() - proxy_add_start_time
)
@@ -907,6 +949,9 @@ class BaseHandler(RequestHandler):
self.settings['failure_count'] = 0
return
# spawn failed, increment count and abort if limit reached
SERVER_SPAWN_DURATION_SECONDS.labels(
status=ServerSpawnStatus.failure
).observe(time.perf_counter() - spawn_start_time)
self.settings.setdefault('failure_count', 0)
self.settings['failure_count'] += 1
failure_count = self.settings['failure_count']
@@ -939,13 +984,16 @@ class BaseHandler(RequestHandler):
# waiting_for_response indicates server process has started,
# but is yet to become responsive.
if spawner._spawn_pending and not spawner._waiting_for_response:
# still in Spawner.start, which is taking a long time
# we shouldn't poll while spawn is incomplete.
self.log.warning(
"User %s is slow to start (timeout=%s)",
user_server_name,
self.slow_spawn_timeout,
)
# If slow_spawn_timeout is intentionally disabled then we
# don't need to log a warning, just return.
if self.slow_spawn_timeout > 0:
# still in Spawner.start, which is taking a long time
# we shouldn't poll while spawn is incomplete.
self.log.warning(
"User %s is slow to start (timeout=%s)",
user_server_name,
self.slow_spawn_timeout,
)
return
# start has finished, but the server hasn't come up
@@ -1082,7 +1130,10 @@ class BaseHandler(RequestHandler):
except gen.TimeoutError:
# hit timeout, but stop is still pending
self.log.warning(
"User %s:%s server is slow to stop", user.name, server_name
"User %s:%s server is slow to stop (timeout=%s)",
user.name,
server_name,
self.slow_stop_timeout,
)
# return handle on the future for hooking up callbacks
@@ -1141,6 +1192,8 @@ class BaseHandler(RequestHandler):
for service in self.services.values():
if not service.url:
continue
if not service.display:
continue
accessible_services.append(service)
return accessible_services