mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-15 22:13:00 +00:00
include protocol in subdomain_host
makes everything easier, and tests are passing with and without subdomains (yay!)
This commit is contained in:
@@ -15,3 +15,7 @@ script:
|
|||||||
- py.test --cov jupyterhub jupyterhub/tests -v
|
- py.test --cov jupyterhub jupyterhub/tests -v
|
||||||
after_success:
|
after_success:
|
||||||
- codecov
|
- codecov
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- python: 3.5
|
||||||
|
env: JUPYTERHUB_TEST_SUBDOMAIN_HOST=http://127.0.0.1.xip.io:8000
|
||||||
|
@@ -16,6 +16,7 @@ from datetime import datetime
|
|||||||
from distutils.version import LooseVersion as V
|
from distutils.version import LooseVersion as V
|
||||||
from getpass import getuser
|
from getpass import getuser
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
if sys.version_info[:2] < (3,3):
|
if sys.version_info[:2] < (3,3):
|
||||||
raise ValueError("Python < 3.3 not supported: %s" % sys.version)
|
raise ValueError("Python < 3.3 not supported: %s" % sys.version)
|
||||||
@@ -239,6 +240,11 @@ class JupyterHub(Application):
|
|||||||
Only used when subdomains are involved.
|
Only used when subdomains are involved.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
def _subdomain_host_changed(self, name, old, new):
|
||||||
|
if new and '://' not in new:
|
||||||
|
# host should include '://'
|
||||||
|
# if not specified, assume https: You have to be really explicit about HTTP!
|
||||||
|
self.subdomain_host = 'https://' + new
|
||||||
|
|
||||||
port = Integer(8000, config=True,
|
port = Integer(8000, config=True,
|
||||||
help="The public facing port of the proxy"
|
help="The public facing port of the proxy"
|
||||||
@@ -923,7 +929,7 @@ class JupyterHub(Application):
|
|||||||
version_hash=datetime.now().strftime("%Y%m%d%H%M%S"),
|
version_hash=datetime.now().strftime("%Y%m%d%H%M%S"),
|
||||||
|
|
||||||
subdomain_host = self.subdomain_host
|
subdomain_host = self.subdomain_host
|
||||||
domain = subdomain_host.rsplit(':', 1)[0]
|
domain = urlparse(subdomain_host).hostname
|
||||||
settings = dict(
|
settings = dict(
|
||||||
log_function=log_request,
|
log_function=log_request,
|
||||||
config=self.config,
|
config=self.config,
|
||||||
|
@@ -476,7 +476,7 @@ class UserSpawnHandler(BaseHandler):
|
|||||||
without_prefix = self.request.uri[len(self.hub.server.base_url):]
|
without_prefix = self.request.uri[len(self.hub.server.base_url):]
|
||||||
target = url_path_join(self.base_url, without_prefix)
|
target = url_path_join(self.base_url, without_prefix)
|
||||||
if self.use_subdomains:
|
if self.use_subdomains:
|
||||||
target = '//' + current_user.host + target
|
target = current_user.host + target
|
||||||
self.redirect(target)
|
self.redirect(target)
|
||||||
else:
|
else:
|
||||||
# not logged in to the right user,
|
# not logged in to the right user,
|
||||||
|
@@ -199,7 +199,7 @@ class Spawner(LoggingConfigurable):
|
|||||||
'--port=%i' % self.user.server.port,
|
'--port=%i' % self.user.server.port,
|
||||||
'--cookie-name=%s' % self.user.server.cookie_name,
|
'--cookie-name=%s' % self.user.server.cookie_name,
|
||||||
'--base-url=%s' % self.user.server.base_url,
|
'--base-url=%s' % self.user.server.base_url,
|
||||||
'--hub-host=%s' % ('//' + self.hub.host) if self.hub.host else '',
|
'--hub-host=%s' % self.hub.host,
|
||||||
'--hub-prefix=%s' % self.hub.server.base_url,
|
'--hub-prefix=%s' % self.hub.server.base_url,
|
||||||
'--hub-api-url=%s' % self.hub.api_url,
|
'--hub-api-url=%s' % self.hub.api_url,
|
||||||
]
|
]
|
||||||
|
@@ -168,10 +168,7 @@ class MockHub(JupyterHub):
|
|||||||
self.db_file.close()
|
self.db_file.close()
|
||||||
|
|
||||||
def login_user(self, name):
|
def login_user(self, name):
|
||||||
if self.subdomain_host:
|
base_url = public_url(self)
|
||||||
base_url = 'http://' + self.subdomain_host + self.proxy.public_server.base_url
|
|
||||||
else:
|
|
||||||
base_url = self.proxy.public_server.url
|
|
||||||
r = requests.post(base_url + 'hub/login',
|
r = requests.post(base_url + 'hub/login',
|
||||||
data={
|
data={
|
||||||
'username': name,
|
'username': name,
|
||||||
@@ -191,13 +188,12 @@ def public_host(app):
|
|||||||
|
|
||||||
|
|
||||||
def public_url(app):
|
def public_url(app):
|
||||||
return 'http://%s%s' % (public_host(app), app.proxy.public_server.base_url)
|
return public_host(app) + app.proxy.public_server.base_url
|
||||||
|
|
||||||
|
|
||||||
def user_url(user, app):
|
def user_url(user, app):
|
||||||
print(user.host)
|
|
||||||
if app.use_subdomains:
|
if app.use_subdomains:
|
||||||
host = user.host
|
host = user.host
|
||||||
else:
|
else:
|
||||||
host = public_host(app)
|
host = public_host(app)
|
||||||
return url_path_join('http://%s' % host, user.server.base_url)
|
return host + user.server.base_url
|
||||||
|
@@ -364,7 +364,7 @@ def test_spawn(app, io_loop):
|
|||||||
for expected in ['--user=%s' % name, '--base-url=%s' % user.server.base_url]:
|
for expected in ['--user=%s' % name, '--base-url=%s' % user.server.base_url]:
|
||||||
assert expected in argv
|
assert expected in argv
|
||||||
if app.use_subdomains:
|
if app.use_subdomains:
|
||||||
assert '--hub-host=//%s' % app.subdomain_host in argv
|
assert '--hub-host=%s' % app.subdomain_host in argv
|
||||||
|
|
||||||
r = api_request(app, 'users', name, 'server', method='delete')
|
r = api_request(app, 'users', name, 'server', method='delete')
|
||||||
assert r.status_code == 204
|
assert r.status_code == 204
|
||||||
|
@@ -22,6 +22,7 @@ def test_root_no_auth(app, io_loop):
|
|||||||
print(routes)
|
print(routes)
|
||||||
print(app.hub.server)
|
print(app.hub.server)
|
||||||
url = public_url(app)
|
url = public_url(app)
|
||||||
|
print(url)
|
||||||
r = requests.get(url)
|
r = requests.get(url)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
assert r.url == ujoin(url, app.hub.server.base_url, 'login')
|
assert r.url == ujoin(url, app.hub.server.base_url, 'login')
|
||||||
|
@@ -4,6 +4,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from .. import orm
|
from .. import orm
|
||||||
from .mocking import MockHub
|
from .mocking import MockHub
|
||||||
@@ -64,7 +65,7 @@ def test_external_proxy(request, io_loop):
|
|||||||
routes = io_loop.run_sync(app.proxy.get_routes)
|
routes = io_loop.run_sync(app.proxy.get_routes)
|
||||||
user_path = '/user/river'
|
user_path = '/user/river'
|
||||||
if app.use_subdomains:
|
if app.use_subdomains:
|
||||||
domain = app.subdomain_host.rsplit(':', 1)[0]
|
domain = urlparse(app.subdomain_host).hostname
|
||||||
user_path = '/%s.%s' % (name, domain) + user_path
|
user_path = '/%s.%s' % (name, domain) + user_path
|
||||||
assert sorted(routes.keys()) == ['/', user_path]
|
assert sorted(routes.keys()) == ['/', user_path]
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
# Distributed under the terms of the Modified BSD License.
|
# Distributed under the terms of the Modified BSD License.
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote, urlparse
|
||||||
|
|
||||||
from tornado import gen
|
from tornado import gen
|
||||||
from tornado.log import app_log
|
from tornado.log import app_log
|
||||||
@@ -171,7 +171,9 @@ class User(HasTraits):
|
|||||||
def host(self):
|
def host(self):
|
||||||
"""Get the *host* for my server (domain[:port])"""
|
"""Get the *host* for my server (domain[:port])"""
|
||||||
# FIXME: escaped_name probably isn't escaped enough in general for a domain fragment
|
# FIXME: escaped_name probably isn't escaped enough in general for a domain fragment
|
||||||
return self.escaped_name + '.' + self.settings['subdomain_host']
|
parsed = urlparse(self.settings['subdomain_host'])
|
||||||
|
h = '%s://%s.%s' % (parsed.scheme, self.escaped_name, parsed.netloc)
|
||||||
|
return h
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
@@ -180,7 +182,7 @@ class User(HasTraits):
|
|||||||
Full name.domain/path if using subdomains, otherwise just my /base/url
|
Full name.domain/path if using subdomains, otherwise just my /base/url
|
||||||
"""
|
"""
|
||||||
if self.settings.get('use_subdomains'):
|
if self.settings.get('use_subdomains'):
|
||||||
return '//{host}{path}'.format(
|
return '{host}{path}'.format(
|
||||||
host=self.host,
|
host=self.host,
|
||||||
path=self.server.base_url,
|
path=self.server.base_url,
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user