Deprecate any arnied wrapper cnfvar functionality
[pyi2ncommon] / src / web_interface.py
CommitLineData
11cbb815
PD
1# The software in this package is distributed under the GNU General
2# Public License version 2 (with a special exception described below).
3#
4# A copy of GNU General Public License (GPL) is included in this distribution,
5# in the file COPYING.GPL.
6#
7# As a special exception, if other files instantiate templates or use macros
8# or inline functions from this file, or you compile this file and link it
9# with other works to produce a work based on this file, this file
10# does not by itself cause the resulting work to be covered
11# by the GNU General Public License.
12#
13# However the source code for this file must still be made available
14# in accordance with section (3) of the GNU General Public License.
15#
16# This exception does not invalidate any other reasons why a work based
17# on this file might be covered by the GNU General Public License.
18#
19# Copyright (c) 2016-2018 Intra2net AG <info@intra2net.com>
20
f49f6323
PD
21"""
22
23SUMMARY
24------------------------------------------------------
25Utility for HTTP based interaction with the arnied web page.
26
27Copyright: Intra2net AG
28
29
30INTERFACE
31------------------------------------------------------
32
33"""
34
35import re
1ba3b378 36import ssl
f49f6323
PD
37import http.client as client
38import urllib.parse as parse
c16498f5 39import socket
f49f6323 40import logging
7628bc48 41
3de8b4d8 42log = logging.getLogger('pyi2ncommon.web_interface')
f49f6323 43
f49f6323 44
c16498f5
CH
45#: FQDN of local machine
46LOCALHOST = socket.gethostname()
47
f49f6323 48
897c6e50 49def find_in_form(regex, form="status", escape=False, check_certs=True):
f49f6323 50 """
7628bc48 51 Find a regex in given I2N web page form.
f49f6323
PD
52
53 :param str regex: regular expression to find
7628bc48 54 :param str form: form name to open
f49f6323 55 :param bool escape: whether to escape the regex
897c6e50 56 :param check_certs: forwarded to :py:func:`web_page_request`, see doc there
f49f6323
PD
57 :returns: whether the regex was found
58 :rtype: bool
59 """
897c6e50
CH
60 data = web_page_request(method="GET", url="/arnie?form=" + form,
61 check_certs=check_certs)
f49f6323
PD
62 if escape:
63 regex = re.escape(regex)
64 if re.search(regex, data):
65 return True
66 else:
67 log.debug("'%s' could not be found in:\n%s", regex, data)
68 return False
69
70
897c6e50 71def web_page_request(method="GET", url="/", body=None, check_certs=True):
f49f6323
PD
72 """
73 Send an HTTPS request and return any response data.
74
897c6e50
CH
75 SSL certificates are checked against a default set of certificates
76 installed on you system. This can be disabled (not recommended, security
77 implications!) by setting `check_certs` to `False`. To allow a secure
78 connection to host with e.g. a self-signed certificate, the caller can
79 load this certificate by specifying `check_certs=/path/to/cert.pem`.
c16498f5
CH
80 (see also: :py:meth:`ssl.SSLContext.load_verify_locations`). Note that the
81 certificate has to be issued for the same server name that we try to
82 access, i.e. :py:data:`LOCALHOST`.
897c6e50 83
f49f6323
PD
84 :param str method: GET or POST method for the request
85 :param str url: url location within the remote host
86 :param body: dictionary to be parsed and added to the url
87 :type body: {str, str} or None
897c6e50
CH
88 :param check_certs: Whether or not to check ssl certificates for connection
89 or file name to a certificate file
90 :type check_certs: bool or str
f49f6323
PD
91 :returns: data from the response if any
92 :rtype: str
93 """
94 body = parse.urlencode(body) if body is not None else ""
95 headers = {"Content-Type": "application/x-www-form-urlencoded",
96 "Accept": "text/plain"}
97
897c6e50
CH
98 if isinstance(check_certs, str):
99 context = ssl.create_default_context(cafile=check_certs)
100 elif check_certs:
101 context = ssl.create_default_context()
102 else:
103 # disable certificate checks
104 context = ssl._create_unverified_context()
c16498f5 105 conn = client.HTTPSConnection(LOCALHOST, context=context)
f49f6323
PD
106 conn.request(method, url, body, headers)
107 resp = conn.getresponse()
108 logging.info("Request status %s and response %s",
109 resp.status, resp.reason)
110 if resp.status != 200:
eed487df 111 raise client.HTTPException("POST request failed.")
f49f6323
PD
112 data = resp.read().decode()
113 conn.close()
114
115 return data