Merge pull request #1332 from astraw/alternate-url-prefix

notebook - allow prefixes in URL path.

This closes #1329. The basic idea is to allow prefixes in the path served. (E.g. serve on http://localhost:8888/ipython/ instead of http://localhost:8888/ )

This is useful for running the ipython notebook behind a proxy serving other content at other URLs. In that case, one would also need to proxy the websockets.

Also, clean up some static paths in our html/css files by using template function calls instead of hardcoded paths.
Fernando Perez 14 years ago
commit d2467be28b

@ -168,12 +168,15 @@ class AuthenticatedHandler(RequestHandler):
@property
def ws_url(self):
"""websocket url matching the current request
turns http[s]://host[:port] into
ws[s]://host[:port]
"""
proto = self.request.protocol.replace('http', 'ws')
return "%s://%s" % (proto, self.request.host)
host = self.application.ipython_app.websocket_host # default to config value
if host == '':
host = self.request.host # get from request
return "%s://%s" % (proto, host)
class AuthenticatedFileHandler(AuthenticatedHandler, web.StaticFileHandler):
@ -192,7 +195,8 @@ class ProjectDashboardHandler(AuthenticatedHandler):
project = nbm.notebook_dir
self.render(
'projectdashboard.html', project=project,
base_project_url=u'/', base_kernel_url=u'/',
base_project_url=self.application.ipython_app.base_project_url,
base_kernel_url=self.application.ipython_app.base_kernel_url,
read_only=self.read_only,
logged_in=self.logged_in,
login_available=self.login_available
@ -255,7 +259,8 @@ class NewHandler(AuthenticatedHandler):
self.render(
'notebook.html', project=project,
notebook_id=notebook_id,
base_project_url=u'/', base_kernel_url=u'/',
base_project_url=self.application.ipython_app.base_project_url,
base_kernel_url=self.application.ipython_app.base_kernel_url,
kill_kernel=False,
read_only=False,
logged_in=self.logged_in,
@ -276,7 +281,8 @@ class NamedNotebookHandler(AuthenticatedHandler):
self.render(
'notebook.html', project=project,
notebook_id=notebook_id,
base_project_url=u'/', base_kernel_url=u'/',
base_project_url=self.application.ipython_app.base_project_url,
base_kernel_url=self.application.ipython_app.base_kernel_url,
kill_kernel=False,
read_only=self.read_only,
logged_in=self.logged_in,
@ -297,7 +303,8 @@ class PrintNotebookHandler(AuthenticatedHandler):
self.render(
'printnotebook.html', project=project,
notebook_id=notebook_id,
base_project_url=u'/', base_kernel_url=u'/',
base_project_url=self.application.ipython_app.base_project_url,
base_kernel_url=self.application.ipython_app.base_kernel_url,
kill_kernel=False,
read_only=self.read_only,
logged_in=self.logged_in,
@ -637,7 +644,8 @@ class NotebookCopyHandler(AuthenticatedHandler):
self.render(
'notebook.html', project=project,
notebook_id=notebook_id,
base_project_url=u'/', base_kernel_url=u'/',
base_project_url=self.application.ipython_app.base_project_url,
base_kernel_url=self.application.ipython_app.base_kernel_url,
kill_kernel=False,
read_only=False,
logged_in=self.logged_in,

@ -84,13 +84,24 @@ ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
ipython notebook --port=5555 --ip=* # Listen on port 5555, all interfaces
"""
#-----------------------------------------------------------------------------
# Helper functions
#-----------------------------------------------------------------------------
def url_path_join(a,b):
if a.endswith('/') and b.startswith('/'):
return a[:-1]+b
else:
return a+b
#-----------------------------------------------------------------------------
# The Tornado web application
#-----------------------------------------------------------------------------
class NotebookWebApplication(web.Application):
def __init__(self, ipython_app, kernel_manager, notebook_manager, log, settings_overrides):
def __init__(self, ipython_app, kernel_manager, notebook_manager, log,
base_project_url, settings_overrides):
handlers = [
(r"/", ProjectDashboardHandler),
(r"/login", LoginHandler),
@ -119,7 +130,14 @@ class NotebookWebApplication(web.Application):
# allow custom overrides for the tornado web app.
settings.update(settings_overrides)
super(NotebookWebApplication, self).__init__(handlers, **settings)
# prepend base_project_url onto the patterns that we match
new_handlers = []
for handler in handlers:
pattern = url_path_join(base_project_url, handler[0])
new_handler = tuple([pattern]+list(handler[1:]))
new_handlers.append( new_handler )
super(NotebookWebApplication, self).__init__(new_handlers, **settings)
self.kernel_manager = kernel_manager
self.log = log
@ -277,7 +295,15 @@ class NotebookApp(BaseIPythonApplication):
"""set mathjax url to empty if mathjax is disabled"""
if not new:
self.mathjax_url = u''
base_project_url = Unicode('/', config=True,
help='''The base URL for the notebook server''')
base_kernel_url = Unicode('/', config=True,
help='''The base URL for the kernel server''')
websocket_host = Unicode("", config=True,
help="""The hostname for the websocket server."""
)
mathjax_url = Unicode("", config=True,
help="""The url for MathJax.js."""
)
@ -285,9 +311,11 @@ class NotebookApp(BaseIPythonApplication):
if not self.enable_mathjax:
return u''
static_path = self.webapp_settings.get("static_path", os.path.join(os.path.dirname(__file__), "static"))
static_url_prefix = self.webapp_settings.get("static_url_prefix",
"/static/")
if os.path.exists(os.path.join(static_path, 'mathjax', "MathJax.js")):
self.log.info("Using local MathJax")
return u"/static/mathjax/MathJax.js"
return static_url_prefix+u"mathjax/MathJax.js"
else:
self.log.info("Using MathJax from CDN")
return u"http://cdn.mathjax.org/mathjax/latest/MathJax.js"
@ -331,7 +359,7 @@ class NotebookApp(BaseIPythonApplication):
"""initialize tornado webapp and httpserver"""
self.web_app = NotebookWebApplication(
self, self.kernel_manager, self.notebook_manager, self.log,
self.webapp_settings
self.base_project_url, self.webapp_settings
)
if self.certfile:
ssl_options = dict(certfile=self.certfile)

@ -124,7 +124,7 @@ var IPython = (function (IPython) {
SaveWidget.prototype.update_url = function () {
var notebook_id = this.get_notebook_id();
if (notebook_id !== '') {
var new_url = '/'+notebook_id;
var new_url = $('body').data('baseProjectUrl') + notebook_id;
window.history.replaceState({}, '', new_url);
};
};

@ -6,10 +6,10 @@
<title>{% block title %}IPython Notebook{% end %}</title>
<link rel="stylesheet" href="/static/jquery/css/themes/base/jquery-ui.min.css" type="text/css" />
<link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" />
<link rel="stylesheet" href="/static/css/layout.css" type="text/css" />
<link rel="stylesheet" href="/static/css/base.css" type="text/css"/>
<link rel="stylesheet" href="{{static_url("jquery/css/themes/base/jquery-ui.min.css") }}" type="text/css" />
<link rel="stylesheet" href="{{static_url("css/boilerplate.css") }}" type="text/css" />
<link rel="stylesheet" href="{{static_url("css/layout.css") }}" type="text/css" />
<link rel="stylesheet" href="{{static_url("css/base.css") }}" type="text/css"/>
{% block stylesheet %}
{% end %}
@ -21,7 +21,7 @@
<body {% block params %}{% end %}>
<div id="header">
<span id="ipython_notebook"><h1><img src='/static/ipynblogo.png' alt='IPython Notebook'/></h1></span>
<span id="ipython_notebook"><h1><img src='{{static_url("ipynblogo.png") }}' alt='IPython Notebook'/></h1></span>
{% block login_widget %}
@ -72,11 +72,11 @@
</div>
<script src="/static/jquery/js/jquery-1.7.1.min.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/jquery/js/jquery-ui.min.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/loginmain.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("jquery/js/jquery-1.7.1.min.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("jquery/js/jquery-ui.min.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("js/loginmain.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("js/loginwidget.js") }}" type="text/javascript" charset="utf-8"></script>
{% block script %}
{% end %}

@ -15,17 +15,17 @@
window.mathjax_url = "{{mathjax_url}}";
</script>
<link rel="stylesheet" href="/static/jquery/css/themes/base/jquery-ui.min.css" type="text/css" />
<link rel="stylesheet" href="/static/codemirror/lib/codemirror.css">
<link rel="stylesheet" href="/static/codemirror/theme/ipython.css">
<link rel="stylesheet" href="{{ static_url("jquery/css/themes/base/jquery-ui.min.css") }}" type="text/css" />
<link rel="stylesheet" href="{{ static_url("codemirror/lib/codemirror.css") }}">
<link rel="stylesheet" href="{{ static_url("codemirror/theme/ipython.css") }}">
<link rel="stylesheet" href="/static/prettify/prettify.css"/>
<link rel="stylesheet" href="{{ static_url("prettify/prettify.css") }}"/>
<link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" />
<link rel="stylesheet" href="/static/css/layout.css" type="text/css" />
<link rel="stylesheet" href="/static/css/base.css" type="text/css" />
<link rel="stylesheet" href="/static/css/notebook.css" type="text/css" />
<link rel="stylesheet" href="/static/css/renderedhtml.css" type="text/css" />
<link rel="stylesheet" href="{{ static_url("css/boilerplate.css") }}" type="text/css" />
<link rel="stylesheet" href="{{ static_url("css/layout.css") }}" type="text/css" />
<link rel="stylesheet" href="{{ static_url("css/base.css") }}" type="text/css" />
<link rel="stylesheet" href="{{ static_url("css/notebook.css") }}" type="text/css" />
<link rel="stylesheet" href="{{ static_url("css/renderedhtml.css") }}" type="text/css" />
{% comment In the notebook, the read-only flag is used to determine %}
{% comment whether to hide the side panels and switch off input %}
@ -39,7 +39,7 @@
>
<div id="header">
<span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='/static/ipynblogo.png' alt='IPython Notebook'/></a></h1></span>
<span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='{{static_url("ipynblogo.png")}}' alt='IPython Notebook'/></a></h1></span>
<span id="save_widget">
<span id="notebook_name"></span>
<span id="save_status"></span>
@ -188,39 +188,39 @@
</div>
<script src="/static/jquery/js/jquery-1.7.1.min.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/jquery/js/jquery-ui.min.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/codemirror/lib/codemirror.js" charset="utf-8"></script>
<script src="/static/codemirror/mode/python/python.js" charset="utf-8"></script>
<script src="/static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script>
<script src="/static/codemirror/mode/xml/xml.js" charset="utf-8"></script>
<script src="/static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script>
<script src="/static/codemirror/mode/css/css.js" charset="utf-8"></script>
<script src="/static/codemirror/mode/rst/rst.js" charset="utf-8"></script>
<script src="/static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script>
<script src="/static/pagedown/Markdown.Converter.js" charset="utf-8"></script>
<script src="/static/prettify/prettify.js" charset="utf-8"></script>
<script src="/static/dateformat/date.format.js" charset="utf-8"></script>
<script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/utils.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/cell.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/codecell.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/textcell.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/kernel.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/layout.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/savewidget.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/quickhelp.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/pager.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/menubar.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/toolbar.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/notebook.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("jquery/js/jquery-1.7.1.min.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("jquery/js/jquery-ui.min.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("codemirror/lib/codemirror.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/python/python.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/htmlmixed/htmlmixed.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/xml/xml.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/javascript/javascript.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/css/css.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/rst/rst.js") }}" charset="utf-8"></script>
<script src="{{ static_url("codemirror/mode/markdown/markdown.js") }}" charset="utf-8"></script>
<script src="{{ static_url("pagedown/Markdown.Converter.js") }}" charset="utf-8"></script>
<script src="{{ static_url("prettify/prettify.js") }}" charset="utf-8"></script>
<script src="{{ static_url("dateformat/date.format.js") }}" charset="utf-8"></script>
<script src="{{ static_url("js/namespace.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/utils.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/cell.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/codecell.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/textcell.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/kernel.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/kernelstatus.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/layout.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/savewidget.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/quickhelp.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/loginwidget.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/pager.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/menubar.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/toolbar.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/notebook.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{ static_url("js/notebookmain.js") }}" type="text/javascript" charset="utf-8"></script>
</body>

@ -5,7 +5,7 @@ IPython Dashboard
{% end %}
{% block stylesheet %}
<link rel="stylesheet" href="/static/css/projectdashboard.css" type="text/css" />
<link rel="stylesheet" href="{{static_url("css/projectdashboard.css") }}" type="text/css" />
{% end %}
{% block meta %}
@ -38,6 +38,6 @@ data-base-kernel-url={{base_kernel_url}}
{% end %}
{% block script %}
<script src="/static/js/notebooklist.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/js/projectdashboardmain.js" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("js/notebooklist.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("js/projectdashboardmain.js") }}" type="text/javascript" charset="utf-8"></script>
{% end %}

Loading…
Cancel
Save