def test_request(self): session = HttpSession(self.url) for interface_ in self.if_dict_list: if isinstance(interface_['step_list'], list): for interface in interface_['step_list']: if interface['method'] in ["post", "put"]: if interface['data_type'] == 'json': res = session.request(method=interface['method'], url=interface['url'], json=interface['body'], headers=interface['header']) elif interface['data_type'] == 'data': res = session.request(method=interface['method'], url=interface['url'], data=interface['body'], headers=interface['header']) elif interface['method'] in ["get", "delete"]: if interface['is_sign']: if interface['sign_type'] == 4: res = session.request( method=interface['method'], url=interface['url'], params={'data': interface['body']}, headers=interface['header']) else: res = session.request(method=interface['method'], url=interface['url'], params=interface['body'], headers=interface['header']) log.info(res.text)
def test_error_message_with_name_replacment(self): s = HttpSession("http://127.0.0.1:%i" % self.port) my_event = events.EventHook() kwargs = {} def on_my_event(**kw): kwargs.update(kw) my_event += on_my_event orig_events = events.request_failure events.request_failure = my_event s.request('get', '/wrong_url/01', name='replaced_url_name') events.request_failure = orig_events self.assertIn('for url: replaced_url_name', str(kwargs['exception']))
def sendGetLegendGraphicRequest(client: locustclients.HttpSession, params: dict, wmsversion: str): requestUrl = "" if "url" in params: # extract request url from params requestUrl = params["url"] params.pop("url") with client.request("GET", requestUrl, params=params, name="WMS-{}-GetLegendGraphic".format(wmsversion), catch_response=True) as response: #if response.history: # #Response was redirected # for resp in response.history: # print("Redirected with code '{}' to url '{}'".format(resp.status_code,resp.url)) if response.url is None: response.failure("Request failed. No response from server.") return url = urllib.parse.unquote(response.url) if response.status_code == 200: if response.headers['content-type'] != "image/png": errormsg = "Expected format 'image/png' but got '{}' instead\n Request URL: {}\n Request params: '{}'\nResponse: '{}'\n".format( response.headers['content-type'], url, params, response.text) vprint("Request failed:\n{}".format(errormsg)) response.failure(errormsg) else: vprint("Request successful: {}".format(url)) response.success()
def sendGetCapabilitiesRequest(client: locustclients.HttpSession, wmsversion: str): params = getGetCapabilitiesRequest(wmsversion=wmsversion) with client.request("GET", "", params=params, name="WMS-{}-GetCapabilities".format(wmsversion), catch_response=True) as response: if response.url is None: response.failure("Request failed. No response from server.") return url = urllib.parse.unquote(response.url) if not response.status_code == 200: errormsg = "Request failed with HTTP status code: '{}'\n Request URL: {}\n Request Params: {}\n Response-Content: '{}'".format( response.status_code, url, params, response.content) vprint("Request failed:\n{}".format(errormsg)) response.failure(errormsg) return if not hasValidGetCapabilitiesResponseType( response.headers['content-type']): response.failure( "Wrong response content-type encountered: '%s' (see %s)" % (response.headers['content-type'], "https://cite.opengeospatial.org/teamengine/about/wms/1.1.1/site/OGCTestData/wms/1.1.1/spec/wms1.1.1.html#basic_elements.params.format" )) return if response.content == "": vprint("Request failed (No data): {}".format(url)) response.failure("No data") return try: capabilities = xmltodict.parse(response.content) vprint("Request successful: {}".format(url)) #return capabilities except: vprint("Request failed (Failed to parse GetCapabilities XML): {}". format(url)) response.failure("Failed to parse GetCapabilities XML") return try: # parse the capabilities document once # for each WMS version parsed_layers = getAllLayers(capabilities=capabilities, wmsversion=wmsversion) return parsed_layers except Exception as ex: vprint( "Request failed (Failed to extract layers from GetCapabilities XML): {}" .format(url)) response.failure( "Failed to extract layers from GetCapabilities XML version '{0}'. Error: {1}" .format(wmsversion, ex)) return
def test_request(self): session = HttpSession(self.url) for interface_ in self.if_dict_list: for interface in interface_: if isinstance(interface['body'], dict): for k, v in interface['body'].items(): if '$' in str(v): interface['body'][k] = self.extract_dict[v[1:]] if interface['method'] in ["post", "put"]: if interface['data_type'] == 'json': res = session.request(method=interface['method'], url=interface['url'], json=interface['body'], headers=interface['header']) elif interface['data_type'] == 'data': res = session.request(method=interface['method'], url=interface['url'], data=interface['body'], headers=interface['header']) elif interface['method'] in ["get", "delete"]: if interface['is_sign']: if interface['sign_type'] == 4: res = session.request( method=interface['method'], url=interface['url'], params={'data': interface['body']}, headers=interface['header']) else: res = session.request(method=interface['method'], url=interface['url'], params=interface['body'], headers=interface['header']) if interface['extract']: self.extract_dict = get_extract(interface['extract'], res.text) log.info(res.text)
def sendGetMapRequest(client: locustclients.HttpSession, params: dict, wmsversion: str): with client.request("GET", "", params=params, name="WMS-{}-GetMap".format(wmsversion), catch_response=True) as response: if response.url is None: response.failure("Request failed. No response from server.") return url = urllib.parse.unquote(response.url) if response.status_code == 200: if response.headers['content-type'] != "image/png": errormsg = "Expected format 'image/png' but got '{}' instead\n Request URL: {}\n Request params: '{}'\nResponse: '{}'\n".format( response.headers['content-type'], url, params, response.text) vprint("Request failed:\n{}".format(errormsg)) response.failure(errormsg) else: vprint("Request successful: {}".format(url)) response.success()
class RunHttp: def __init__(self, host, is_locust=True, http_session=None, catch_dict=None): self.host = host if http_session is None: self.http_session = HttpSession(host) else: self.http_session = http_session self.is_locust = is_locust self.run_item_list = [] # self.order_dict = {} self.res_dict = {} self.catch_dict = {} if catch_dict is None else catch_dict self._add_catch_dict = {} self._add_check_dict = {} def run(self): for i in self._generator_key(): # try: # self._do_http(self.run_dict[name]) # except Exception as e: # print('err', e) self._do_http(i) class DoRes: def __init__(self, res, catch_res): self._res = res self._catch_res = catch_res def get_all_result_dict(self): return self._res def get_all_result_json(self): return json.dumps(self._res) def get_catch_dict(self): return self._catch_res def get_catch_json(self): return json.dumps(self._catch_res) try: return DoRes(self.res_dict, self.catch_dict) except Exception as e: print('结果解析错误', e) def _reg_get_all(self, s): if type(s) is dict: return self._reg_get_dict(s) elif type(s) is list: return self._reg_get_list(s) else: return self._reg_get(s) def _reg_get_list(self, s): if len(s) > 0: for i in len(s): s[i] = self._reg_get_all(s[i]) return s else: return s def _reg_get_dict(self, s): if type(s) is dict: if len(s) > 0: for j, k in s.items(): s[j] = self._reg_get_all(k) return s else: return s def _reg_get(self, s): if s is None or s == [] or s == {}: return s else: p = re.compile(r'\$\{(.*?)\}') s1 = p.findall(s) if len(s1) > 0: for i in s1: a1 = self.catch_dict.get(i) # print(a1) if a1 is not None: s = s.replace('${%s}' % i, a1) return s else: return s def add_request(self, method, path, name=None, params=None, data=None, headers=None, files=None, auth=None, timeout=None, allow_redirects=True, proxies=None, json=None, check=None, catch=None, content_encoding='utf8'): if name is None: name = path # name = path if name is None else name data = [] if data is None else data files = [] if files is None else files headers = {} if headers is None else headers params = {} if params is None else params self.run_item_list.append( dict(method=method, path=path, name=name, params=params, data=data, headers=headers, files=files, auth=auth, timeout=timeout, allow_redirects=allow_redirects, proxies=proxies, json=json, check=check, catch=catch, content_encoding=content_encoding)) return self def _generator_key(self): for i in self.run_item_list: info = dict() info['name'] = self._reg_get_all(i.get('name')) info['data'] = self._reg_get_all(i.get('data')) info['files'] = i.get('files') info['headers'] = self._reg_get_all(i.get('headers')) info['params'] = self._reg_get_all(i.get('params')) # info['method'] = method # info['path'] = path info['json'] = self._reg_get_all(i.get('json')) info['auth'] = i.get('auth') info['timeout'] = i.get('timeout') info['allow_redirects'] = i.get('allow_redirects') info['proxies'] = i.get('proxies') yield { 'method': i.get('method'), 'url': self._reg_get_all(i.get('path')), 'info': info, 'check': i.get('check'), 'catch': i.get('catch'), 'content_encoding': i.get('content_encoding') } def add_catch(self, catch_items): pass def add_check(self, check_item): pass def _catch_check_res(self, item, res, content_encoding): try: if item.get('response_item') is not None and item.get( 'response_item') in ResponseItem: if item.get('way') is not None: if item.get('response_item') is ResponseItem.content: p = re.compile(item.get('way')) p2 = p.findall(res.content.decode(content_encoding)) if len(p2) == 1: return p2[0] elif len(p2) < 1: return None else: print("正则匹配到多个结果,默认选择第一个:", item.get('way')) return p2[0] elif item.get('response_item') is ResponseItem.json: json = res.json() return eval(item.get('way')) elif item.get('response_item') is ResponseItem.cookies: cookie = {k: j for k, j in res.cookies.items()} return eval(item.get('way')) elif item.get('response_item') is ResponseItem.headers: header = {k: j for k, j in res.headers.items()} return eval(item.get('way')) elif item.get('response_item') is ResponseItem.encoding: return res.encoding elif item.get('response_item') is ResponseItem.status_code: return res.status_code else: print('在提取数据时,发生错误:', item) return None else: if item.get('response_item') is ResponseItem.encoding: return res.encoding elif item.get('response_item') is ResponseItem.status_code: return res.status_code else: print('在提取数据时,发生错误:', item) return None else: print('在抓取数据时,抓取项格式错误:', item) return None except Exception as e: print('在解析数据时,发生错误:', e) return None def catch_res(self, catch_items, res, is_dict, content_encoding): if is_dict: if catch_items.get('name') is not None: catch_result = self._catch_check_res(catch_items, res, content_encoding) if catch_result is not None: self.catch_dict[catch_items['name']] = catch_result else: for i in catch_items: if type(i) == dict: if i.get('name') is not None: catch_result = self._catch_check_res( i, res, content_encoding) if catch_result is not None: self.catch_dict[i['name']] = catch_result else: print('在抓取数据时,格式错误:', i) def check_res(self, check_items, res, is_dict, content_encoding): if is_dict: if check_items['value'] is not None: check_result = self._catch_check_res(check_items, res, content_encoding) if check_result is None: return False, '没有找到匹配的值匹配:' + str(check_items.get('value')) else: r3 = (str(check_result) == str(check_items.get('value'))) return r3, '获取' + check_items.get( 'response_item').name + ',结果为:' + str( r3) + ',实际获取:' + str( check_result) + ',期望等于:' + str( check_items.get('value')) else: print('输入格式有误,请检查:', check_items) return False, "输入格式有误,请检查:" + check_items else: is_ok = True check_result = '' for i in check_items: if type(i) == dict: if i.get('value') is not None: r2 = self._catch_check_res(i, res, content_encoding) if r2 is None: # return False, '输入格式有误,请检查:'+i if str(i.get('value')) == 'None': check_result += ( '\n获取%s,结果为:%s,期望为:%s,实际是:%s' % (i.get('response_item').name, r3, str(i.get('value')), str(r2))) is_ok = False check_result = check_result + '\n没有找到匹配的值匹配:' + i # [{'result': False, 'value': str(check_items.get('value')), 'actual': str(r2)}] else: r3 = (str(r2) == str(i.get('value'))) is_ok = (is_ok and r3) check_result += ('\n获取%s,结果为:%s,期望为:%s,实际是:%s' % (i.get('response_item').name, r3, str(i.get('value')), str(r2))) else: print('输入格式有误,请检查:', i) check_result = check_result + '\n输入格式有误,请检查' + i return is_ok, check_result def _do_http(self, key): with self.http_session.request(method=key['method'], url=key['url'], catch_response=True, **key['info']) as r: r1 = MyResponse(r, self.is_locust) if key['check'] is None: if r1.ok: r1.success() else: r1.failure(r1.reason) else: if type(key['check']) == list: if len(key['check']) > 0: r2 = self.check_res(key['check'], r1, False, key['content_encoding']) if r2[0]: r1.success() else: r1.failure(r2[1]) else: if r1.ok: r1.success() else: r1.failure(r1.reason) else: if type(key['check']) == dict: r2 = self.check_res(key['check'], r1, True, key['content_encoding']) if r2[0]: r1.success() else: r1.failure(r2[1]) else: r1.failure('校验值输入格式有误') raise Exception('校验值输入格式有误') if key['catch'] is None: pass else: if type(key['catch']) == list and len(key['catch']) > 0: self.catch_res(key['catch'], r1, False, key['content_encoding']) elif type(key['catch']) == dict: self.catch_res(key['catch'], r1, True, key['content_encoding']) else: print("抓取数据格式不正确", key['catch']) if self.is_locust: pass else: self.res_dict[key['info']['name']] = RunHttp._get_response(r1) return RunHttp._get_response(r1, key['content_encoding']) def analysis_res(self): pass @staticmethod def _get_response(res, content_encoding='UTF-8'): req11 = dict() req11['method'] = res.request.method req11['url'] = res.request.url # print(type(res.request.headers)) req11['headers'] = {k: j for k, j in res.request.headers.lower_items()} result = dict() result['status_code'] = res.status_code try: result['json'] = res.json() except: result['json'] = False # try: # result['text'] = res.text # except: # result['text'] = 'no' try: req11['auth'] = res.request.auth except: req11['auth'] = False try: req11['files'] = res.request.files except: req11['files'] = False try: req11['data'] = res.request.data except: req11['data'] = False # try: # req['params'] = res.request.params # except: # req['params'] = 'no' # try: # req['params'] = res.request.params # except: # req['params'] = 'no' result['encoding'] = res.encoding result['status_code'] = res.status_code result['headers'] = {k: j for k, j in res.headers.items()} try: result['content'] = res.content.decode(content_encoding) except UnicodeDecodeError: try: result['content'] = res.content.decode('gbk') except: result['content'] = res.content.decode('utf-8', "ignore") result['cookies'] = {k: j for k, j in res.cookies.items()} result['ok'] = res.ok result['request_meta'] = res.locust_request_meta result['reason'] = res.reason result['request'] = req11 result['elapsed'] = res.elapsed.seconds return result
class TaskqueueClient(object): """ Decorates Locust HttpSession with protobuffer and REST request preparation and response processing for communication with TaskQueue. Encapsulates TaskQueue host and ProjectID. """ SERVICE_NAME = 'taskqueue' def __init__(self, tq_location): self.tq_location = tq_location self.http_session = HttpSession(base_url=f'http://{tq_location}') @contextmanager def protobuf(self, pb_method, pb_request): """ Provides simplified interface for sending Protobuffer requests to the TaskQueue service. Args: pb_method: a str representing name of TaskQueue method. pb_request: an instance of ProtobufferMessage representing request. Returns: an instance of corresponding ProtobufferMessage (response). """ remote_api_request = remote_api_pb2.Request() remote_api_request.service_name = self.SERVICE_NAME remote_api_request.method = pb_method remote_api_request.request = pb_request.SerializeToString() headers = { 'protocolbuffertype': 'Request', 'appdata': TEST_PROJECT, 'Module': '', 'Version': '' } body = remote_api_request.SerializeToString() locust_wrapped_response = self.http_session.request( 'POST', f'http://{self.tq_location}', headers=headers, data=body, name=pb_method, catch_response=True ) with locust_wrapped_response as resp: if resp.status_code >= 400: resp.failure(f'TaskQueue responded ' f'"HTTP {resp.status_code}: {resp.reason}"') raise api_helper.HTTPError(resp.status_code, resp.reason, resp.content) api_response = remote_api_pb2.Response() api_response.ParseFromString(resp.content) if api_response.HasField('application_error'): err = api_response.application_error msg = f'{err.code}: {err.detail}' resp.failure(msg) raise api_helper.ProtobufferAppError( msg, code=err.code, detail=err.detail) if api_response.HasField('exception'): resp.failure(api_response.exception) raise api_helper.ProtobufferException(api_response.exception) pb_resp_cls_name = f'TaskQueue{pb_method}Response' pb_resp_cls = getattr(taskqueue_service_pb2, pb_resp_cls_name) pb_resp = pb_resp_cls() pb_resp.ParseFromString(api_response.response) try: yield pb_resp finally: resp.success() @contextmanager def rest(self, method, *, path_suffix, params=None, json=None): """ Provides simplified interface for sending REST requests to the TaskQueue service. Args: method: a str representing HTTP method. path_suffix: a str to use in URL: http://<HOST>/taskqueue/v1beta2/projects/<PROJECT>/taskqueues/<PATH_PREFIX>. params: a dict containing request parameters. json: an object to serialise as JSON body. Returns: an instance of Taskqueue.RESTResponse. """ url = f'/taskqueue/v1beta2/projects/{TEST_PROJECT}/taskqueues{path_suffix}' locust_wrapped_response = self.http_session.request( method, url, params=params, json=json, name=path_suffix, catch_response=True ) with locust_wrapped_response as resp: try: resp.raise_for_status() except RequestException as err: resp.failure(err) raise else: try: yield resp finally: resp.success()