Skip to content

Commit 04bcd85

Browse files
committed
some refactoring on request parser
1 parent 7e04c0b commit 04bcd85

File tree

5 files changed

+79
-51
lines changed

5 files changed

+79
-51
lines changed

server/api_request_handler.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ def handle(self, client_address: tuple, post_data: dict):
2222
"Error during parsing request. \nClient: {} \nRequest: {} \nException: {}".format(
2323
client_address,
2424
post_data,
25-
ex)
25+
ex
26+
)
2627
)
2728

2829
response = {
2930
'status': 'error',
30-
'error': str(ex)
31+
'error_message': str(ex)
3132
}
3233
except ExecutionError as ex:
3334
self._logger.warning(
@@ -36,11 +37,10 @@ def handle(self, client_address: tuple, post_data: dict):
3637
post_data,
3738
ex)
3839
)
39-
raise ex
4040

4141
response = {
4242
'status': 'error',
43-
'error': 'error during execution request'
43+
'error_message': 'error during execution request'
4444
}
4545

4646
return response

server/proxy_provider_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ async def post(self, request):
113113
except ValueError:
114114
response = {
115115
'status': "error",
116-
'error': "Your request doesn't look like request",
116+
'error_message': "Your request doesn't look like request",
117117
}
118118

119119
return aiohttp.web.json_response(response)

server/requests_to_models/request.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
class Request:
3+
def __init__(self, class_name):
4+
self.class_name = class_name
5+
6+
7+
class GetRequest(Request):
8+
def __init__(self, class_name, fields: list=None):
9+
super(GetRequest, self).__init__(class_name)
10+
self.fields = fields if fields is not None else []
11+
12+
@staticmethod
13+
def from_request(request: Request):
14+
return GetRequest(request.class_name)

server/requests_to_models/request_executor.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,38 @@
11
from models import session
2+
from server.requests_to_models.request import Request, GetRequest
23
import importlib
34

45

56
class RequestExecutor:
6-
def execute(self, request):
7+
def execute(self, request: Request):
78
try:
89
return {
9-
'get': self._get,
10-
}[request['method']](request)
11-
except Exception as ex:
10+
GetRequest: self._get,
11+
}[type(request)](request)
12+
except BaseException as ex:
1213
raise ExecutionError(repr(ex))
13-
except:
14-
raise ExecutionError()
1514

16-
def _get(self, request):
17-
package = importlib.import_module(request['ClassName'][0])
18-
Class = getattr(package, request['ClassName'][1])
15+
def _get(self, request: GetRequest):
16+
package = importlib.import_module(request.class_name[0])
17+
class_name = getattr(package, request.class_name[1])
1918

2019
# TODO: remove bad_proxy
2120

22-
queryset = session.query(Class).filter(Class.number_of_bad_checks == 0)
21+
queryset = session.query(class_name).filter(class_name.number_of_bad_checks == 0)
2322
result = []
2423

2524
for item in queryset:
2625
obj = {}
2726

28-
for field_name in request['fields']:
27+
for field_name in request.fields:
2928
obj[field_name] = getattr(item, field_name)
3029

3130
result.append(obj)
3231

3332
return {
3433
'data': result,
3534
'count': queryset.count(),
36-
'last_page': True,
35+
'has_more': False,
3736
}
3837

3938

server/requests_to_models/request_parser.py

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from server.requests_to_models.request import Request, GetRequest
2+
13
import string
24
import copy
35
import re
@@ -17,37 +19,39 @@ def __init__(self, config):
1719
def parse(self, request: dict):
1820
for key in request.keys():
1921
request[key] = str(request[key])
22+
self.validate_key(key)
23+
2024
if key in self.COMMA_SEPARATED_KEYS:
21-
request[key] = self._comma_separated_field_to_list(request[key])
22-
self._validate_key_value(key, request[key])
25+
request[key] = self.comma_separated_field_to_list(request[key])
2326

24-
return self._parse_dict(request)
27+
self.validate_value(key, request[key])
2528

26-
def _validate_key_value(self, key, value):
27-
self._validate_key(key)
29+
return self.parse_dict(request)
30+
31+
def validate_value(self, key: str, value):
32+
if type(value) not in [str, int, list]:
33+
raise ValidationError('Value type should be string, integer or list')
2834

29-
if len(key) > self.MAXIMUM_KEY_LENGTH:
30-
raise ValidationError(
31-
'Some key is too big. Maximum allowed length is {}'.format(self.MAXIMUM_KEY_LENGTH))
3235
if len(value) > self.MAXIMUM_VALUE_LENGTH:
3336
raise ValidationError(
3437
'Some value is too big. Maximum allowed length is {}'.format(self.MAXIMUM_VALUE_LENGTH))
3538

3639
# validate list types
3740
if type(value) is list:
3841
for value_item in value:
39-
self._validate_key_value(key, value_item)
42+
self.validate_value(key, value_item)
4043
return
4144

4245
if key in {'model', 'method', 'fields', 'order_by'}:
46+
self._validate_value_type(key, value, str)
4347
self._validate_value_regex(key, value, r'^[a-zA-Z][a-zA-Z0-9_]+$')
4448
elif key in {'filter'}:
49+
self._validate_value_type(key, value, str)
4550
self._validate_value_regex(key, value, r'^[a-zA-Z0-9_]+$')
46-
pass
4751
elif key in {'limit', 'offset'}:
48-
if type(value) is not int:
49-
raise ValidationError("Value of key '{}' should be int".format(key))
50-
pass
52+
self._validate_value_type(key, value, int)
53+
if value < 0:
54+
raise ValidationError('Value of key "{}" should be positive'.format(key))
5155
else:
5256
# It means I forget to add validation of field
5357
raise ValidationError('Server Error')
@@ -56,62 +60,73 @@ def _validate_value_regex(self, key, value, pattern):
5660
if not re.match(pattern, value):
5761
raise ValidationError("Value of key '{}' doesn't match to pattern {}".format(key, pattern))
5862

59-
def _validate_key(self, key):
63+
def _validate_value_type(self, key, value, type):
64+
if type(value) is not type:
65+
raise ValidationError('Value of key "{}" should be {}'.format(key, type))
66+
67+
def validate_key(self, key: str):
6068
if type(key) is not str:
6169
raise ValidationError("Key {} is not string".format(key))
70+
if len(key) > self.MAXIMUM_KEY_LENGTH:
71+
raise ValidationError(
72+
'Some key is too big. Maximum allowed length is {}'.format(key, self.MAXIMUM_KEY_LENGTH))
6273
if not re.match(r'^[a-zA-Z][a-zA-Z0-9_]+$', key):
63-
raise ValidationError("Key '{}' doesn't match to pattern ^[a-zA-Z][a-zA-Z0-9_]+$".format(key))
74+
raise ValidationError('Key "{}" doesn\'t match to pattern ^[a-zA-Z][a-zA-Z0-9_]+$'.format(key))
6475
if key not in self.ALLOWED_KEYS:
65-
raise ValidationError("Key '{}' isn't allowed".format(key))
76+
raise ValidationError('Key "{}" isn\'t allowed'.format(key))
6677

67-
def _comma_separated_field_to_list(self, string_field):
78+
def comma_separated_field_to_list(self, string_field):
6879
result = []
6980
for val in string_field.split(','):
7081
val = val.strip()
7182
if val:
7283
result.append(val)
7384
return result
7485

75-
def _parse_dict(self, req_dict):
76-
self.result_request = {}
86+
def parse_dict(self, req_dict):
7787
if 'model' not in req_dict:
78-
raise ParseError("You should specify 'model'")
88+
raise ParseError('You should specify "model"')
7989

8090
if req_dict['model'] not in self.config:
8191
raise ParseError("Model doesn't exist or isn't allowed")
8292

8393
config = self.config[req_dict['model']]
8494

85-
self.result_request['ClassName'] = config['modelClass']
95+
result_request = Request(config['modelClass'])
8696

8797
if 'method' not in req_dict:
88-
raise ParseError("You should specify 'method'")
98+
raise ParseError('You should specify "method"')
99+
100+
method = req_dict['method']
89101

90-
if req_dict['method'] not in config['methods']:
102+
if method not in config['methods']:
91103
raise ParseError("Method doesn't exist or isn't allowed")
92104

93-
self.result_request['method'] = req_dict['method']
105+
config = config['methods'][method]
94106

95-
config = config['methods'][req_dict['method']]
96107
return {
97108
'get': self._get,
98-
}[req_dict['method']](req_dict, config)
109+
}[method](req_dict, config, result_request)
110+
111+
def _get(self, req_dict, config, result_request):
112+
fields = []
99113

100-
def _get(self, req_dict, config):
101114
if 'fields' not in req_dict:
102-
req_dict['fields'] = ["*"]
103-
self.result_request['fields'] = copy.copy(config['fields'])
115+
fields = copy.copy(config['fields'])
104116
else:
105-
self.result_request['fields'] = []
106-
107117
for field in req_dict['fields']:
108118
if field not in config['fields']:
109-
raise ParseError("Field '{}' doesn't exist or isn't allowed".format(field))
110-
self.result_request['fields'].append(field)
119+
raise ParseError("Field \"{}\" doesn't exist or isn't allowed".format(field))
120+
121+
fields.append(field)
122+
123+
result_request = GetRequest.from_request(result_request)
124+
result_request.fields = fields
111125

112-
return self.result_request
126+
return result_request
113127

114128
def _validate_config(self):
129+
# TODO: check fields for existence and so on
115130
if False:
116131
raise ConfigFormatError()
117132

0 commit comments

Comments
 (0)