-
Notifications
You must be signed in to change notification settings - Fork 11
/
micro_handler.py
92 lines (75 loc) · 4.15 KB
/
micro_handler.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
from collections import namedtuple
from functools import partial
from frontik.handler import BaseHandler, HTTPError
class MicroHandler(BaseHandler):
_Request = namedtuple('_Request', ('method', 'host', 'uri', 'kwargs'))
def GET(self, host, uri, data=None, headers=None, connect_timeout=None, request_timeout=None,
follow_redirects=True, labels=None, fail_on_error=False):
return MicroHandler._Request(
'GET', host, uri, dict(
data=data, headers=headers,
connect_timeout=connect_timeout, request_timeout=request_timeout,
follow_redirects=follow_redirects, labels=labels,
parse_on_error=True, fail_on_error=fail_on_error
)
)
def POST(self, host, uri, data='', headers=None, files=None, connect_timeout=None, request_timeout=None,
follow_redirects=True, content_type=None, labels=None, fail_on_error=False):
return MicroHandler._Request(
'POST', host, uri, dict(
data=data, headers=headers, files=files,
connect_timeout=connect_timeout, request_timeout=request_timeout,
follow_redirects=follow_redirects, content_type=content_type, labels=labels,
parse_on_error=True, fail_on_error=fail_on_error
)
)
def PUT(self, host, uri, data='', headers=None, connect_timeout=None, request_timeout=None,
content_type=None, labels=None, fail_on_error=False):
return MicroHandler._Request(
'PUT', host, uri, dict(
data=data, headers=headers,
connect_timeout=connect_timeout, request_timeout=request_timeout,
content_type=content_type, labels=labels,
parse_on_error=True, fail_on_error=fail_on_error
)
)
def DELETE(self, host, uri, data=None, headers=None, connect_timeout=None, request_timeout=None,
content_type=None, labels=None, fail_on_error=False):
return MicroHandler._Request(
'DELETE', host, uri, dict(
data=data, headers=headers,
connect_timeout=connect_timeout, request_timeout=request_timeout,
content_type=content_type, labels=labels,
parse_on_error=True, fail_on_error=fail_on_error
)
)
def __init__(self, application, request, logger, request_id=None, **kwargs):
super(MicroHandler, self).__init__(application, request, logger, request_id, **kwargs)
self._METHODS_MAPPING = {
'GET': self._http_client.get_url,
'POST': self._http_client.post_url,
'PUT': self._http_client.put_url,
'DELETE': self._http_client.delete_url
}
def handle_return_value(self, handler_method_name, return_value):
def _fail_on_error_wrapper(name, data, response):
error_method_name = handler_method_name + '_requests_failed'
if hasattr(self, error_method_name):
getattr(self, error_method_name)(name, data, response)
status_code = response.code if 300 <= response.code < 500 else 503
raise HTTPError(status_code, 'HTTP request failed with code {}'.format(response.code))
if isinstance(return_value, dict):
futures = {}
for name, req in return_value.iteritems():
req_type = getattr(req, 'method', None)
if req_type not in self._METHODS_MAPPING:
raise Exception('Invalid request object: {!r}'.format(req))
if req.kwargs.pop('fail_on_error'):
req.kwargs['error_callback'] = partial(_fail_on_error_wrapper, name)
method = self._METHODS_MAPPING[req_type]
url = '{}/{}'.format(req.host.rstrip('/'), req.uri.lstrip('/'))
futures[name] = method(url, **req.kwargs)
done_method_name = handler_method_name + '_requests_done'
self._http_client.group(futures, getattr(self, done_method_name, None), name='MicroHandler')
elif return_value is not None:
raise Exception('Invalid return type: {}'.format(type(return_value)))