Move to requests to handle TLS connections

Fixes #15
This commit is contained in:
Scott Wallace 2021-05-26 21:52:46 +01:00
parent 4d74be6b9f
commit a4688c4442
10 changed files with 68 additions and 53 deletions

View file

@ -17,8 +17,7 @@ The following environment variables will override any config or default:
* DISABLE_RESOLVED (default: False)
* GOTIFY_KEY_APP (default: None)
* GOTIFY_KEY_CLIENT (default: None)
* GOTIFY_PORT (default: 80)
* GOTIFY_SERVER (default: localhost)
* GOTIFY_URL_PREFIX (default: http://localhost)
* LISTEN_PORT (default: 8080)
* VERBOSE (default: 0)
```
@ -48,7 +47,7 @@ docker build . -t 'alertify:latest'
e.g.
```bash
docker run --name alertify -p 8080:8080 -e TZ=Europe/London -e GOTIFY_KEY_APP=_APPKEY_ -e GOTIFY_SERVER=gotify -e GOTIFY_PORT=80 alertify:latest
docker run --name alertify -p 8080:8080 -e TZ=Europe/London -e GOTIFY_KEY_APP=_APPKEY_ -e GOTIFY_URL_PREFIX=http://gotify alertify:latest
```
## Compose:
@ -76,7 +75,6 @@ services:
- DELETE_ONRESOLVE=true
- GOTIFY_KEY_APP=_APPKEY_
- GOTIFY_KEY_CLIENT=_CLIENTKEY_
- GOTIFY_SERVER=gotify
- GOTIFY_PORT=80
- GOTIFY_URL_PREFIX=http://gotify
restart: unless-stopped
```

View file

@ -1,7 +1,6 @@
---
disable_resolved: false
gotify_key: sOmEsEcReTkEy1
gotify_port: "80"
gotify_server: gotifyserver.example.net
gotify_url_prefix: http://gotifyserver.example.net
listen_port: "8080"
verbose: true

View file

@ -1,3 +1,4 @@
flask
flask-classful
pyyaml
requests

View file

@ -50,8 +50,7 @@ class Alertify(FlaskView):
self.config = Config(configfile)
self.gotify = Gotify(
self.config.gotify_server,
self.config.gotify_port,
self.config.gotify_url_prefix,
self.config.gotify_key_app,
self.config.gotify_key_client,
)

View file

@ -19,8 +19,7 @@ class Config:
disable_resolved = bool(False)
gotify_key_app = str()
gotify_key_client = str()
gotify_port = int(80)
gotify_server = str('localhost')
gotify_url_prefix = str('http://localhost')
listen_port = int(8080)
verbose = int(0)

View file

@ -1,20 +1,21 @@
"""
Module to handle communication with the Gotify server
"""
import http.client
import json
import logging
import socket
from typing import Optional
from requests import request
class Gotify:
"""
Class to handle Gotify communications
"""
def __init__(self, server: str, port: int, app_key: str, client_key: Optional[str] = None):
self.api = http.client.HTTPConnection(server, port)
def __init__(self, url_prefix: str, app_key: str, client_key: Optional[str] = None):
self.url_prefix = url_prefix
self.app_key = app_key
self.client_key = client_key
self.base_headers = {
@ -22,7 +23,7 @@ class Gotify:
'Accept': 'application/json',
}
def _call(self, method: str, url: str, body: Optional[str] = None) -> dict:
def _call(self, method: str, url: str, data: Optional[object] = None) -> dict:
"""
Method to call Gotify with an app or client key as appropriate
"""
@ -32,11 +33,15 @@ class Gotify:
else:
headers['X-Gotify-Key'] = self.app_key
logging.debug('Sending to Gotify:\n%s', body)
logging.debug('Sending to Gotify:\n%s', data)
try:
self.api.request(method, url, body=body, headers=headers)
response = self.api.getresponse()
response = request(
method,
f'{self.url_prefix}{url}',
json=data,
headers=headers,
)
except (ConnectionRefusedError, socket.gaierror) as error:
logging.error('Connection error: %s', error)
return {
@ -45,14 +50,13 @@ class Gotify:
}
resp_obj = {
'status': response.status,
'status': response.status_code,
'reason': response.reason,
'json': None,
}
rawbody = response.read()
if len(rawbody) > 0:
if len(response.content) > 0:
try:
resp_obj['json'] = json.loads(rawbody.decode())
resp_obj['json'] = response.json
except json.decoder.JSONDecodeError as error:
logging.error('Could not parse JSON: %s', error)
@ -109,7 +113,7 @@ class Gotify:
Method to send a message payload to a Gotify server
"""
logging.debug('Sending message to Gotify')
return self._call('POST', '/message', body=json.dumps(payload, indent=2))
return self._call('POST', '/message', data=payload)
def healthcheck(self) -> dict:
"""

View file

@ -16,8 +16,7 @@ class ConfigTest(unittest.TestCase):
'disable_resolved': bool(False),
'gotify_key_app': str(),
'gotify_key_client': str(),
'gotify_port': int(80),
'gotify_server': str('localhost'),
'gotify_url_prefix': str('http://localhost'),
'listen_port': int(8080),
'verbose': int(0),
}

View file

@ -14,7 +14,7 @@ class GotifyTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.gotify_client = gotify.Gotify('', 0, '', '')
cls.gotify_client = gotify.Gotify('http://localhost', '')
@classmethod
def tearDownClass(cls):
@ -26,15 +26,12 @@ class GotifyTest(unittest.TestCase):
def tearDown(self):
pass
@patch('http.client.HTTPConnection.request')
@patch('http.client.HTTPConnection.getresponse')
@patch('http.client.HTTPResponse.read')
def test_delete(self, mock_request, mock_getresponse, mock_read):
@patch('requests.Session.request')
def test_delete(self, mock_request):
"""Test"""
mock_request.return_value.status = {}
mock_getresponse.return_value.status = 200
mock_getresponse.return_value.reason = 'OK'
mock_read.return_value = {}
mock_request.return_value.status_code = 200
mock_request.return_value.reason = 'OK'
mock_request.return_value.content = ''
self.assertDictEqual(
self.gotify_client.delete('123'),
@ -67,18 +64,15 @@ class GotifyTest(unittest.TestCase):
dict(),
)
@patch('http.client.HTTPConnection.request')
@patch('http.client.HTTPConnection.getresponse')
@patch('http.client.HTTPResponse.read')
def test_send_alert(self, mock_request, mock_getresponse, mock_read):
@patch('requests.Session.request')
def test_send_alert_empty(self, mock_request):
"""Test"""
mock_request.return_value.status = {}
mock_getresponse.return_value.status = 200
mock_getresponse.return_value.reason = 'OK'
mock_read.return_value = {}
mock_request.return_value.status_code = 200
mock_request.return_value.reason = 'OK'
mock_request.return_value.content = ''
self.assertDictEqual(
self.gotify_client.send_alert({}),
self.gotify_client.send_alert(dict()),
{
'status': 200,
'reason': 'OK',
@ -86,15 +80,35 @@ class GotifyTest(unittest.TestCase):
},
)
@patch('http.client.HTTPConnection.request')
@patch('http.client.HTTPConnection.getresponse')
@patch('http.client.HTTPResponse.read')
def test_healthcheck(self, mock_request, mock_getresponse, mock_read):
@patch('requests.Session.request')
def test_send_alert_dummy(self, mock_request):
"""Test"""
mock_request.return_value.status = {}
mock_getresponse.return_value.status = 200
mock_getresponse.return_value.reason = 'OK'
mock_read.return_value = {}
mock_request.return_value.status_code = 200
mock_request.return_value.reason = 'OK'
mock_request.return_value.content = ''
self.assertDictEqual(
self.gotify_client.send_alert(
{
'title': 'TITLE',
'message': 'MESSAGE',
'priority': 0,
'extras': dict(),
}
),
{
'status': 200,
'reason': 'OK',
'json': None,
},
)
@patch('requests.Session.request')
def test_healthcheck(self, mock_request):
"""Test"""
mock_request.return_value.status_code = 200
mock_request.return_value.reason = 'OK'
mock_request.return_value.content = ''
self.assertDictEqual(
self.gotify_client.healthcheck(),

View file

@ -12,7 +12,7 @@ class HealthcheckTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.healthcheck = health.Healthcheck(gotify.Gotify('', 0, '', ''))
cls.healthcheck = health.Healthcheck(gotify.Gotify('http://localhost', '', ''))
@classmethod
def tearDownClass(cls):

View file

@ -12,7 +12,9 @@ class MessageHandlerTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.messaging = messaging.MessageHandler(gotify.Gotify('', 0, '', ''))
cls.messaging = messaging.MessageHandler(
gotify.Gotify('http://localhost', '', '')
)
@classmethod
def tearDownClass(cls):