mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-13 13:03:01 +00:00
Provide more detailed error message in case of version mismatch
this is the most likely cause of redirect loops when using docker, so record the spawner version and check it when a redirect is detected. In the event of a redirect and mismatch, fail with a message explaining the version mismatch and how to fix it.
This commit is contained in:
@@ -35,8 +35,11 @@ def _check_version(hub_version, singleuser_version, log):
|
|||||||
else:
|
else:
|
||||||
# log warning-level for more significant mismatch, such as 0.8 vs 0.9, etc.
|
# log warning-level for more significant mismatch, such as 0.8 vs 0.9, etc.
|
||||||
log_method = log.warning
|
log_method = log.warning
|
||||||
log_method("jupyterhub version %s != jupyterhub-singleuser version %s",
|
extra = " This could cause failure to authenticate and result in redirect loops!"
|
||||||
hub_version, singleuser_version,
|
log_method(
|
||||||
|
"jupyterhub version %s != jupyterhub-singleuser version %s." + extra,
|
||||||
|
hub_version,
|
||||||
|
singleuser_version,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
log.debug("jupyterhub and jupyterhub-singleuser both on version %s" % hub_version)
|
log.debug("jupyterhub and jupyterhub-singleuser both on version %s" % hub_version)
|
||||||
|
@@ -20,7 +20,7 @@ from .. import __version__
|
|||||||
from .. import orm
|
from .. import orm
|
||||||
from ..objects import Server
|
from ..objects import Server
|
||||||
from ..spawner import LocalProcessSpawner
|
from ..spawner import LocalProcessSpawner
|
||||||
from ..utils import default_server_name, url_path_join, exponential_backoff
|
from ..utils import default_server_name, url_path_join
|
||||||
|
|
||||||
# pattern for the authentication token header
|
# pattern for the authentication token header
|
||||||
auth_header_pat = re.compile(r'^(?:token|bearer)\s+([^\s]+)$', flags=re.IGNORECASE)
|
auth_header_pat = re.compile(r'^(?:token|bearer)\s+([^\s]+)$', flags=re.IGNORECASE)
|
||||||
@@ -675,7 +675,10 @@ class UserSpawnHandler(BaseHandler):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# spawn has supposedly finished, check on the status
|
# spawn has supposedly finished, check on the status
|
||||||
status = yield spawner.poll()
|
if spawner.ready:
|
||||||
|
status = yield spawner.poll()
|
||||||
|
else:
|
||||||
|
status = 0
|
||||||
if status is not None:
|
if status is not None:
|
||||||
if spawner.options_form:
|
if spawner.options_form:
|
||||||
self.redirect(url_concat(url_path_join(self.hub.base_url, 'spawn'),
|
self.redirect(url_concat(url_path_join(self.hub.base_url, 'spawn'),
|
||||||
@@ -693,9 +696,23 @@ class UserSpawnHandler(BaseHandler):
|
|||||||
self.log.warning("Invalid redirects argument %r", self.get_argument('redirects'))
|
self.log.warning("Invalid redirects argument %r", self.get_argument('redirects'))
|
||||||
redirects = 0
|
redirects = 0
|
||||||
|
|
||||||
if redirects >= self.settings.get('user_redirect_limit', 5):
|
# check redirect limit to prevent browser-enforced limits.
|
||||||
|
# In case of version mismatch, raise on only two redirects.
|
||||||
|
if redirects >= self.settings.get(
|
||||||
|
'user_redirect_limit', 4
|
||||||
|
) or (redirects >= 2 and spawner._jupyterhub_version != __version__):
|
||||||
# We stop if we've been redirected too many times.
|
# We stop if we've been redirected too many times.
|
||||||
raise web.HTTPError(500, "Redirect loop detected.")
|
msg = "Redirect loop detected."
|
||||||
|
if spawner._jupyterhub_version != __version__:
|
||||||
|
msg += (
|
||||||
|
" Notebook has jupyterhub version {singleuser}, but the Hub expects {hub}."
|
||||||
|
" Try installing jupyterhub=={hub} in the user environment"
|
||||||
|
" if you continue to have problems."
|
||||||
|
).format(
|
||||||
|
singleuser=spawner._jupyterhub_version or 'unknown (likely < 0.8)',
|
||||||
|
hub=__version__,
|
||||||
|
)
|
||||||
|
raise web.HTTPError(500, msg)
|
||||||
|
|
||||||
# set login cookie anew
|
# set login cookie anew
|
||||||
self.set_login_cookie(current_user)
|
self.set_login_cookie(current_user)
|
||||||
|
@@ -53,6 +53,7 @@ class Spawner(LoggingConfigurable):
|
|||||||
_stop_pending = False
|
_stop_pending = False
|
||||||
_proxy_pending = False
|
_proxy_pending = False
|
||||||
_waiting_for_response = False
|
_waiting_for_response = False
|
||||||
|
_jupyterhub_version = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _log_name(self):
|
def _log_name(self):
|
||||||
|
@@ -472,6 +472,9 @@ class User(HasTraits):
|
|||||||
else:
|
else:
|
||||||
server_version = resp.headers.get('X-JupyterHub-Version')
|
server_version = resp.headers.get('X-JupyterHub-Version')
|
||||||
_check_version(__version__, server_version, self.log)
|
_check_version(__version__, server_version, self.log)
|
||||||
|
# record the Spawner version for better error messages
|
||||||
|
# if it doesn't work
|
||||||
|
spawner._jupyterhub_version = server_version
|
||||||
finally:
|
finally:
|
||||||
spawner._waiting_for_response = False
|
spawner._waiting_for_response = False
|
||||||
spawner._start_pending = False
|
spawner._start_pending = False
|
||||||
|
Reference in New Issue
Block a user