diff --git a/IPython/frontend/html/notebook/handlers.py b/IPython/frontend/html/notebook/handlers.py index 304f05c..05a06ac 100644 --- a/IPython/frontend/html/notebook/handlers.py +++ b/IPython/frontend/html/notebook/handlers.py @@ -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, diff --git a/IPython/frontend/html/notebook/notebookapp.py b/IPython/frontend/html/notebook/notebookapp.py index 21252d8..4adf60e 100644 --- a/IPython/frontend/html/notebook/notebookapp.py +++ b/IPython/frontend/html/notebook/notebookapp.py @@ -85,12 +85,23 @@ 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) diff --git a/IPython/frontend/html/notebook/static/js/savewidget.js b/IPython/frontend/html/notebook/static/js/savewidget.js index e93493f..ad1f5f3 100644 --- a/IPython/frontend/html/notebook/static/js/savewidget.js +++ b/IPython/frontend/html/notebook/static/js/savewidget.js @@ -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); }; }; diff --git a/IPython/frontend/html/notebook/templates/layout.html b/IPython/frontend/html/notebook/templates/layout.html index 735c110..700a706 100644 --- a/IPython/frontend/html/notebook/templates/layout.html +++ b/IPython/frontend/html/notebook/templates/layout.html @@ -6,10 +6,10 @@