mirror of
https://github.com/jupyter/notebook.git
synced 2025-01-12 11:45:38 +08:00
4a3386663c
* Improve some docstrings too * Fix a busted extension link along the way (c) Copyright IBM Corp. 2016
128 lines
4.7 KiB
ReStructuredText
128 lines
4.7 KiB
ReStructuredText
Custom request handlers
|
|
=======================
|
|
|
|
The notebook webserver can be interacted with using a well `defined
|
|
RESTful
|
|
API <http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml>`__.
|
|
You can define custom RESTful API handlers in addition to the ones
|
|
provided by the notebook. As described below, to define a custom handler
|
|
you need to first write a notebook server extension. Then, in the
|
|
extension, you can register the custom handler.
|
|
|
|
Writing a notebook server extension
|
|
-----------------------------------
|
|
|
|
The notebook webserver is written in Python, hence your server extension
|
|
should be written in Python too. Server extensions, like IPython
|
|
extensions, are Python modules that define a specially named load
|
|
function, ``load_jupyter_server_extension``. This function is called
|
|
when the extension is loaded.
|
|
|
|
.. code:: python
|
|
|
|
def load_jupyter_server_extension(nb_server_app):
|
|
"""
|
|
Called when the extension is loaded.
|
|
|
|
Args:
|
|
nb_server_app (NotebookWebApplication): handle to the Notebook webserver instance.
|
|
"""
|
|
pass
|
|
|
|
To get the notebook server to load your custom extension, you'll need to
|
|
add it to the list of extensions to be loaded. You can do this using the
|
|
config system. ``NotebookApp.server_extensions`` is a config variable
|
|
which is an array of strings, each a Python module to be imported.
|
|
Because this variable is notebook config, you can set it two different
|
|
ways, using config files or via the command line.
|
|
|
|
For example, to get your extension to load via the command line add a
|
|
double dash before the variable name, and put the Python array in
|
|
double quotes. If your package is "mypackage" and module is
|
|
"mymodule", this would look like
|
|
``jupyter notebook --NotebookApp.server_extensions="['mypackage.mymodule']"``
|
|
.
|
|
Basically the string should be Python importable.
|
|
|
|
Alternatively, you can have your extension loaded regardless of the
|
|
command line args by setting the variable in the Jupyter config file.
|
|
The default location of the Jupyter config file is
|
|
``~/.jupyter/profile_default/jupyter_notebook_config.py``. Then, inside
|
|
the config file, you can use Python to set the variable. For example,
|
|
the following config does the same as the previous command line example
|
|
[1].
|
|
|
|
.. code:: python
|
|
|
|
c = get_config()
|
|
c.NotebookApp.server_extensions = [
|
|
'mypackage.mymodule'
|
|
]
|
|
|
|
Before continuing, it's a good idea to verify that your extension is
|
|
being loaded. Use a print statement to print something unique. Launch
|
|
the notebook server and you should see your statement printed to the
|
|
console.
|
|
|
|
Registering custom handlers
|
|
---------------------------
|
|
|
|
Once you've defined a server extension, you can register custom handlers
|
|
because you have a handle to the Notebook server app instance
|
|
(``nb_server_app`` above). However, you first need to define your custom
|
|
handler. To declare a custom handler, inherit from
|
|
``notebook.base.handlers.IPythonHandler``. The example below[1] is a
|
|
Hello World handler:
|
|
|
|
.. code:: python
|
|
|
|
from notebook.base.handlers import IPythonHandler
|
|
|
|
class HelloWorldHandler(IPythonHandler):
|
|
def get(self):
|
|
self.finish('Hello, world!')
|
|
|
|
The Jupyter Notebook server use
|
|
`Tornado <http://www.tornadoweb.org/en/stable/>`__ as its web framework.
|
|
For more information on how to implement request handlers, refer to the
|
|
`Tornado documentation on the
|
|
matter <http://www.tornadoweb.org/en/stable/web.html#request-handlers>`__.
|
|
|
|
After defining the handler, you need to register the handler with the
|
|
Notebook server. See the following example:
|
|
|
|
.. code:: python
|
|
|
|
web_app = nb_server_app.web_app
|
|
host_pattern = '.*$'
|
|
route_pattern = url_path_join(web_app.settings['base_url'], '/hello')
|
|
web_app.add_handlers(host_pattern, [(route_pattern, HelloWorldHandler)])
|
|
|
|
Putting this together with the extension code, the example looks like the
|
|
following:
|
|
|
|
.. code:: python
|
|
|
|
from notebook.utils import url_path_join
|
|
from notebook.base.handlers import IPythonHandler
|
|
|
|
class HelloWorldHandler(IPythonHandler):
|
|
def get(self):
|
|
self.finish('Hello, world!')
|
|
|
|
def load_jupyter_server_extension(nb_server_app):
|
|
"""
|
|
Called when the extension is loaded.
|
|
|
|
Args:
|
|
nb_server_app (NotebookWebApplication): handle to the Notebook webserver instance.
|
|
"""
|
|
web_app = nb_server_app.web_app
|
|
host_pattern = '.*$'
|
|
route_pattern = url_path_join(web_app.settings['base_url'], '/hello')
|
|
web_app.add_handlers(host_pattern, [(route_pattern, HelloWorldHandler)])
|
|
|
|
References:
|
|
1. `Peter Parente's
|
|
Mindtrove <http://mindtrove.info/4-ways-to-extend-jupyter-notebook/#nb-server-exts>`__
|