Modul http
Dieses Modul implementiert die Möglichkeit das http Protokoll und damit unter anderem die Möglichkeit Webinterfaces für Plugins zu erstellen.
API des Moduls
- class modules.http.CherryPyFilter(name='')[Quellcode]
Bases:
Filter
This class builds a filter to be used in logging.yaml to configure logging
Returning True tells logging to suppress this logentry, whereas False will include the record into further processing and eventual output
- filter(record)[Quellcode]
Determine if the specified record is to be logged.
Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place.
- class modules.http.Http(*args, **kargs)[Quellcode]
Bases:
Module
- version = '1.7.2'
- webif_mount_prefix = '/plugin'
- gtemplates_dir = ''
- gstatic_dir = ''
- init_template_environment()[Quellcode]
Initialize the Jinja2 template engine environment
- Rückgabe:
Jinja2 template engine environment
- Rückgabetyp:
object
- is_staticfile(path)[Quellcode]
Method tests, if the given pathname points to an existing file in the webif’s static directory or the global static directory gstatic in the http module
This method extends the jinja2 template engine
- Parameter:
path – path to test
type – str
- Rückgabe:
True if the file exists
- Rückgabetyp:
bool
- is_port_in_use(port)[Quellcode]
- get_user_dict()[Quellcode]
Returns the user(s) defined in ../etc/module.yaml (section http) as a dict
The information is a dict containing the hashed_password and a list of groups for each user
- Rückgabe:
Information of defined users
- Rückgabetyp:
dict
- validate_password(realm, username, password)[Quellcode]
Validate a given user/password combination
- Parameter:
realm –
username –
password –
- Rückgabe:
- validate_service_password(realm, username, password)[Quellcode]
- get_local_ip_address()[Quellcode]
Returns the local ip address under which the webinterface can be reached
- Rückgabe:
ip address
- Rückgabetyp:
str
- get_local_hostname()[Quellcode]
Returns the local hostname under which the webinterface can be reached
- Rückgabe:
fully qualified hostname
- Rückgabetyp:
str
- get_local_port()[Quellcode]
Returns the local port under which the webinterface can be reached
- Rückgabe:
port number
- Rückgabetyp:
int
- get_local_servicesport()[Quellcode]
Returns the local port under which the webservices can be reached
- Rückgabe:
port number
- Rückgabetyp:
int
- get_service_user()[Quellcode]
Returns the user with which the webservices can be reached
- Rückgabe:
user
- Rückgabetyp:
str
- get_service_password()[Quellcode]
Returns the hashed password with which the webservices can be reached
- Rückgabe:
hashed password
- Rückgabetyp:
str
- get_webifs_for_plugin(pluginname)[Quellcode]
Returns infos about the registered webinterfaces for a plugin (specified by shortname)
The information is returned as a list of dicts. One listentry for each registered webinterface. The dict for each registered webinterface has the following structure:
- webif_dict = {‚Mount‘: mount,
‚Pluginclass‘: pluginclass, ‚Webifname‘: webifname, ‚Pluginname‘: pluginname, ‚Instance‘: instance, ‚Conf‘: conf, ‚Description‘: description}
- Parameter:
pluginname (str) – Shortname of the plugin
- Rückgabe:
Tnfos about the registered webinterfaces
- Rückgabetyp:
list of dicts
- get_services_for_plugin(pluginname)[Quellcode]
Returns infos about the registered webservices for a plugin (specified by shortname)
The information is returned as a list of dicts. One listentry for each registered webservice. The dict for each registered webinterface has the following structure:
- service_dict = {‚mount‘: mount,
‚pluginclass‘: pluginclass, ‚servicename‘: servicename, ‚pluginname‘: pluginname, ‚instance‘: instance, ‚conf‘: conf, ‚description‘: description}
- Parameter:
pluginname (str) – Shortname of the plugin
- Rückgabe:
Tnfos about the registered webservices
- Rückgabetyp:
list of dicts
- register_webif(app, pluginname, conf, pluginclass='', instance='', description='', webifname='', use_global_basic_auth=True, useprefix=True)[Quellcode]
Register an application for CherryPy
This method is called by a plugin to register a webinterface
It should be called like this:
- self.mod_http.register_webif(WebInterface( … ),
self.get_shortname(), config, self.get_classname(), self.get_instance_name(), description, webifname, use_global_basic_auth, useprefix)
- Parameter:
app (object) – Instance of the application object
pluginname (str) – Mount point for the application
conf (dict) – Cherrypy application configuration dictionary
pluginclass (str) – Name of the plugin’s class
instance – Instance of the plugin (if multi-instance)
description (str) – Description of the functionallity of the webif. If left empty, a generic description will be generated
webifname (str) – Name of the webinterface. If left empty, the pluginname is used
use_global_basic_auth (bool) – if True, global basic_auth settings from the http module are used. If False, registering plugin provides its own basic_auth
useprefix (bool) – if False, no webif_mount_prefix is added to the turl
- register_service(app, pluginname, conf, pluginclass='', instance='', description='', servicename='', use_global_basic_auth=True)[Quellcode]
Register a service for CherryPy
This method is called by a plugin to register a webservice.
It should be called like this:
- self.mod_http.register_service(Webservice( … ),
self.get_shortname(), config, self.get_classname(), self.get_instance_name(), description, servicename, use_global_basic_auth)
- Parameter:
app (object) – Instance of the service object
pluginname (str) – Mount point for the service
conf (dict) – Cherrypy application configuration dictionary
pluginclass (str) – Name of the plugin’s class
instance – Instance of the plugin (if multi-instance)
description (str) – Description of the functionallity of the webif. If left empty, a generic description will be generated
servicename (str) – Name of the service. I if left empty, the pluginname is used
use_global_basic_auth – if True, global basic_auth settings from the http module are used. If False, registering plugin provides its own basic_auth
- Type:
use_global_basic_auth: bool
- register_visu(pluginname, conf, visu_port=None, use_global_basic_auth=True)[Quellcode]
Register a service for CherryPy
This method is called by a plugin to register a webservice.
It should be called like this:
self.mod_http.register_visu(self.get_shortname(), config, use_global_basic_auth)
- Parameter:
pluginname (str) – Mount point for the service
conf (dict) – Cherrypy application configuration dictionary
use_global_basic_auth – if True, global basic_auth settings from the http module are used. If False, registering plugin provides its own basic_auth
- Type:
use_global_basic_auth: bool
- start()[Quellcode]
If the module needs to startup threads or uses python modules that create threads, put thread creation code or the module startup code here.
Otherwise don’t enter code here
- stop()[Quellcode]
If the module has started threads or uses python modules that created threads, put cleanup code here.
Otherwise don’t enter code here
- log_server_info(server_nr)[Quellcode]
Log the information of a cherrypy server object
- Rückgabe:
- class modules.http.ModuleApp(mod, starturl)[Quellcode]
Bases:
object
The module http implements it’s own webinterface. This WebApp implements the entrypoint for the webinterface of the module ‚http‘.
Depenting on the configuration of the ‚http‘ module, it redirects to the webinterface of a specified plugin or it redirects to a chooser which allows the start of the differnt webinterfaces of the plugins.
This webinterface is mounted to CherryPy as ‚/‘
- index()[Quellcode]
This method is exposed to CherryPy. It implements the page ‚index.html‘
README
# Module http (README)
This module allows plugins to implement a web interface. The API is described below. The first plugin to utilize this API is the backend plugin.
> Note: To write a plugin that utilizes this module, you have to be familiar with CherryPy.
## Requirements
This module is running under SmartHomeNG versions beyond v1.3. It requires Python >= 3.4 as well as the lib **cherrypy**. You can install the libraries (python modules) with:
```
(sudo apt-get install python-cherrypy)
sudo pip3 install cherrypy
```
And please pay attention that the lib(s) are installed for Python3 and not an older Python 2.7 that is probably installed on your system. Be careful to use `pip3` and not `pip`.
> Note: This module needs the module handling in SmartHomeNG to be activated. Make sure, that `use_modules`in `etc/smarthome.yaml` is **not** set to False!
## Configuration
### etc/module.yaml
```yaml
# etc/module.yaml
http:
module_name: http
# port: 8383
# servicesport: 8384
# showpluginlist: False
showservicelist: True
# starturl: backend
# threads: 8
# showtraceback: True
# webif_pagelength: 0
```
#### user (optional)
username for the web access. By default username `admin` is used.
#### password (optional)
password for the web access. By default empty. Without a password access is available for everyone.
#### hashed_password (optional)
hashed password for the web access. By default empty. Without a hashed password the parameter password is used.
#### service_user (optional
username for the access to webervices. By default username `serviceuser` is used.
#### service_password (optional)
password for the access to the web services. By default empty. Without a password access is available for everyone.
#### service_hashed_password (optional)
hashed password for access to the web services. By default empty. Without a hashed password the parameter Service_password is used.
#### port (optional)
The port on which the html interface listens. By default port **`8383`** is used.
#### servicesport (optional)
The port on which the html interface listens. By default port **`8384`** is used.
#### showpluginlist
If set to `False` no list of pluins with web interface is shown under `smarthomeNG.local:8383/plugins`. By default, **showpluginlist** is **True**.
#### showservicelist
If set to `True` a list of webservices is shown under `smarthomeNG.local:8384/services`. By default, ** showservicelist** is **False**.
#### starturl (optional)
The name of the plugin that is started when calling url `smarthomeNG.local:8383` without further detailing that url. If you want to startup the **backend** plugin for example: You set `starturl: backend`. That results in a redirect which redirects `smarthomeNG.local:8383` to `smarthomeNG.local:8383/backend`.
if `starturl` is not specified or point to an url that does not exist, a redirect to `smarthomeNG.local:8383/plugins` will take place (if ** showpluginlist** is **True**). It points to a page that lists all plugins that have registered a html interface and allows you to start those interfaces.
> Note: If you have redirected to a specific plugin, you can always get to the page with the list of all plugins that have registered a html interface, by entering the url `smarthomeNG.local:8383/plugins`.
#### threads (optional)
Number of worker threads to start by cherrypy (default 8, which may be too much for slow CPUs)
#### showtraceback
If set to **True, error-pages (except for error 404) will show the Python traceback for that error.
#### webif_pagelength
Amount of items being listed in a web interface table per page by default.
0 adjusts the table height automatically based on the height of the browser windows.
-1 shows all table entries on one page.
## API of module http
### Test if module http is loaded
`http` is a loadlable module. Therefore there is no guarantiee that it is present in every system. Before you can use this module, you have to make sure ist is loaded. You can do it by calling a method of the main smarthome object. Do it like this:
```
self.classname = self.__class__.__name__
try:
self.mod_http = self._sh.get_module('http')
except:
self.mod_http = None
if self.mod_http == None:
# Do what is necessary if you can't start a web interface
# for your plugin. For example:
self.logger.error('{}: Module ''http'' not loaded - Abort loading of plugin {0}'.format(self.classname))
return
```
### Registering a web application/interface
For registering a web interface (or a web application in CherryPy terminology) you first have to define an application configuration for cherrypy.
> Note: Be careful not to include a CherryPy ``global`` configuration.
An application configuration for CherryPy can look like this;
```
app_config = {
'/': {
'tools.staticdir.root': current_dir,
'tools.auth_basic.on': self._basic_auth,
'tools.auth_basic.realm': 'earth',
'tools.auth_basic.checkpassword': self.validate_password,
},
'/static': {
'tools.staticdir.on': True,
'tools.staticdir.dir': os.path.join(current_dir, 'static')
}
}
```
> Note: The `tools.auth_basic`entries in this example are for implementing a basic logon security. If you don`t want/need login security, delete those enties.
For registering a web application/interface you have to call the `register_app` of module `http`:
```
register_app(app_object,
appname,
app_config,
pluginclass, instance,
description)
```
For example:
```
appname = 'backend' # Name of the plugin
pluginclass = self.__class__.__name__
instance = self.get_instance_name()
self.mod_http.register_app(Backend(self, self.updates_allowed, language, self.developer_mode, self.pypi_timeout),
appname,
app_config,
pluginclass, instance,
description='Administration interface for SmartHomeNG')
```
## Implementing a web interface for you plugin
For details about implementing a web interface (CherryPy application) for your plugin, refer to the CherryPy documentation.
The documentation will tell you how to expose parts of your python code to be availabe through CheryPy`s http-server.
### Methods for implementing a web interface
#### get_local_ip_address()
Returns the ip address under which the web interface is listening.
#### get_local_hostname()
Returns the hostname (with domain) under which the web interface is listening.
#### get_local_port()
Returns the port under which the implemented web interfaces can be reached.
#### get_local_servicesport( ... )
Returns the port under which the implemented webservices can be reached.
#### register_app()
##### Parameters
- **app** - Instance of the CherryPy App
- **pluginname** - Standard would be: Shortname of the plugin (name of the plugin's directory)
- **conf** - dict with CherryPy App-Config
- **pluginclass** - Class of the plugin
- **instance** - Optional: Instance of the plugin (if multi-instance)
- **description** - Optional: Description to be shown on page with plugin-list
#### register_service( ... )
##### Parameters
- **service** - Instance of the CherryPy App
- **servicename** - Standard would be: Shortname of the plugin (name of the plugin's directory)
- **conf** - dict with CherryPy App-Config
- **pluginclass** - Class of the plugin
- **instance** - Optional: Instance of the plugin (if multi-instance)
- **description** - Optional: Description to be shown on page with services-list
Metadaten
Auskommentierte Parameter in den Metadaten sind noch nicht implementiert. Die Implementierung dieser Parameter wird im Rahmen der Weiterentwicklung von SmartHomeNG erfolgen:
# Metadata for the plugin
module:
# Global module attributes
classname: Http
version: 1.7.2
sh_minversion: 1.5b
# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest)
description:
de: 'Modul zur Implementierung von Backend-Webinterfaces für Plugins'
en: 'Module for implementing a backend-webinterface for plugins'
fr: "Module pour l'implémentation d'interfaces web des extensions"
parameters:
# Definition of parameters to be configured in etc/module.yaml
connectionretries:
type: int
valid_min: 0
valid_max: 100
default: 5
description:
de: Maximale Anzahl an Verbindungsversuchen zum Start von smarthomeNG, um die lokale IP zu eruieren.
en: Maximum number of connection retries to retrieve local IP address
fr: Nombre maximum de tentatives de connexion pour récupérer l'adresse IP locale
user:
type: str
default: 'admin'
description:
de: Benutzername für den Web Zugriff (Basic Auth), falls ein Passwort definiert ist
en: username for the web access (basic auth), if a password is defined
fr: Nom d'utilisateur pour l'accès web (Auth basique) si un mot de passe est défini
password:
type: str
description:
de: Passwort (im Klartext) für den Web Zugriff
en: password (unencrypted) for the web access
fr: Mot de passe (texte clair) pour l'accès web
hashed_password:
type: password
description:
de: hashed Version des Passworts für den Web Zugriff, ersetzt den Parameter 'password'
en: hashed version of the password for the web access, supersedes the parameter 'password'
fr: version haché du mot de passe pour l'interface web, remplace le paramètre 'password'
service_user:
type: str
default: 'serviceuser'
description:
de: Benutzername für den Zugriff auf Webservices (Basic Auth), falls ein Passwort definiert ist
en: username for the access to webervices (basic auth), if a password is defined
fr: Nom d'utilisateur pour l'accès au service web (Auth basique) si un mot de passe est défini
service_password:
type: str
description:
de: Passwort (im Klartext) für den Zugriff auf Webservices
en: password (unencrypted) for the access to webervices
fr: Mot de passe (texte clair) pour l'accès aux services web
service_hashed_password:
type: password
description:
de: hashed Version des Passworts für den Zugriff auf Webservices, ersetzt den Parameter 'password'
en: hashed version of the password for the access to webervices, supersedes the parameter 'password'
fr: version haché du mot de passe pour l'accès au service web (Auth basique) si un mot de passe est défini
ip:
type: ipv4
description:
de: IP Adresse auf der das http Modul aktiv sein soll - muss normalerweise nicht angegeben werden
en: IP adress on which the http module should operate - not needed, has only to be specified for special configurations
fr: Adresse IP sur laquelle le module http devrait fonctionner - il n'est généralement pas nécessaire de la spécifier
port:
type: int
valid_min: 0
valid_max: 65535
default: 8383
description:
de: Portnummer für die Webinterfaces bei Nutzung von http
en: Port number for the access to web interfaces
fr: Numéro de port pour l'accès à l'interface web
tls_port:
type: int
valid_min: 0
valid_max: 65535
default: 8385
description:
de: Portnummer für die Webinterfaces bei Nutzung von https
en: Port number for the access to webervices when using https
fr: Numéro de port pour l'accès à l'interface web si utilisation de https
use_tls:
type: bool
gui_type: yes_no
default: False
description:
de: Auf True setzen, um Zugriffe über https:// zu ermöglichen (Zertifikat muss installiert sein)
en: Set to true to allow access over https:// (certificate has to be installed)
fr: Mettre sur 'true' pour activer les accès par https (certificats doivent être installés)
tls_cert:
type: str
default: shng.cer
description:
de: Name der Zertifikatsdatei mit der Endung '.cer' oder '.pem'. Die Datei muss im Verzeichnis ../etc liegen
en: Name of the certificate file. The file musst be stored in ../etc
fr: Nom du fichier contanent les certificats. Le fichier doit se trouver dans ../etc
tls_key:
type: str
default: shng.key
description:
de: Name der Datei mit dem privaten Schlüssel und der Endung '.key'. Die Datei muss im Verzeichnis ../etc liegen
en: Name of the private key file. The file musst be stored in ../etc
fr: Nom du fichier contanent les clés privés. Le fichier doit se trouver dans ../etc
servicesport:
type: int
valid_min: 0
valid_max: 65535
default: 8384
description:
de: Portnummer für die Webservices
en: Port number for the access to webervices
fr: Numéro de port pour les services web
showpluginlist:
type: bool
gui_type: yes_no
default: True
description:
de: Anzeige einer Liste der Plugins mit Webinterfaces unter der url /plugins
en: Show a list of plugins with web interfaces under the url /plugins
fr: Afficher une listes des extensions avec interface web sous l'url /plugins
showservicelist:
type: bool
gui_type: yes_no
default: False
description:
de: Anzeige einer Liste der Plugins mit Webservices unter der url /services
en: Show a list of plugins with webservices under the url /services
fr: Afficher une listes des extensions avec des services web sous l'url /services
starturl:
type: str
default: admin
description:
de: Weiterleitungs-Url, wenn SmartHomeNG im Browser nur mit <DNS-Name>:<Portnummer> aufgerufen wird.
en: Redirection-url, if SmartHomeNG is called in the browser only by <dns-name>:<portnumber>
fr: Url de redirection si SmartHomeNG est chargé par le navigateur en utilisant seulement <nom-dns>:<numéro de port>.
threads:
type: int
default: 4
description:
de: Anzahl Threads, die für jede CherryPy App eingerichtet wird
en: number of threads setup per CherryPy app
fr: numéro de tâches prévus par application CherryPy
valid_list:
- 2
- 3
- 4
- 5
- 6
- 7
- 8
showtraceback:
type: bool
gui_type: yes_no
default: False
description:
de: Traceback bei Python Exceptions in der Fehlermeldung im Browser anzeigen. (Sollte in Produktionsinstallationen False sein)
en: Show traceback of Python exceptions on the error page displayed in the browser. (Should be False in production environment)
fr: Montrer les traces des exepctions Python sur la page d'erreurs affiché dans le navigateur. (Normallement 'False' dans en environnement de production)
webif_pagelength:
type: int
default: 0
valid_list:
- -1
- 0
- 25
- 50
- 100
description:
de: 'Anzahl an Tabellen-Zeilen, die standardmäßig in einer Web Interface Tabelle pro Seite angezeigt werden.
0 = automatisch (so viele in das Browser-Fenster passen) , -1 = alle
(Wirkt sich nur auf Web Interfaces mit sortierbaren Tabellen aus)'
en: 'Amount of table lines being listed in a web interface table per page by default.
0 = automatic (as many as can be fitted into the browser window), -1 = all
(Only affects web interfaces with sortable tables)'
description_long:
de: 'Anzahl an Tabellen-Zeilen, die standardmäßig in einer Web Interface Tabelle pro Seite angezeigt werden.\n
Bei 0 wird die Tabelle automatisch an die Höhe des Browserfensters angepasst.\n
Bei -1 werden alle Tabelleneinträge auf einer Seite angezeigt.'
en: 'Amount of table lines being listed in a web interface table per page by default.\n
0 adjusts the table height automatically based on the height of the browser windows.\n
-1 shows all table entries on one page.'