HTTP server side API — Mopidy 2.0.1 documentation

# HTTP server side API

The Mopidy-HTTP extension comes with an HTTP server to host Mopidy’s HTTP JSON-RPC API. This web server can also be used by other extensions that need to expose something over HTTP.

The HTTP server side API can be used to:

- host static files for e.g. a Mopidy client written in pure JavaScript,
- host a Tornado application, or
- host a WSGI application, including e.g. Flask applications.

To host static files using the web server, an extension needs to register a name and a file path in the extension registry under the `http:static` key.

To extend the web server with a web application, an extension must register a name and a factory function in the extension registry under the `http:app` key.

For details on how to make a Mopidy extension, see the Extension development guide.

## Static web client example

To serve static files, you just need to register an `http:static` dictionary in the extension registry. The dictionary must have two keys: `name` and `path`. The `name` is used to build the URL the static files will be served on. By convention, it should be identical with the extension’s `ext_name`, like in the following example. The `path` tells Mopidy where on the disk the static files are located.

Assuming that the code below is located in the file `mywebclient/__init__.py`, the files in the directory `mywebclient/static/` will be made available at `/mywebclient/` on Mopidy’s web server. For example, `mywebclient/static/foo.html` will be available at http://localhost:6680/mywebclient/foo.html.

    from __future__ import absolute_import, unicode_literals

    import os

    from mopidy import ext

    class MyWebClientExtension(ext.Extension):
        ext_name = 'mywebclient'

        def setup(self, registry):
            registry.add('http:static', {
                'name': self.ext_name,
                'path': os.path.join(os.path.dirname(__file__), 'static'),
            })

        # See the Extension API for the full details on this class

## Tornado application example

The Mopidy-HTTP extension’s web server is based on the Tornado web framework. Thus, it has first class support for Tornado request handlers.

In the following example, we create a `tornado.web.RequestHandler` called `MyRequestHandler` that responds to HTTP GET requests with the string `Hello, world! This is Mopidy $version`, where it gets the Mopidy version from Mopidy’s core API.

To hook the request handler into Mopidy’s web server, we must register a dictionary under the `http:app` key in the extension registry. The dictionary must have two keys: `name` and `factory`.

The `name` is used to build the URL the app will be served on. By convention, it should be identical with the extension’s `ext_name`, like in the following example.

The `factory` must be a function that accepts two arguments, `config` and `core`, respectively a dict structure of Mopidy’s config and a `pykka.ActorProxy` to the full Mopidy core API. The `factory` function must return a list of Tornado request handlers. The URL patterns of the request handlers should not include the `name`, as that will be prepended to the URL patterns by the web server.

When the extension is installed, Mopidy will respond to requests to http://localhost:6680/mywebclient/ with the string `Hello, world! This is Mopidy $version`.

    from __future__ import absolute_import, unicode_literals

    import os

    import tornado.web

    from mopidy import ext

    class MyRequestHandler(tornado.web.RequestHandler):
        def initialize(self, core):
            self.core = core

        def get(self):
            self.write(
                'Hello, world! This is Mopidy %s' %
                self.core.get_version().get())

    def my_app_factory(config, core):
        return [
            ('/', MyRequestHandler, {'core': core})
        ]

    class MyWebClientExtension(ext.Extension):
        ext_name = 'mywebclient'

        def setup(self, registry):
            registry.add('http:app', {
                'name': self.ext_name,
                'factory': my_app_factory,
            })

        # See the Extension API for the full details on this class

## WSGI application example

WSGI applications are second-class citizens on Mopidy’s HTTP server. The WSGI applications are run inside Tornado, which is based on non-blocking I/O and a single event loop. In other words, your WSGI applications will only have a single thread to run on, and if your application is doing blocking I/O, it will block all other requests from being handled by the web server as well.

The example below shows how a WSGI application that returns the string `Hello, world! This is Mopidy $version` on all requests. The WSGI application is wrapped as a Tornado application and mounted at http://localhost:6680/mywebclient/.

    from __future__ import absolute_import, unicode_literals

    import os

    import tornado.web
    import tornado.wsgi

    from mopidy import ext

    def my_app_factory(config, core):

        def wsgi_app(environ, start_response):
            status = '200 OK'
            response_headers = [('Content-type', 'text/plain')]
            start_response(status, response_headers)
            return [
                'Hello, world! This is Mopidy %s\n' %
                self.core.get_version().get()
            ]

        return [
            ('(.*)', tornado.web.FallbackHandler, {
                'fallback': tornado.wsgi.WSGIContainer(wsgi_app),
            }),
        ]

    class MyWebClientExtension(ext.Extension):
        ext_name = 'mywebclient'

        def setup(self, registry):
            registry.add('http:app', {
                'name': self.ext_name,
                'factory': my_app_factory,
            })

        # See the Extension API for the full details on this class

## API implementors

See Web extensions.