Skip to content

Commit

Permalink
Mock ssr add jsonpath to get part of mock data; Reporter error when s…
Browse files Browse the repository at this point in the history
…erver not init; Extra mock server add client address; jsonpath support return one result (#778)
  • Loading branch information
yumiguan authored Aug 23, 2023
1 parent 9119e0b commit 121b2be
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 26 deletions.
1 change: 1 addition & 0 deletions lyrebird/config/keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY = 'mock.request.ssr.mock_in_body'
CONFIG_MOCK_REQUEST_SSR_MOCK_BODY_KEY = 'mock.request.ssr.mock_body_key'
CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY_PARAM = 'mock.request.ssr.mock_in_body.param'
CONFIG_MOCK_REQUEST_SSR_MOCK_DATA_JSONPATH = 'mock.request.ssr.mock_data_jsonpath'

11 changes: 6 additions & 5 deletions lyrebird/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,12 @@ def publish(self, channel, message, state=False, *args, **kwargs):
context.application.socket_io.emit('event', {'id': event_id, 'channel': channel})

# Send report
application.reporter.report({
'action': 'event',
'channel': channel,
'event': message
})
if application.reporter:
application.reporter.report({
'action': 'event',
'channel': channel,
'event': message
})

logger.debug(f'channel={channel} state={state}\nmessage:\n-----------\n{message}\n-----------\n')

Expand Down
8 changes: 8 additions & 0 deletions lyrebird/mock/dm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,14 @@ def add_data(self, parent_id, raw_data, **kwargs):

return _data_id

def _flow_str_2_data(self, data_str):
if not isinstance(data_str, str):
return data_str
try:
return json.loads(data_str)
except Exception:
return data_str

def _flow_data_2_str(self, data):
if isinstance(data, str):
return data
Expand Down
4 changes: 3 additions & 1 deletion lyrebird/mock/dm/jsonpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class JSONPath:

@staticmethod
def search(root, path:str):
def search(root, path:str, find_one=False):
""" Find JSON object in object (a ``list`` or ``dict`` JSON object) file by JSONPath
``root`` <list> or <dict> an object containing data
Expand Down Expand Up @@ -44,6 +44,8 @@ def search(root, path:str):

result = []
JSONPath._search_iterator(root, keys, result)
if find_one:
return result[0].node if result else None
return result

@staticmethod
Expand Down
1 change: 1 addition & 0 deletions lyrebird/mock/extra_mock_server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async def send_request(context: LyrebirdProxyContext, target_url):
headers = {k: v for k, v in request.headers.items() if k.lower() not in [
'cache-control', 'host', 'transfer-encoding']}
headers['Proxy-Raw-Headers'] = make_raw_headers_line(request)
headers['Lyrebird-Client-Address'] = request.remote
request_body = None
if request.body_exists:
request_body = request.content
Expand Down
2 changes: 2 additions & 0 deletions lyrebird/mock/handlers/handler_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ def _parse_request(self):
DataHelper.origin2flow(self.request, output=_request, chain=self.request_chain)

if self.request.headers.get('Lyrebird-Client-Address'):
# from extra mock server and mitmproxy
self.client_address = self.request.headers.get('Lyrebird-Client-Address')
else:
# from origin mock server
self.client_address = self.request.remote_addr
self.flow['client_address'] = self.client_address

Expand Down
67 changes: 47 additions & 20 deletions lyrebird/mock/handlers/mock_handler.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from pathlib import Path
from lyrebird.mock.dm.jsonpath import jsonpath
import json
from lyrebird.mock import context
from lyrebird.log import get_logger
from .mock_data_helper import MockDataHelper
from lyrebird.application import config
from lyrebird.config import CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY, CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY_PARAM, CONFIG_MOCK_REQUEST_SSR_MOCK_BODY_KEY
from lyrebird.config import CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY, CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY_PARAM, CONFIG_MOCK_REQUEST_SSR_MOCK_BODY_KEY, CONFIG_MOCK_REQUEST_SSR_MOCK_DATA_JSONPATH


logger = get_logger()
Expand All @@ -15,6 +17,22 @@ class MockHandler:
"""

@staticmethod
def is_handle_ssr(handler_context):
if not config.get(CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY):
return False

key = config.get(CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY_PARAM, 'is_ssr')
is_open_ssr = handler_context.flow['request']['query'].get(key)
if not is_open_ssr:
return False

if 'data' in handler_context.flow['request'] and not isinstance(handler_context.flow['request']['data'], dict):
logger.warning('ssr but request body type is not Object')
return False

return True

def handle(self, handler_context):
hit_datas = context.application.data_manager.get_matched_data(handler_context.flow)
if len(hit_datas) <= 0:
Expand All @@ -25,31 +43,40 @@ def handle(self, handler_context):

activated_groups = context.application.data_manager.activated_group
activated_group = list(activated_groups.values())[0]
logger.info(
f'<Mock> Hit Group:{activated_group.get("name")} - Data:{hit_data["name"]} \nURL: {handler_context.flow["request"]["url"]}\nGroupID:{activated_group["id"]} DataID:{hit_data["id"]}')

if config.get(CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY):
key = config.get(CONFIG_MOCK_REQUEST_SSR_MOCK_IN_BODY_PARAM, 'is_ssr')
is_open_ssr = handler_context.flow['request']['query'].get(key)
if is_open_ssr:
if 'data' not in handler_context.flow['request']:
handler_context.flow['request']['data'] = {}
is_ssr = MockHandler.is_handle_ssr(handler_context)
if is_ssr:
logger.info(
f'<Mock> <SSR> Hit Group:{activated_group.get("name")} - Data:{hit_data["name"]} \nURL: {handler_context.flow["request"]["url"]}\nGroupID:{activated_group["id"]} DataID:{hit_data["id"]}')

resp_key = config.get(CONFIG_MOCK_REQUEST_SSR_MOCK_BODY_KEY, 'lyrebird_mock_response')
request_data_update = {}

handler_context.flow['request']['data'][resp_key] = hit_data['response'].get('data', '')
resp_key = config.get(CONFIG_MOCK_REQUEST_SSR_MOCK_BODY_KEY, 'lyrebird_mock_response')
request_data_update[resp_key] = hit_data['response'].get('data', '')

handler_context.set_request_edited()
handler_context.flow['request']['headers']['lyrebird'] = 'mock'
resp_jsonpath = config.get(CONFIG_MOCK_REQUEST_SSR_MOCK_DATA_JSONPATH)
if resp_jsonpath:
request_data_update[resp_key] = context.application.data_manager._flow_str_2_data(request_data_update[resp_key])
target_response_data = jsonpath.search(request_data_update[resp_key], resp_jsonpath, find_one=True)
request_data_update[resp_key] = context.application.data_manager._flow_data_2_str(target_response_data)

handler_context.add_flow_action({
'id': 'mock_ssr',
'name': Path(__file__).name,
'group_id': activated_group['id'],
'mock_id': hit_data['id']
})
return
if 'data' not in handler_context.flow['request']:
handler_context.flow['request']['data'] = {}
handler_context.flow['request']['data'].update(request_data_update)

handler_context.set_request_edited()
handler_context.flow['request']['headers']['lyrebird'] = 'mock'

handler_context.add_flow_action({
'id': 'mock_ssr',
'name': Path(__file__).name,
'group_id': activated_group['id'],
'mock_id': hit_data['id']
})
return

logger.info(
f'<Mock> Hit Group:{activated_group.get("name")} - Data:{hit_data["name"]} \nURL: {handler_context.flow["request"]["url"]}\nGroupID:{activated_group["id"]} DataID:{hit_data["id"]}')
handler_context.flow['response']['code'] = hit_data['response']['code']
handler_context.flow['response']['headers'] = {k:v for k,v in hit_data['response']['headers'].items()}
handler_context.flow['response']['data'] = hit_data['response'].get('data', '')
Expand Down
1 change: 1 addition & 0 deletions lyrebird/plugins/plugin_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def load_all_from_ep():
logger.error(f'Load plugin {ep.name} failed: {ep.dist}\n{e}\n{traceback.format_exc()}')
continue
plugins[plugin.project_name] = plugin
logger.info(f'Load plugin from ep success: {plugin.project_name}')
return plugins


Expand Down
1 change: 1 addition & 0 deletions lyrebird/plugins/plugin_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def reload(self):
for plugin_path in self.plugin_path_list:
try:
plugin = plugin_loader.load_from_path(plugin_path)
logger.info(f'Load plugin from path success: {plugin.project_name}')
except:
logger.error(f'Load plugin failed. Skip plugin : {plugin_path}\n{traceback.format_exc()}')
continue
Expand Down

0 comments on commit 121b2be

Please sign in to comment.