-
Notifications
You must be signed in to change notification settings - Fork 27
/
http.py
120 lines (99 loc) · 4.29 KB
/
http.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# Copyright (C) 2014 by Clearcode <http://clearcode.cc>
# and associates (see AUTHORS).
# This file is part of mirakuru.
# mirakuru is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# mirakuru is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License
# along with mirakuru. If not, see <http://www.gnu.org/licenses/>.
"""HTTP enabled process executor."""
import re
import socket
from logging import getLogger
from urllib.parse import urlparse, urlencode
from http.client import HTTPConnection, HTTPException
from typing import Union, List, Tuple, Optional, Dict, Any
from mirakuru.tcp import TCPExecutor
LOG = getLogger(__name__)
class HTTPExecutor(TCPExecutor):
"""Http enabled process executor."""
DEFAULT_PORT = 80
"""Default TCP port for the HTTP protocol."""
def __init__(
self,
command: Union[str, List[str], Tuple[str, ...]],
url: str,
status: Union[str, int] = r"^2\d\d$",
method: str = "HEAD",
payload: Optional[Dict[str, str]] = None,
headers: Optional[Dict[str, str]] = None,
**kwargs: Any,
) -> None:
"""
Initialize HTTPExecutor executor.
:param (str, list) command: command to be run by the subprocess
:param str url: URL that executor checks to verify
if process has already started.
:param bool shell: same as the `subprocess.Popen` shell definition
:param str|int status: HTTP status code(s) that an endpoint must
return for the executor being considered as running. This argument
is interpreted as a single status code - e.g. '200' or '404' but
also it can be a regular expression - e.g. '4..' or '(200|404)'.
Default: any 2XX HTTP status code.
:param str method: request method to check status on.
Defaults to HEAD.
:param dict payload: Payload to send along the request
:param dict headers:
:param int timeout: number of seconds to wait for the process to start
or stop. If None or False, wait indefinitely.
:param float sleep: how often to check for start/stop condition
:param int sig_stop: signal used to stop process run by the executor.
default is `signal.SIGTERM`
:param int sig_kill: signal used to kill process run by the executor.
default is `signal.SIGKILL`
"""
self.url = urlparse(url)
"""
An :func:`urlparse.urlparse` representation of an url.
It'll be used to check process status on.
"""
if not self.url.hostname:
raise ValueError("Url provided does not contain hostname")
port = self.url.port
if port is None:
port = self.DEFAULT_PORT
self.status = str(status)
self.status_re = re.compile(str(status))
self.method = method
self.payload = payload
self.headers = headers
super().__init__(command, host=self.url.hostname, port=port, **kwargs)
def after_start_check(self) -> bool:
"""Check if defined URL returns expected status to a check request."""
conn = HTTPConnection(self.host, self.port)
try:
body = urlencode(self.payload) if self.payload else None
headers = self.headers if self.headers else {}
conn.request(
self.method,
self.url.path,
body,
headers,
)
try:
status = str(conn.getresponse().status)
finally:
conn.close()
if status == self.status or self.status_re.match(status):
return True
return False
except (HTTPException, socket.timeout, socket.error) as ex:
LOG.debug(
"Encounter %s while trying to check if service has started.", ex
)
return False