spaceapi-server/README.md

196 lines
5.9 KiB
Markdown
Raw Normal View History

2019-11-25 04:10:20 +01:00
# SpaceAPI Server
[![pipeline status](https://gitlab.com/s3lph/spaceapi-server/badges/master/pipeline.svg)][master]
[![coverage report](https://gitlab.com/s3lph/spaceapi-server/badges/master/coverage.svg)][master]
2019-11-30 03:24:29 +01:00
A lightweight server for [SpaceAPI][spaceapi] endpoints. Includes
support for pluggable templating, so dynamic content, like sensor
values, can be added.
2019-11-25 04:10:20 +01:00
## Dependencies
- Python 3 (>=3.6)
- [Bottle][pypi-bottle]
- [Jinja2][pypi-jinja2]
## License
[MIT License][mit]
2019-11-30 03:24:29 +01:00
## Introduction
This project is an attempt to implement a lightweight, yet versatile
SpaceAPI endpoint server. In its simplest configuration, it just
serves a plain, static, boring JSON document.
In order to provide dynamic content (e.g. whether your space is
currently open), you can replace parts of the JSON document (anything
except object keys) with [Jinja2 templates][jinja], from which you can
invoke custom plugins, which look up and return your dynamic content.
2019-11-25 04:10:20 +01:00
## Usage
2019-11-30 03:24:29 +01:00
### 0. Download
Head over to the [Releases][releases], download and install the
package that suits your needs. Alternatively, clone the repo and get
started.
2019-11-30 03:43:31 +01:00
The remainder of this document assumes that you installed the
2019-11-30 03:24:29 +01:00
server as an OS distribution package.
2019-11-25 04:10:20 +01:00
2019-11-30 03:24:29 +01:00
### 1. Overview
The configuration of this server consists of three parts:
- The **main configuration** file, usually located at
`/etc/spaceapi-server/config.json`. This file controls all the
internal settings of the server.
- The **response template** file, located at
`/etc/spaceapi-server/template.json`. This file defines the content
served by your sever.
- The **plugins** directory, located at
`/etc/spaceapi-server/plugins/`. Here you can put your plugins for
rendering dynamic content.
### 2. Configure the Server
Open the file `/etc/spaceapi-server/config.json`.
The following options are currently available:
2019-11-25 04:10:20 +01:00
```json
{
"address": "::1", # The address to listen on.
"port": 8000, # The TCP port to listen on.
"server": "wsgiref", # The Bottle backend server to use.
"template": "template.json", # Path to the SpaceAPI response template file.
"plugins_dir": "plugins", # Path to the directory containing your plugins.
"plugins": {
2019-11-30 03:24:29 +01:00
# Plugin-specific configuration should go in here, separated by plugin
"my_plugin": {
"my_option": "Hello, World!",
2019-11-30 03:43:31 +01:00
"my_other_option": [ 42, 1337 ]
2019-11-30 03:24:29 +01:00
}
2019-11-25 04:10:20 +01:00
}
}
```
2019-11-30 03:24:29 +01:00
### 3. Configure a Static SpaceAPI Endpoint
Open the file `/etc/spaceapi-server/template.json`. By default it
contains a minimal example response. If you only want to serve static
content, your `template.json` should simply contain the SpaceAPI JSON
response you want to serve.
2019-11-25 04:10:20 +01:00
2019-11-30 03:24:29 +01:00
The content is served "almost-as-is" (once parsed and re-serialized).
2019-11-25 04:10:20 +01:00
2019-11-30 03:24:29 +01:00
To learn about how a SpaceAPI response should look like, have a look
at [SpaceAPI: Getting Started][spaceapi-getting-started].
2019-11-25 04:10:20 +01:00
2019-11-30 03:24:29 +01:00
### 4. Add Dynamic Content
2019-11-25 04:10:20 +01:00
2019-11-30 03:24:29 +01:00
This example guides you through adding a dynamic `state` property to
your SpaceAPI endpoint. We'll use the following (rather simple, and
probably not too useful) data source: Check a certain file, and mark
the space as open depending on its existence.
1. Create a plugin to fetch the data. Let's name it `filestate.py`
and put in in our plugins directory:
2019-11-25 04:10:20 +01:00
```python
import os
from spaceapi_server import config, plugins
@plugins.template_function
def space_state():
# Get the plugin config dict
2019-11-30 03:24:29 +01:00
conf = config.get_plugin_config(filestate')
2019-11-25 04:10:20 +01:00
# Get the filename
filename = conf.get('filename', '/var/space_state')
try:
# Get the file's properties
stat = os.stat(filename)
except FileNotFoundError:
# File doesn't exist, aka. space is closed
return {
'open': False
}
# File exists, aka. space is open. Also report the mtime as "last changed" timestamp
return {
'open': True,
'lastchange': int(stat.st_mtime)
}
```
2019-11-30 03:24:29 +01:00
The `@template_function` decorator registers the function as a
callable in Jinja's globals. There's also `@template_filter`,
which registers a Jinja2 filter, and `@template_test`, which
registers a test. For more information on the Jinja2 templating
engine, see [Jinja2][jinja].
2019-11-25 04:10:20 +01:00
2. Call the template function in your template:
```json
{
# ...
"state": "{{ space_state() }}"
# ...
}
```
2019-11-30 03:24:29 +01:00
Although the value for the `state` key is a string containing the
Jinja2 template, the return value of your template function is a
complex data type, which will be inserted into the result as such.
Please be aware that only the first token of a templated string is
used in the result. This limitation is caused by the way Jinja2
is (ab-) used.
2019-11-25 04:10:20 +01:00
3. Configure the server:
```json
# ...
"template": "template.json",
"plugins_dir": "plugins",
"plugins": {
2019-11-30 03:24:29 +01:00
"filestate": {
"filename": "/var/space_state"
2019-11-25 04:10:20 +01:00
}
}
# ...
```
2019-11-30 03:24:29 +01:00
### 5. Start the Server
Start the server with e.g.:
```bash
systemctl start spaceapi-server.service
```
To reload the configuration, template and plugins, send a SIGHUP,
e.g. through `systemctl reload`.
If you need to run the server ad-hoc, you can start it with:
```bash
python3 -m spaceapi_server /path/to/config.json
```
### 6. Test the Server
```bash
curl http://localhost:8000/
```
You should be greeted with the SpaceAPI endpoint response.
2019-11-25 04:10:20 +01:00
[master]: https://gitlab.com/s3lph/spaceapi-server/commits/master
2019-11-30 03:24:29 +01:00
[releases]: https://gitlab.com/s3lph/spaceapi-server/-/releases
2019-11-25 04:10:20 +01:00
[spaceapi]: https://spaceapi.io/
[pypi-bottle]: https://pypi.org/project/bottle/
[pypi-jinja2]: https://pypi.org/project/Jinja2/
[mit]: https://gitlab.com/s3lph/spaceapi-server/blob/master/LICENSE
[spaceapi-getting-started]: https://spaceapi.io/getting-started/
2019-11-30 03:24:29 +01:00
[jinja]: https://jinja.palletsprojects.com/