def match(request, session, trace, system_date, url_args, hooks, module_system_date=None): """Returns the stats of a request match process :param request: source stubo request :param session: cached session payload associated with this request :param module_system_date: optional system date of an external module """ request_text = request.request_body() scenario_key = session['scenario'] session_name = session['session'] log.debug(u'match: request_text={0}'.format(request_text)) trace.info('system_date={0}, module_system_date={1}'.format( system_date, module_system_date)) stats = [] if 'stubs' not in session or not len(session['stubs']): if session.get('status') != 'playback': raise exception_response(400, title="session {0} not in playback mode for scenario " "{1}".format(session_name, scenario_key)) raise exception_response(500, title="no stubs found in session {0} for {1}, status={2}".format( session_name, scenario_key, session.get('status'))) stub_count = len(session['stubs']) trace.info(u'matching against {0} stubs'.format(stub_count)) for stub_number in range(stub_count): trace.info('stub ({0})'.format(stub_number)) stub = StubCache(session['stubs'][stub_number], scenario_key, session_name) source_stub = copy.deepcopy(stub) request_copy = copy.deepcopy(request) stub, request_copy = transform(stub, request_copy, module_system_date=module_system_date, system_date=system_date, function='get/response', cache=session.get('ext_cache'), hooks=hooks, stage='matcher', trace=trace, url_args=url_args) trace.info('finished transformation') if source_stub != stub: trace.diff('stub ({0}) was transformed'.format(stub_number), source_stub.payload, stub.payload) trace.info('stub ({0}) was transformed into'.format(stub_number), stub.payload) if request_copy != request: trace.diff('request was transformed', request_copy.request_body(), request.request_body()) trace.info('request was transformed into', request_copy.request_body()) matcher = StubMatcher(trace) if matcher.match(request_copy, stub): return (True, stub_number, stub) return (False,)
def get_response(handler, session_name): request = handler.request stubo_request = StuboRequest(request) request_body = stubo_request.request_body() if not request_body: # TODO: not an error if they match on other attrs raise exception_response(400, title='No text in body') cache = Cache(get_hostname(request)) if cache.blacklisted(): raise exception_response( 400, title="Sorry the host URL '{0}' has been " "blacklisted. Please contact Stub-O-Matic support.".format( cache.host)) scenario_key = cache.find_scenario_key(session_name) scenario_name = scenario_key.partition(':')[-1] handler.track.scenario = scenario_name request_id = compute_hash(request_body) module_system_date = handler.get_argument('system_date', None) url_args = handler.track.request_params if not module_system_date: # BA LEGACY module_system_date = handler.get_argument('stubbedSystemDate', None) trace_matcher = TrackTrace(handler.track, 'matcher') user_cache = handler.settings['ext_cache'] # check cached requests cached_request = cache.get_request(scenario_name, session_name, request_id) if cached_request: response_ids, delay_policy_name, recorded, system_date, module_info, request_index_key = cached_request else: retry_count = 5 if handler.settings.get('is_cluster', False) else 1 session, retries = cache.get_session_with_delay( scenario_name, session_name, retry_count=retry_count, retry_interval=1) if retries > 0: log.warn("replication was slow for session: {0} {1}, it took {2} "\ "secs!".format(scenario_key, session_name, retries+1)) if session['status'] != 'playback': raise exception_response( 500, title='cache status != playback. session={0}'.format(session)) system_date = session['system_date'] if not system_date: raise exception_response( 500, title="slave session {0} not available for scenario {1}". format(session_name, scenario_key)) session['ext_cache'] = user_cache results = match(stubo_request, session, trace_matcher, as_date(system_date), url_args=url_args, hooks=handler.settings['hooks'], module_system_date=module_system_date) # 0 is best match hits_info, stub = results[0] log.debug(u'match result: (hits_info={0}, stub={1})'.format( hits_info, stub.payload)) hits, stub_number = hits_info if not hits: raise exception_response(400, title='E017:No matching response found') response_ids = stub.response_ids() delay_policy_name = stub.delay_policy_name() recorded = stub.recorded() module_info = stub.module() request_index_key = add_request( session, request_id, stub, system_date, stub_number, handler.settings['request_cache_limit']) if not stub.response_body(): stub.set_response_body( stub.get_response_body_from_cache(request_index_key)) if delay_policy_name: stub.load_delay_from_cache(delay_policy_name) if cached_request: stub = StubCache({}, scenario_key, session_name) stub.load_from_cache(response_ids, delay_policy_name, recorded, system_date, module_info, request_index_key) trace_response = TrackTrace(handler.track, 'response') if module_info: trace_response.info('module used', str(module_info)) response_text = stub.response_body() if not response_text: raise exception_response( 500, title='Unable to find response in ' 'cache using session: {0}:{1}, response_ids: {2}'.format( scenario_key, session_name, response_ids)) # get latest delay policy delay_policy = stub.delay_policy() if delay_policy: delay = calculate_delay(delay_policy) if delay: msg = 'apply delay: {0} => {1}'.format(delay_policy, delay) log.debug(msg) handler.track['delay'] = delay trace_response.info(msg) trace_response.info('found response') module_system_date = as_date(module_system_date) if module_system_date \ else module_system_date stub, _ = transform(stub, stubo_request, module_system_date=module_system_date, system_date=as_date(system_date), function='get/response', cache=user_cache, hooks=handler.settings['hooks'], stage='response', trace=trace_response, url_args=url_args) transfomed_response_text = stub.response_body()[0] # Note transformed_response_text can be encoded in utf8 if response_text[0] != transfomed_response_text: trace_response.diff('response:transformed', dict(response=response_text[0]), dict(response=transfomed_response_text)) return transfomed_response_text
stub.set_module({ 'name': module_name, # TODO: is module['system_date'] used? 'system_date': today_str('%Y-%m-%d'), 'recorded_system_date': recorded_module_system_date or today_str('%Y-%m-%d') }) trace.info('module used', stub.module()) try: source_stub = copy.deepcopy(stub) stub, _ = transform(stub, stubo_request, function='put/stub', cache=handler.settings['ext_cache'], hooks=handler.settings['hooks'], stage='put/stub', trace=trace, url_args=url_args) if source_stub != stub: trace.diff('stub was transformed', source_stub.payload, stub.payload) trace.info('stub was transformed into', stub.payload) except UserExitModuleNotFound, e: # ignore legacy stubbedSystem param stub.payload.pop('module') scenario_name = session['scenario'] handler.track.scenario = scenario_name.partition(':')[2] session_status = session['status'] if session_status != 'record':
def match(request, session, trace, system_date, url_args, hooks, module_system_date=None): """Returns the stats of a request match process :param request: source stubo request :param session: cached session payload associated with this request :param module_system_date: optional system date of an external module """ request_text = request.request_body() scenario_key = session['scenario'] session_name = session['session'] log.debug(u'match: request_text={0}'.format(request_text)) trace.info('system_date={0}, module_system_date={1}'.format( system_date, module_system_date)) stats = [] if 'stubs' not in session or not len(session['stubs']): if session.get('status') != 'playback': raise exception_response(400, title="session {0} not in playback mode for scenario " "{1}".format(session_name, scenario_key)) raise exception_response(500, title="no stubs found in session {0} for {1}, status={2}".format( session_name, scenario_key, session.get('status'))) stub_count = len(session['stubs']) trace.info(u'matching against {0} stubs'.format(stub_count)) for stub_number in range(stub_count): trace.info('stub ({0})'.format(stub_number)) stub = StubCache(session['stubs'][stub_number], scenario_key, session_name) source_stub = copy.deepcopy(stub) request_copy = copy.deepcopy(request) stub, request_copy = transform(stub, request_copy, module_system_date=module_system_date, system_date=system_date, function='get/response', cache=session.get('ext_cache'), hooks=hooks, stage='matcher', trace=trace, url_args=url_args) trace.info('finished transformation') if source_stub != stub: trace.diff('stub ({0}) was transformed'.format(stub_number), source_stub.payload, stub.payload) trace.info('stub ({0}) was transformed into'.format(stub_number), stub.payload) if request_copy != request: trace.diff('request was transformed', request_copy.request_body(), request.request_body()) trace.info('request was transformed into', request_copy.request_body()) matcher = StubMatcher(trace) hits = matcher.match(request_copy, stub) stats.append(((hits, stub_number), stub)) if hits == stub.number_of_matchers(): # without most_matchers_win support trace.info(u"stub '{0}' matched".format(stub_number)) break # sort by hits (desc), stub_number (asc) # to match against 1. greatest hits or 2. first stub to get a hit return sorted(stats, key=lambda k: (k[0][0], -k[0][1]), reverse=True)
def get_response(handler, session_name): request = handler.request stubo_request = StuboRequest(request) cache = Cache(get_hostname(request)) if cache.blacklisted(): raise exception_response(400, title="Sorry the host URL '{0}' has been " "blacklisted. Please contact Stub-O-Matic support.".format(cache.host)) scenario_key = cache.find_scenario_key(session_name) scenario_name = scenario_key.partition(':')[-1] handler.track.scenario = scenario_name request_id = stubo_request.id() module_system_date = handler.get_argument('system_date', None) url_args = handler.track.request_params if not module_system_date: # LEGACY module_system_date = handler.get_argument('stubbedSystemDate', None) trace_matcher = TrackTrace(handler.track, 'matcher') user_cache = handler.settings['ext_cache'] # check cached requests cached_request = cache.get_request(scenario_name, session_name, request_id) if cached_request: response_ids, delay_policy_name, recorded, system_date, module_info, request_index_key = cached_request else: retry_count = 5 if handler.settings.get('is_cluster', False) else 1 session, retries = cache.get_session_with_delay(scenario_name, session_name, retry_count=retry_count, retry_interval=1) if retries > 0: log.warn("replication was slow for session: {0} {1}, it took {2} "\ "secs!".format(scenario_key, session_name, retries+1)) if session['status'] != 'playback': raise exception_response(500, title='cache status != playback. session={0}'.format(session)) system_date = session['system_date'] if not system_date: raise exception_response(500, title="slave session {0} not available for scenario {1}".format( session_name, scenario_key)) session['ext_cache'] = user_cache result = match(stubo_request, session, trace_matcher, as_date(system_date), url_args=url_args, hooks=handler.settings['hooks'], module_system_date=module_system_date) if not result[0]: raise exception_response(400, title='E017:No matching response found') _, stub_number, stub = result response_ids = stub.response_ids() delay_policy_name = stub.delay_policy_name() recorded = stub.recorded() module_info = stub.module() request_index_key = add_request(session, request_id, stub, system_date, stub_number, handler.settings['request_cache_limit']) if not stub.response_body(): _response = stub.get_response_from_cache(request_index_key) stub.set_response_body(_response['body']) if delay_policy_name: stub.load_delay_from_cache(delay_policy_name) if cached_request: stub = StubCache({}, scenario_key, session_name) stub.load_from_cache(response_ids, delay_policy_name, recorded, system_date, module_info, request_index_key) trace_response = TrackTrace(handler.track, 'response') if module_info: trace_response.info('module used', str(module_info)) response_text = stub.response_body() if not response_text: raise exception_response(500, title='Unable to find response in ' 'cache using session: {0}:{1}, response_ids: {2}'.format( scenario_key, session_name, response_ids)) # get latest delay policy delay_policy = stub.delay_policy() if delay_policy: delay = Delay.parse_args(delay_policy) if delay: delay = delay.calculate() msg = 'apply delay: {0} => {1}'.format(delay_policy, delay) log.debug(msg) handler.track['delay'] = delay trace_response.info(msg) trace_response.info('found response') module_system_date = as_date(module_system_date) if module_system_date \ else module_system_date stub, _ = transform(stub, stubo_request, module_system_date=module_system_date, system_date=as_date(system_date), function='get/response', cache=user_cache, hooks=handler.settings['hooks'], stage='response', trace=trace_response, url_args=url_args) transfomed_response_text = stub.response_body()[0] # Note transformed_response_text can be encoded in utf8 if response_text[0] != transfomed_response_text: trace_response.diff('response:transformed', dict(response=response_text[0]), dict(response=transfomed_response_text)) if stub.response_status() != 200: handler.set_status(stub.response_status()) if stub.response_headers(): for k, v in stub.response_headers().iteritems(): handler.set_header(k, v) return transfomed_response_text
raise exception_response(400, title='session not found - {0}'.format( session_name)) stub.set_recorded(recorded or today_str('%Y-%m-%d')) if module_name: stub.set_module({ 'name' : module_name, # TODO: is module['system_date'] used? 'system_date' : today_str('%Y-%m-%d'), 'recorded_system_date' : recorded_module_system_date or today_str( '%Y-%m-%d') }) trace.info('module used', stub.module()) source_stub = copy.deepcopy(stub) stub, _ = transform(stub, stubo_request, function='put/stub', cache=handler.settings['ext_cache'], hooks=handler.settings['hooks'], stage='put/stub', trace=trace, url_args=url_args) if source_stub != stub: trace.diff('stub was transformed', source_stub.payload, stub.payload) trace.info('stub was transformed into', stub.payload) scenario_name = session['scenario'] handler.track.scenario = scenario_name.partition(':')[2] session_status = session['status'] if session_status != 'record': raise exception_response(400, title='Scenario not in record ' 'mode - {0} in {1} mode.'.format(scenario_name, session_status)) doc = dict(scenario=scenario_name, stub=stub) scenario_col = Scenario()
def get_response(handler, session_name): # getting request value request = handler.request stubo_request = StuboRequest(request) cache = Cache(get_hostname(request)) scenario_key = cache.find_scenario_key(session_name) scenario_name = scenario_key.partition(':')[-1] handler.track.scenario = scenario_name # request_id - computed hash request_id = stubo_request.id() module_system_date = handler.get_argument('system_date', None) url_args = handler.track.request_params if not module_system_date: # LEGACY module_system_date = handler.get_argument('stubbedSystemDate', None) trace_matcher = TrackTrace(handler.track, 'matcher') user_cache = handler.settings['ext_cache'] # check cached requests cached_request = cache.get_request(scenario_name, session_name, request_id) if cached_request: response_ids, delay_policy_name, recorded, system_date, module_info, request_index_key = cached_request else: retry_count = 5 if handler.settings.get('is_cluster', False) else 1 session, retries = cache.get_session_with_delay( scenario_name, session_name, retry_count=retry_count, retry_interval=1) if retries > 0: log.warn( "replication was slow for session: {0} {1}, it took {2} secs!". format(scenario_key, session_name, retries + 1)) if session['status'] != 'playback': raise exception_response( 500, title='cache status != playback. session={0}'.format(session)) system_date = session['system_date'] if not system_date: raise exception_response( 500, title="slave session {0} not available for scenario {1}". format(session_name, scenario_key)) session['ext_cache'] = user_cache result = match(stubo_request, session, trace_matcher, as_date(system_date), url_args=url_args, hooks=handler.settings['hooks'], module_system_date=module_system_date) if not result[0]: raise exception_response(400, title='E017:No matching response found') _, stub_number, stub = result response_ids = stub.response_ids() delay_policy_name = stub.delay_policy_name() recorded = stub.recorded() module_info = stub.module() request_index_key = add_request( session, request_id, stub, system_date, stub_number, handler.settings['request_cache_limit']) if not stub.response_body(): _response = stub.get_response_from_cache(request_index_key) stub.set_response_body(_response['body']) if delay_policy_name: stub.load_delay_from_cache(delay_policy_name) if cached_request: stub = StubCache({}, scenario_key, session_name) stub.load_from_cache(response_ids, delay_policy_name, recorded, system_date, module_info, request_index_key) trace_response = TrackTrace(handler.track, 'response') if module_info: trace_response.info('module used', str(module_info)) response_text = stub.response_body() if not response_text: raise exception_response( 500, title='Unable to find response in cache using session: {0}:{1}, ' 'response_ids: {2}'.format(scenario_key, session_name, response_ids)) # get latest delay policy delay_policy = stub.delay_policy() if delay_policy: delay = Delay.parse_args(delay_policy) if delay: delay = delay.calculate() msg = 'apply delay: {0} => {1}'.format(delay_policy, delay) log.debug(msg) handler.track['delay'] = delay trace_response.info(msg) trace_response.info('found response') module_system_date = as_date(module_system_date) if module_system_date \ else module_system_date stub, _ = transform(stub, stubo_request, module_system_date=module_system_date, system_date=as_date(system_date), function='get/response', cache=user_cache, hooks=handler.settings['hooks'], stage='response', trace=trace_response, url_args=url_args) transfomed_response_text = stub.response_body()[0] # Note transformed_response_text can be encoded in utf8 if response_text[0] != transfomed_response_text: trace_response.diff('response:transformed', dict(response=response_text[0]), dict(response=transfomed_response_text)) if stub.response_status() != 200: handler.set_status(stub.response_status()) if stub.response_headers(): for k, v in stub.response_headers().iteritems(): handler.set_header(k, v) return transfomed_response_text
def get_response_v2(handler, full_scenario_name, session_name): # main result dictionary that will be returned result_dict = {} request = handler.request stubo_request = StuboRequest(request) cache = Cache(get_hostname(request)) scenario_name = full_scenario_name.partition(':')[-1] handler.track.scenario = scenario_name request_id = stubo_request.id() module_system_date = handler.get_argument('system_date', None) url_args = handler.track.request_params # trace_matcher = TrackTrace(handler.track, 'matcher') user_cache = handler.settings['ext_cache'] # check cached requests cached_request = cache.get_request(scenario_name, session_name, request_id) if cached_request: response_ids, delay_policy_name, recorded, system_date, module_info, request_index_key = cached_request else: retry_count = 5 if handler.settings.get('is_cluster', False) else 1 session, retries = cache.get_session_with_delay( scenario_name, session_name, retry_count=retry_count, retry_interval=1) if retries > 0: log.warn( "replication was slow for session: {0} {1}, it took {2} secs!". format(full_scenario_name, session_name, retries + 1)) if session['status'] != 'playback': result_dict[ "error"] = 'cache status != playback. session={0}'.format( session) result_dict["statusCode"] = 412 return result_dict system_date = session['system_date'] if not system_date: result_dict[ "error"] = "slave session {0} not available for scenario {1}".format( session_name, full_scenario_name) result_dict["statusCode"] = 412 return result_dict trace_matcher = TrackTrace(handler.track, 'matcher') session['ext_cache'] = user_cache result = match(stubo_request, session, trace_matcher, as_date(system_date), url_args=url_args, hooks=handler.settings['hooks'], module_system_date=module_system_date) # matching request not found if not result[0]: result_dict["error"] = "Not matching request found" result_dict["statusCode"] = 404 return result_dict _, stub_number, stub = result response_ids = stub.response_ids() delay_policy_name = stub.delay_policy_name() recorded = stub.recorded() module_info = stub.module() request_index_key = add_request( session, request_id, stub, system_date, stub_number, handler.settings['request_cache_limit']) if not stub.response_body(): _response = stub.get_response_from_cache(request_index_key) stub.set_response_body(_response['body']) if delay_policy_name: stub.load_delay_from_cache(delay_policy_name) if cached_request: stub = StubCache({}, full_scenario_name, session_name) stub.load_from_cache(response_ids, delay_policy_name, recorded, system_date, module_info, request_index_key) trace_response = TrackTrace(handler.track, 'response') if module_info: trace_response.info('module used', str(module_info)) response_text = stub.response_body() if not response_text: result_dict[ "error"] = 'Unable to find response in cache using session: {0}:{1}, ' 'response_ids: {2}'.format(full_scenario_name, session_name, response_ids) result_dict["statusCode"] = 400 return result_dict # get latest delay policy delay_policy = stub.delay_policy() if delay_policy: delay = Delay.parse_args(delay_policy) if delay: delay = delay.calculate() msg = 'apply delay: {0} => {1}'.format(delay_policy, delay) log.debug(msg) handler.track['delay'] = delay trace_response.info(msg) trace_response.info('found response') module_system_date = as_date(module_system_date) if module_system_date \ else module_system_date stub, _ = transform(stub, stubo_request, module_system_date=module_system_date, system_date=as_date(system_date), function='get/response', cache=user_cache, hooks=handler.settings['hooks'], stage='response', trace=trace_response, url_args=url_args) transfomed_response_text = stub.response_body()[0] # Note transformed_response_text can be encoded in utf8 if response_text[0] != transfomed_response_text: trace_response.diff('response:transformed', dict(response=response_text[0]), dict(response=transfomed_response_text)) result_dict["body"] = transfomed_response_text result_dict["headers"] = stub.response_headers() result_dict["statusCode"] = stub.response_status() return result_dict