This project is deprecated and no longer maintained. Please see, our main repository, stencila/stencila, for other projects that provide similar or alternative functionality.
Bindilla acts as a bridge between Stencila interfaces and execution contexts hosted by Binder. Using this bridge, clients such as Stencila Desktop or eLife RDS Reader can launch, and interact with, alternative execution envionments provided by Binder.
Binder supports launching a Git repository containing a Dar archive directly. But what if you want to have the content of a reproducible article served from somewhere else and only use Binder for code execution?
Stencila clients talk to execution contexts using an API. This API is implemented by several packages including stencila/py, stencila/r, and stencila/node. These packages are available within a Binder container via nbstencilaproxy. You can embed a reproducible document into the container and launch it via a per-user Binder container.
However, in some cases you don't want to rely on having a running container to deliver your reproducible document to each reader. Instead, you can use a progressive enhancement approach to reproducibility in which reproducible elements can be made dynamic, on demand, based on user interaction. The API is designed to allow for this use case, allowing user interfaces to connect to alternative execution contexts both local and remote. By exposing the API as a bridge Bindilla enables this use case for execution contexts hosted on Binder.
This bridge relies on nbstencilaproxy
being in the container image that is launched by Binder. repo2docker
will detect Dar folders in a repo and install nbstencilaproxy
and other necessary requirements automatically.
To use Bindilla to connect a Stencila interface with a Binder container add the hosts
URL parameter. For example:
-
An example of a Jupyter Notebook converted to JATS and hosted in an Amazon S3 bucket: http://builds.stenci.la/stencila/persist-some-cell-state-2018-07-27-e42260d/example.html?archive=py-jupyter&hosts=https://bindilla.stenci.la/v0
-
An example scientific article hosted in an Amazon S3 bucket: http://builds.stenci.la/stencila/update-the-introduction-rds-example-2018-11-16-db47651/example.html?archive=introduction-rds&hosts=https://bindilla.stenci.la/https://github.com/stencila/examples/elife-30274-binder/v0
-
The same example hosted on Substance's CDN: http://cdn.substance.io/rds-reader-4/example.html?archive=rds-user-testing&hosts=https://bindilla.stenci.la/https://github.com/stencila/examples/elife-30274-binder/v0
BinderHub, and much of the wider Jupyter ecosystem, is implemented in Python. We want to have an implementation that is familiar to that community.
For the same reason we are using Python, because BinderHub uses Tornado.
The Host
is implemented in bindilla/host.py
and a HTTP server is implemented in bindilla/host_http_server.py
. This is to maintain consistency with the code and file structure in other implementations of the Stencila Host API e.g. stencila/py
, stencila/node
. Although for Bindilla it probably only makes sense to have a HTTP server, in these other implementations there may be more than one server protocol providing access to the host and this structure provides for separation of concerns.
As it happens, yes!
Host(self, binder_host='https://mybinder.org', proxy=True)
A Stencila Host
that launches, and then proxies to, a container on Binder.
Host.manifest(self, extra_environs=None)
Return the manifest for this host.
Host.parse_environ(environ_id)
Parse an environ id into an environment spec to include in manifest.
Also split out the parts needed for a Binder repo path, which have the pattern
<provider-name>/<org-name>/<repo-name>/<branch|commit|tag>
The <branch|commit|tag> part is optional and defaults to
master`.
Host.launch_environ(self, environ_id)
Launch an environment on Binder.
This sends a request to Binder to create a new container based on the environment identifier.
Host.proxy_environ(self, method, binder_id, token, path, body=None)
Proxy requests through to the binder.
This methods appends /stencila-host
to the Binder container's URL
e.g https://hub.mybinder.org/user/org-repo-mukdlnm5/stencila-host
and puts the token into the header for authorization.
BaseHandler(self, application, request, **kwargs)
A base class for all request handlers.
Adds necessary headers and handles OPTIONS
requests
needed for CORS. Handles errors.
IndexHandler(self, application, request, **kwargs)
Handles requests to the index/home page.
Just redirect to the Github repo. Don't use a 301, or 302, because that can cause load balancer helth checks to fail.
ManifestHandler(self, application, request, **kwargs)
Handles requests for Bindilla's Host
manifest.
EnvironHandler(self, application, request, **kwargs)
Handles requests to launch and shutdown an environment on Binder.
EnvironHandler.post(self, environ_id)
Launch a Binder for the environment.
EnvironHandler.delete(self, environ_id)
Shutdown a Binder for the environment.
Currently, this is a no-op, but is provided for API compatability (clients may request for an environ to be stopped).
ProxyHandler(self, application, request, **kwargs)
Proxies requests through to the container running on Binder.
make()
Make the Tornado RuleRouter
.
run()
Run the HTTP server.