3 from configparser import ConfigParser
\r
7 from flask import request, jsonify, current_app
\r
8 from app.helpers.time_helper import unix_time_millis
\r
9 from app.errors.bad_request_exception import BadRequestException
\r
15 def create_headers(enable_cache=True, content_type="application/json", connection="Keep-Alive"):
\r
16 headers = {'Cache-Control':'no-cache, no-store, must-revalidate', "Pragma":"no-cache", "Expires":"0"} if not enable_cache else {}
\r
17 headers['content-type'] = content_type
\r
18 headers['connection'] = connection
\r
20 def create_url(config=None, uri_path = "/", url_string=None):
\r
21 return config['api']['base_url'] +":"+ config['api']['port']+uri_path if url_string is None else url_string
\r
23 def valid_string_json(string, response_message="Invalid json string in query or jsonBody, format requires quoted json object e.g. \"{'key':'value, key2:{'innerKey':'innerValue'}}\""):
\r
25 string_to_dict = ast.literal_eval(string)
\r
27 raise BadRequestException(406, response_message)
\r
29 def route_check(config=None, get_function=None, post_function=None, put_function=None, delete_function=None):
\r
32 Since all routes do the same pre-check and have a similar skeleton, this function just refactored the pre-check for code reuse
\r
33 Arguments (**kwargs): pass in the specified key(s) and method(s) that handle the type of method, method must be allowed by route decorator
\r
34 get_function => type: function
\r
35 put_function => type: function
\r
36 delete_function => type: function
\r
38 returns the return of the function call, typically a jsonified response.
\r
39 you can capture response in a var and execute logic or you can just return the function call/response
\r
41 response = route_check(post_function = handle_post)
\r
42 return route_check(get_function = handle_get, post_function = handle_post)
\r
44 if not request.is_json: raise BadRequestException(406, "Invalid Json Request")
\r
47 response_dict = vth_response_dic()
\r
48 start_time = unix_time_millis(datetime.datetime.now())
\r
50 ret_url = request.args.get('retURL')
\r
54 request_data = request.json
\r
55 json_keys = set(request_data)
\r
56 action_request = request_data.get("action").lower()
\r
57 valid_actions = {"policies", "policy", "policy_ids", "policy_schema", "policy_schemas", "policy_status", "policy_types", "ric", "rics", "service", "services", "keepalive", "status" }
\r
58 required_keys = {"action", "method", "auth", "action_data"}
\r
60 #check for valid action and json request contains required keys
\r
61 if not required_keys <= json_keys: raise BadRequestException(406, "Json request is missing required keys {}".format(required_keys))
\r
62 if not action_request in valid_actions: raise BadRequestException(406, "Action is not supported {}".format(action_request))
\r
63 #check request's action_data key contains required keys
\r
64 if 'query' not in request.json['action_data']: raise BadRequestException(406, "action_data must contain query and jsonBody ")
\r
65 if 'jsonBody' not in request.json['action_data']: raise BadRequestException(406, "action_data must contain query and jsonBody")
\r
67 query = request.json['action_data']['query'] if 'query' in request.json['action_data'] else ""
\r
68 json_body = request.json['action_data']['jsonBody'] if 'jsonBody' in request.json['action_data'] else ""
\r
71 if valid_string_json(query) and valid_string_json(json_body):
\r
72 if(request.method == 'GET'):
\r
73 response_dict = get_function(request, response_dict, config)
\r
74 elif(request.method == 'POST'):
\r
75 response_dict = post_function(request, response_dict, config)
\r
76 elif(request.method == 'PUT'):
\r
77 response_dict = put_function(request, response_dict, config)
\r
78 elif(request.method == 'DELETE'):
\r
79 response_dict = delete_function(request, response_dict, config)
\r
81 raise BadRequestException(406, "Invalid JSON Strings")
\r
82 end_time = unix_time_millis(datetime.datetime.now())
\r
83 response_dict['vthResponse']['testDurationMS'] = end_time-start_time
\r
84 if ret_url is not None:
\r
85 sendCallback(ret_url,response_dict)
\r
87 return jsonify(response_dict), status_code
\r
89 def get_proxies(config):
\r
90 proxy_enabled = config.getboolean('resource', 'proxy_enabled')
\r
95 if not proxy_enabled:
\r
98 req_proxies['http'] = config['resource']['http_proxy']
\r
99 req_proxies['https'] = config['resource']['https_proxy']
\r
101 def get_credentials(json_data, config):
\r
102 auth_enabled = config.getboolean('auth', 'creds_enabled')
\r
103 if not auth_enabled:
\r
106 username = config['auth']['username'] if 'username' not in json_data['auth'] else json_data['auth']['username']
\r
107 password = config['auth']['password'] if 'password' not in json_data['auth'] else json_data['auth']['password']
\r
108 return (username, password)
\r
109 def vth_response_dic():
\r
117 "testDurationMS": "",
\r
118 'dateTimeUTC': str(datetime.datetime.now()),
\r
119 "abstractMessage": "Success",
\r
123 return response_data
\r
125 def sendCallback(url, data):
\r
127 if type(data) is not dict:
\r
128 data = {"msg": data}
\r
129 current_app.logger.info("sending callback")
\r
130 requests.post(url, json=data)
\r
131 except Exception as e:
\r
132 current_app.logger.info(e)
\r
135 def get_request_data(request):
\r
136 if not request.is_json:
\r
137 raise ValueError("request must be json")
\r
138 requestData = request.get_json()
\r
142 def valid_json(data):
\r
145 _ = json.loads(data)
\r
146 except ValueError as e:
\r
149 def get_config(config_file_name):
\r
150 config = ConfigParser(os.environ)
\r
151 config.read(config_file_name)
\r
154 def validate_request(request_data, isPublish=True):
\r
156 missing_params = []
\r
158 if 'topic_name' not in request_data:
\r
159 missing_params.append("topic_name")
\r
161 if 'data' not in request_data:
\r
162 missing_params.append('data')
\r
164 if 'consumer_group' not in request_data:
\r
165 missing_params.append('consumer_group')
\r
166 if 'consumer_id' not in request_data:
\r
167 missing_params.append('consumer_id')
\r
170 err_msg = '{} request requires the following: '.format('publish' if isPublish else 'subscribe')
\r
171 err_msg += ','.join(missing_params)
\r
172 raise KeyError(err_msg)
\r
175 def build_url(config, request_data, is_publish=True):
\r
177 base_path = config['resource']['base_address'] + config['resource']['publish']
\r
178 topic_name = request_data['topic_name']
\r
179 publish_address = base_path.format(topic_name=topic_name)
\r
180 return publish_address
\r
182 base_path = config['resource']['base_address'] + config['resource']['subscribe']
\r
183 topic_name = request_data['topic_name']
\r
184 consumer_group = request_data['consumer_group']
\r
185 consumer_id = request_data['consumer_id']
\r
186 subscribe_address = base_path.format(topic_name=topic_name, consumer_group=consumer_group, consumer_id=consumer_id)
\r
187 if ('timeout' in request_data):
\r
188 subscribe_address = (subscribe_address + '?timeout={}').format(request_data['timeout'])
\r
189 return subscribe_address
\r
192 def send_request(url, config, is_subscribe_request=False, payload=None):
\r
193 # setup default values
\r
194 auth_enabled = config.getboolean('auth', 'auth_enabled')
\r
195 proxy_enabled = config.getboolean('resource', 'proxy_enabled')
\r
202 # place proxy and authentication information
\r
204 username = config['auth']['username']
\r
205 password = config['auth']['password']
\r
207 req_proxies['http'] = config['resource']['http_proxy']
\r
208 req_proxies['https'] = config['resource']['https_proxy']
\r
210 # for subscribe request
\r
211 if is_subscribe_request:
\r
212 return requests.get(url,
\r
213 auth=(username, password) if auth_enabled else None,
\r
214 proxies=req_proxies if proxy_enabled else None)
\r
215 # for publish request
\r
216 req_headers = {'Content-type': 'application/json'}
\r
217 return requests.post(url,
\r
219 auth=(username, password) if auth_enabled else None,
\r
220 proxies=req_proxies if proxy_enabled else None,
\r
221 headers=req_headers)
\r