Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Launch the browser with a redirect file #4260

Merged
merged 4 commits into from
Dec 13, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 76 additions & 25 deletions notebook/notebookapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import signal
import socket
import sys
import tempfile
import threading
import time
import warnings
Expand Down Expand Up @@ -107,7 +108,7 @@
from notebook._sysinfo import get_sys_info

from ._tz import utcnow, utcfromtimestamp
from .utils import url_path_join, check_pid, url_escape
from .utils import url_path_join, check_pid, url_escape, urljoin, pathname2url

#-----------------------------------------------------------------------------
# Module globals
Expand Down Expand Up @@ -1184,6 +1185,13 @@ def _update_mathjax_config(self, change):
def _default_info_file(self):
info_file = "nbserver-%s.json" % os.getpid()
return os.path.join(self.runtime_dir, info_file)

browser_open_file = Unicode()

@default('browser_open_file')
def _default_browser_open_file(self):
basename = "nbserver-%s-open.html" % os.getpid()
return os.path.join(self.runtime_dir, basename)

pylab = Unicode('disabled', config=True,
help=_("""
Expand Down Expand Up @@ -1697,6 +1705,67 @@ def remove_server_info_file(self):
if e.errno != errno.ENOENT:
raise

def write_browser_open_file(self):
"""Write an nbserver-<pid>-open.html file

This can be used to open the notebook in a browser
"""
# default_url contains base_url, but so does connection_url
open_url = self.default_url[len(self.base_url):]

with open(self.browser_open_file, 'w', encoding='utf-8') as f:
self._write_browser_open_file(open_url, f)

def _write_browser_open_file(self, url, fh):
if self.token:
url = url_concat(url, {'token': self.token})
minrk marked this conversation as resolved.
Show resolved Hide resolved
url = url_path_join(self.connection_url, url)

jinja2_env = self.web_app.settings['jinja2_env']
template = jinja2_env.get_template('browser-open.html')
fh.write(template.render(open_url=url))

def remove_browser_open_file(self):
"""Remove the nbserver-<pid>-open.html file created for this server.

Ignores the error raised when the file has already been removed.
"""
try:
os.unlink(self.browser_open_file)
except OSError as e:
if e.errno != errno.ENOENT:
raise

def launch_browser(self):
try:
browser = webbrowser.get(self.browser or None)
except webbrowser.Error as e:
self.log.warning(_('No web browser found: %s.') % e)
browser = None

if not browser:
return

if self.file_to_run:
if not os.path.exists(self.file_to_run):
self.log.critical(_("%s does not exist") % self.file_to_run)
self.exit(1)

relpath = os.path.relpath(self.file_to_run, self.notebook_dir)
uri = url_escape(url_path_join('notebooks', *relpath.split(os.sep)))

# Write a temporary file to open in the browser
fd, open_file = tempfile.mkstemp(suffix='.html')
with open(fd, 'w', encoding='utf-8') as fh:
self._write_browser_open_file(uri, fh)
else:
open_file = self.browser_open_file

b = lambda: browser.open(
urljoin('file:', pathname2url(open_file)),
new=self.webbrowser_open_new)
threading.Thread(target=b).start()

def start(self):
""" Start the Notebook server app, after initialization

Expand Down Expand Up @@ -1726,38 +1795,19 @@ def start(self):
"resources section at https://jupyter.org/community.html."))

self.write_server_info_file()
self.write_browser_open_file()

if self.open_browser or self.file_to_run:
try:
browser = webbrowser.get(self.browser or None)
except webbrowser.Error as e:
self.log.warning(_('No web browser found: %s.') % e)
browser = None

if self.file_to_run:
if not os.path.exists(self.file_to_run):
self.log.critical(_("%s does not exist") % self.file_to_run)
self.exit(1)

relpath = os.path.relpath(self.file_to_run, self.notebook_dir)
uri = url_escape(url_path_join('notebooks', *relpath.split(os.sep)))
else:
# default_url contains base_url, but so does connection_url
uri = self.default_url[len(self.base_url):]
if self.one_time_token:
uri = url_concat(uri, {'token': self.one_time_token})
if browser:
b = lambda : browser.open(url_path_join(self.connection_url, uri),
new=self.webbrowser_open_new)
threading.Thread(target=b).start()
self.launch_browser()

if self.token and self._token_generated:
# log full URL with generated token, so there's a copy/pasteable link
# with auth info.
self.log.critical('\n'.join([
'\n',
'Copy/paste this URL into your browser when you connect for the first time,',
'to login with a token:',
'To access the notebook, open this file in a browser:',
' %s' % urljoin('file:', pathname2url(self.browser_open_file)),
'Or copy and paste one of these URLs:',
' %s' % self.display_url,
]))

Expand All @@ -1773,6 +1823,7 @@ def start(self):
info(_("Interrupted..."))
finally:
self.remove_server_info_file()
self.remove_browser_open_file()
self.cleanup_kernels()

def stop(self):
Expand Down
18 changes: 18 additions & 0 deletions notebook/templates/browser-open.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{# This template is not served, but written as a file to open in the browser,
passing the token without putting it in a command-line argument. #}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="1;url={{ open_url }}" />
<title>Opening Jupyter Notebook</title>
</head>
<body>

<p>
This page should redirect you to Jupyter Notebook. If it doesn't,
<a href="{{ open_url }}">click here to go to Jupyter</a>.
</p>

</body>
</html>
7 changes: 4 additions & 3 deletions notebook/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
from distutils.version import LooseVersion

try:
from urllib.parse import quote, unquote, urlparse
from urllib.parse import quote, unquote, urlparse, urljoin
from urllib.request import pathname2url
except ImportError:
from urllib import quote, unquote
from urlparse import urlparse
from urllib import quote, unquote, pathname2url
from urlparse import urlparse, urljoin

from ipython_genutils import py3compat

Expand Down