mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-18 23:42:59 +00:00
Teach FormSpawner to handle query next=/path/to/landing
* before, if /user-redirect/ was used, or if ?next=/path/ and there was a FormSpawner, the query param would be lost
This commit is contained in:
@@ -529,7 +529,8 @@ class UserSpawnHandler(BaseHandler):
|
|||||||
status = yield current_user.spawner.poll()
|
status = yield current_user.spawner.poll()
|
||||||
if status is not None:
|
if status is not None:
|
||||||
if current_user.spawner.options_form:
|
if current_user.spawner.options_form:
|
||||||
self.redirect(url_path_join(self.hub.server.base_url, 'spawn'))
|
self.redirect(url_concat(url_path_join(self.hub.server.base_url, 'spawn'),
|
||||||
|
{'next': self.request.uri}))
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
yield self.spawn_single_user(current_user)
|
yield self.spawn_single_user(current_user)
|
||||||
|
@@ -7,6 +7,7 @@ from http.client import responses
|
|||||||
|
|
||||||
from jinja2 import TemplateNotFound
|
from jinja2 import TemplateNotFound
|
||||||
from tornado import web, gen
|
from tornado import web, gen
|
||||||
|
from tornado.httputil import url_concat
|
||||||
|
|
||||||
from .. import orm
|
from .. import orm
|
||||||
from ..utils import admin_only, url_path_join
|
from ..utils import admin_only, url_path_join
|
||||||
@@ -66,8 +67,13 @@ class HomeHandler(BaseHandler):
|
|||||||
if user.running:
|
if user.running:
|
||||||
# trigger poll_and_notify event in case of a server that died
|
# trigger poll_and_notify event in case of a server that died
|
||||||
yield user.spawner.poll_and_notify()
|
yield user.spawner.poll_and_notify()
|
||||||
|
url = user.url
|
||||||
|
else:
|
||||||
|
url = url_concat(url_path_join(self.base_url, 'spawn'),
|
||||||
|
{'next': self.request.uri})
|
||||||
html = self.render_template('home.html',
|
html = self.render_template('home.html',
|
||||||
user=user,
|
user=user,
|
||||||
|
url=url,
|
||||||
)
|
)
|
||||||
self.finish(html)
|
self.finish(html)
|
||||||
|
|
||||||
@@ -85,6 +91,7 @@ class SpawnHandler(BaseHandler):
|
|||||||
user=user,
|
user=user,
|
||||||
spawner_options_form=user.spawner.options_form,
|
spawner_options_form=user.spawner.options_form,
|
||||||
error_message=message,
|
error_message=message,
|
||||||
|
url=self.request.uri,
|
||||||
)
|
)
|
||||||
|
|
||||||
@web.authenticated
|
@web.authenticated
|
||||||
@@ -126,6 +133,13 @@ class SpawnHandler(BaseHandler):
|
|||||||
return
|
return
|
||||||
self.set_login_cookie(user)
|
self.set_login_cookie(user)
|
||||||
url = user.url
|
url = user.url
|
||||||
|
|
||||||
|
next_url = self.get_argument('next', '')
|
||||||
|
if next_url and not next_url.startswith('/'):
|
||||||
|
self.log.warning("Disallowing redirect outside JupyterHub: %r", next_url)
|
||||||
|
elif next_url:
|
||||||
|
url = next_url
|
||||||
|
|
||||||
self.redirect(url)
|
self.redirect(url)
|
||||||
|
|
||||||
class AdminHandler(BaseHandler):
|
class AdminHandler(BaseHandler):
|
||||||
|
@@ -114,6 +114,10 @@ def test_spawn_page(app):
|
|||||||
assert r.url.endswith('/spawn')
|
assert r.url.endswith('/spawn')
|
||||||
assert FormSpawner.options_form in r.text
|
assert FormSpawner.options_form in r.text
|
||||||
|
|
||||||
|
r = get_page('spawn?next=foo', app, cookies=cookies)
|
||||||
|
assert r.url.endswith('/spawn?next=foo')
|
||||||
|
assert FormSpawner.options_form in r.text
|
||||||
|
|
||||||
def test_spawn_form(app, io_loop):
|
def test_spawn_form(app, io_loop):
|
||||||
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
|
with mock.patch.dict(app.users.settings, {'spawner_class': FormSpawner}):
|
||||||
base_url = ujoin(public_host(app), app.hub.server.base_url)
|
base_url = ujoin(public_host(app), app.hub.server.base_url)
|
||||||
@@ -122,11 +126,12 @@ def test_spawn_form(app, io_loop):
|
|||||||
u = app.users[orm_u]
|
u = app.users[orm_u]
|
||||||
io_loop.run_sync(u.stop)
|
io_loop.run_sync(u.stop)
|
||||||
|
|
||||||
r = requests.post(ujoin(base_url, 'spawn'), cookies=cookies, data={
|
r = requests.post(ujoin(base_url, 'spawn?next=/user/jones/tree'), cookies=cookies, data={
|
||||||
'bounds': ['-1', '1'],
|
'bounds': ['-1', '1'],
|
||||||
'energy': '511keV',
|
'energy': '511keV',
|
||||||
})
|
})
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
assert r.history
|
||||||
print(u.spawner)
|
print(u.spawner)
|
||||||
print(u.spawner.user_options)
|
print(u.spawner.user_options)
|
||||||
assert u.spawner.user_options == {
|
assert u.spawner.user_options == {
|
||||||
|
@@ -8,13 +8,7 @@
|
|||||||
{% if user.running %}
|
{% if user.running %}
|
||||||
<a id="stop" class="btn btn-lg btn-danger">Stop My Server</a>
|
<a id="stop" class="btn btn-lg btn-danger">Stop My Server</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a id="start" class="btn btn-lg btn-success"
|
<a id="start" class="btn btn-lg btn-success" href="{{ url }}">
|
||||||
{% if user.running %}
|
|
||||||
href="{{ user.url }}"
|
|
||||||
{% else %}
|
|
||||||
href="{{base_url}}spawn"
|
|
||||||
{% endif %}
|
|
||||||
>
|
|
||||||
{% if not user.running %}
|
{% if not user.running %}
|
||||||
Start
|
Start
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
Error: {{error_message}}
|
Error: {{error_message}}
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form enctype="multipart/form-data" id="spawn_form" action="{{base_url}}spawn" method="post" role="form">
|
<form enctype="multipart/form-data" id="spawn_form" action="{{url}}" method="post" role="form">
|
||||||
{{spawner_options_form | safe}}
|
{{spawner_options_form | safe}}
|
||||||
<br>
|
<br>
|
||||||
<input type="submit" value="Spawn" class="btn btn-jupyter">
|
<input type="submit" value="Spawn" class="btn btn-jupyter">
|
||||||
|
Reference in New Issue
Block a user