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
14 def create_headers(enable_cache=True, content_type="application/json", connection="Keep-Alive"):
\r
15 headers = {'Cache-Control':'no-cache, no-store, must-revalidate', "Pragma":"no-cache", "Expires":"0"} if not enable_cache else {}
\r
16 headers['content-type'] = content_type
\r
17 headers['connection'] = connection
\r
19 def create_url(config=None, uri_path = "/", url_string=None):
\r
20 return config['api']['base_url'] +":"+ config['api']['port']+uri_path if url_string is None else url_string
\r
22 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
24 string_to_dict = ast.literal_eval(string)
\r
26 raise BadRequestException(406, response_message)
\r
28 def route_check(config=None, get_function=None, post_function=None, put_function=None, delete_function=None):
\r
31 Since all routes do the same pre-check and have a similar skeleton, this function just refactored the pre-check for code reuse
\r
32 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
33 get_function => type: function
\r
34 put_function => type: function
\r
35 delete_function => type: function
\r
37 returns the return of the function call, typically a jsonified response.
\r
38 you can capture response in a var and execute logic or you can just return the function call/response
\r
40 response = route_check(post_function = handle_post)
\r
41 return route_check(get_function = handle_get, post_function = handle_post)
\r
43 if not request.is_json: raise BadRequestException(406, "Invalid Json Request")
\r
45 response_dict = vth_response_dic()
\r
46 start_time = unix_time_millis(datetime.datetime.now())
\r
48 ret_url = request.args.get('retURL')
\r
52 request_data = request.json
\r
53 json_keys = set(request_data)
\r
54 action_request = request_data.get("action").lower()
\r
55 valid_actions = {"geta1policytype", "geta1policy", "puta1policy", "deletea1policy", "geta1policystatus"}
\r
56 required_keys = {"action", "auth", "action_data"}
\r
58 #check for valid action and json request contains required keys
\r
59 if not required_keys <= json_keys: raise BadRequestException(406, "Json request is missing required keys {}".format(required_keys))
\r
60 if not action_request in valid_actions: raise BadRequestException(406, "Action is not supported {}".format(action_request))
\r
61 #check request's action_data key contains required keys
\r
62 if 'query' not in request.json['action_data']: raise BadRequestException(406, "action_data must contain query and jsonBody ")
\r
63 if 'jsonBody' not in request.json['action_data']: raise BadRequestException(406, "action_data must contain query and jsonBody")
\r
65 query = request.json['action_data']['query'] if 'query' in request.json['action_data'] else ""
\r
66 json_body = request.json['action_data']['jsonBody'] if 'jsonBody' in request.json['action_data'] else ""
\r
68 if valid_string_json(query) and valid_string_json(json_body):
\r
69 if(request.method == 'GET'):
\r
70 response_dict = get_function(request, response_dict, config)
\r
71 elif(request.method == 'POST'):
\r
72 response_dict = post_function(request, response_dict, config)
\r
73 elif(request.method == 'PUT'):
\r
74 response_dict = put_function(request, response_dict, config)
\r
75 elif(request.method == 'DELETE'):
\r
76 response_dict = delete_function(request, response_dict, config)
\r
78 raise BadRequestException(406, "Invalid JSON Strings")
\r
79 end_time = unix_time_millis(datetime.datetime.now())
\r
80 response_dict['vthResponse']['testDurationMS'] = end_time-start_time
\r
81 if ret_url is not None:
\r
82 sendCallback(ret_url,response_dict)
\r
84 return jsonify(response_dict), status_code
\r
86 def get_proxies(config):
\r
87 proxy_enabled = config.getboolean('resource', 'proxy_enabled')
\r
92 if not proxy_enabled:
\r
95 req_proxies['http'] = config['resource']['http_proxy']
\r
96 req_proxies['https'] = config['resource']['https_proxy']
\r
98 def get_credentials(json_data, config):
\r
99 auth_enabled = config.getboolean('auth', 'creds_enabled')
\r
100 if not auth_enabled:
\r
103 username = config['auth']['username'] if 'username' not in json_data['auth'] else json_data['auth']['username']
\r
104 password = config['auth']['password'] if 'password' not in json_data['auth'] else json_data['auth']['password']
\r
105 return (username, password)
\r
106 def vth_response_dic():
\r
114 "testDurationMS": "",
\r
115 'dateTimeUTC': str(datetime.datetime.now()),
\r
116 "abstractMessage": "Success",
\r
120 return response_data
\r
121 #TODO data is data from callback and not my json response
\r
122 def sendCallback(url, data):
\r
124 if type(data) is not dict:
\r
125 data = {"msg": data}
\r
126 current_app.logger.info("sending callback")
\r
127 requests.post(url, json=data)
\r
128 except Exception as e:
\r
129 current_app.logger.info(e)
\r
132 def get_request_data(request):
\r
133 if not request.is_json:
\r
134 raise ValueError("request must be json")
\r
135 requestData = request.get_json()
\r
139 def valid_json(data):
\r
142 _ = json.loads(data)
\r
143 except ValueError as e:
\r
146 def get_config(config_file_name):
\r
147 config = ConfigParser(os.environ)
\r
148 config.read(config_file_name)
\r
151 def validate_request(request_data, isPublish=True):
\r
153 missing_params = []
\r
155 if 'topic_name' not in request_data:
\r
156 missing_params.append("topic_name")
\r
158 if 'data' not in request_data:
\r
159 missing_params.append('data')
\r
161 if 'consumer_group' not in request_data:
\r
162 missing_params.append('consumer_group')
\r
163 if 'consumer_id' not in request_data:
\r
164 missing_params.append('consumer_id')
\r
167 err_msg = '{} request requires the following: '.format('publish' if isPublish else 'subscribe')
\r
168 err_msg += ','.join(missing_params)
\r
169 raise KeyError(err_msg)
\r
172 def build_url(config, request_data, is_publish=True):
\r
174 base_path = config['resource']['base_address'] + config['resource']['publish']
\r
175 topic_name = request_data['topic_name']
\r
176 publish_address = base_path.format(topic_name=topic_name)
\r
177 return publish_address
\r
179 base_path = config['resource']['base_address'] + config['resource']['subscribe']
\r
180 topic_name = request_data['topic_name']
\r
181 consumer_group = request_data['consumer_group']
\r
182 consumer_id = request_data['consumer_id']
\r
183 subscribe_address = base_path.format(topic_name=topic_name, consumer_group=consumer_group, consumer_id=consumer_id)
\r
184 if ('timeout' in request_data):
\r
185 subscribe_address = (subscribe_address + '?timeout={}').format(request_data['timeout'])
\r
186 return subscribe_address
\r
189 def send_request(url, config, is_subscribe_request=False, payload=None):
\r
190 # setup default values
\r
191 auth_enabled = config.getboolean('auth', 'auth_enabled')
\r
192 proxy_enabled = config.getboolean('resource', 'proxy_enabled')
\r
199 # place proxy and authentication information
\r
201 username = config['auth']['username']
\r
202 password = config['auth']['password']
\r
204 req_proxies['http'] = config['resource']['http_proxy']
\r
205 req_proxies['https'] = config['resource']['https_proxy']
\r
207 # for subscribe request
\r
208 if is_subscribe_request:
\r
209 return requests.get(url,
\r
210 auth=(username, password) if auth_enabled else None,
\r
211 proxies=req_proxies if proxy_enabled else None)
\r
212 # for publish request
\r
213 req_headers = {'Content-type': 'application/json'}
\r
214 return requests.post(url,
\r
216 auth=(username, password) if auth_enabled else None,
\r
217 proxies=req_proxies if proxy_enabled else None,
\r
218 headers=req_headers)
\r