新增工具‘HTTP请求头管理器’,支持设置HTTP请求头数据

This commit is contained in:
azhengzz 2021-03-26 20:57:24 +08:00
parent 17eb6f7b70
commit 3db0ae1b24
19 changed files with 732 additions and 8 deletions

View File

@ -6,6 +6,7 @@ from app.cores.logger import DispatcherLogger
from app.cores.dictionaries import DISPATCHER_TYPE, REPORT_RESULT
from app.cores.dispatcher import AbstractCaseDispatcher
from app.cores.case.http.request_util import handle_url
from app.cores.case.http.http_request_header_pool_manager import HTTPRequestHeaderPoolManager
from app.cores.case.base.script import exec_postprocessor_script, exec_preprocessor_script
from app.cores.case.base.last_result import LastResult
from app.cores.case.base.expectation import get_expectations_result
@ -39,6 +40,8 @@ class HTTPCaseDispatcher(AbstractCaseDispatcher):
# cookie数据
self.rcj = None
# http请求头
self.headers = None
# http请求字段
self.protocol = None
@ -59,6 +62,8 @@ class HTTPCaseDispatcher(AbstractCaseDispatcher):
super().set_up()
# 获取cookie
self.rcj = http_cookie_manager.get_request_cookie_jar(type=self.dispatcher_type)
# 获取HTTP请求头
self.headers = HTTPRequestHeaderPoolManager.get_http_request_header(project_id=self.case.scene.module.project.id)
# 预处理脚本执行
preprocessor_script = self.case.specific_case.preprocessor_script_
exec_preprocessor_script(
@ -96,7 +101,8 @@ class HTTPCaseDispatcher(AbstractCaseDispatcher):
message_body=self.message_body,
cookies=self.rcj,
file_upload=self.file_upload,
content_type=self.content_type)
content_type=self.content_type,
headers=self.headers)
self.request_.send()
def tear_down(self):

View File

@ -0,0 +1,115 @@
# coding=utf-8
from typing import Dict
from flask import session
from app.extensions import session_id_manager
from app.cores.dictionaries import DISPATCHER_TRIGGER_TYPE
class HTTPRequestHeaderPoolManager:
"""
HTTPRequestHeaderPool = {
session_id: {
project_id: {
key: value,
key1: value1,
...
},
project_id2: {
...
}
},
session_id2:{
...
},
...
}
ScheduleHTTPRequestHeaderPool = {
project_id: {
key: value,
key1: value1,
...
},
project_id2: {
...
},
...
}
"""
# HTTP请求头数据池
HTTPRequestHeaderPool = {}
# 定时任务HTTP请求头数据池
ScheduleHTTPRequestHeaderPool = {}
@classmethod
def get_http_request_header(cls, project_id):
"""
获取项目中HTTP请求头数据
:param project_id: 项目id
:type project_id: int
:return: 项目定义的HTTP请求头数据
:rtype: Dict
"""
cls._set_default_http_request_header(project_id=project_id)
if session.get('dispatcher_trigger_type') == DISPATCHER_TRIGGER_TYPE.BY_SCHEDULE:
project_id = session.get('project_id')
if project_id:
return cls.ScheduleHTTPRequestHeaderPool.get(project_id)
else:
session_id = session_id_manager.get_session_id()
return cls.HTTPRequestHeaderPool.get(session_id).get(project_id)
@classmethod
def set_http_request_header(cls, project_id, key, value):
"""
设置HTTP请求头
:param project_id: 项目id
:type project_id: int
:param key: 变量名
:type key: str
:param value: 变量值
:type value: str
"""
cls._set_default_http_request_header(project_id=project_id)
if session.get('dispatcher_trigger_type') == DISPATCHER_TRIGGER_TYPE.BY_SCHEDULE:
project_id = session.get('project_id')
if project_id:
cls.ScheduleHTTPRequestHeaderPool.get(project_id).update({
key: value
})
else:
session_id = session_id_manager.get_session_id()
cls.HTTPRequestHeaderPool.get(session_id).get(project_id).update({
key: value
})
@classmethod
def _set_default_http_request_header(cls, project_id):
"""当RequestHeaderPool为空时为其设置默认值避免取出值为None"""
if session.get('dispatcher_trigger_type') == DISPATCHER_TRIGGER_TYPE.BY_SCHEDULE:
project_id = session.get('project_id')
if project_id:
project_var = cls.ScheduleHTTPRequestHeaderPool.get(project_id)
if project_var is None:
cls.ScheduleHTTPRequestHeaderPool.update({
project_id: {}
})
else:
session_id = session_id_manager.get_session_id()
session_var = cls.HTTPRequestHeaderPool.get(session_id)
if session_var is None:
cls.HTTPRequestHeaderPool.update({
session_id: {
project_id: {}
}
})
else:
project_var = cls.HTTPRequestHeaderPool.get(session_id).get(project_id)
if project_var is None:
cls.HTTPRequestHeaderPool.get(session_id).update({
project_id: {}
})

View File

@ -211,7 +211,6 @@ def make_request(method, url, *, parameters=None, content_type=None, message_bod
:rtype: HTTPRequest
"""
headers = kwargs.get('headers', {})
# 选择适当的参数数据, 如果parameters没有数据则取message_body作为入参数据
params = []
if (parameters is not None) and (len(parameters) > 0):
@ -222,6 +221,7 @@ def make_request(method, url, *, parameters=None, content_type=None, message_bod
if method.lower() == 'get':
return Get(url=url, params=handle_params(params), **kwargs)
if method.lower() == 'post':
headers = kwargs.pop('headers', {})
files = handle_file_upload(file_upload) if file_upload else None
if content_type == CONTENT_TYPE.FORM_DATA:
data = MultipartEncoder(handle_data(params, content_type=CONTENT_TYPE.FORM_DATA))

View File

@ -101,6 +101,7 @@ class TOOL_TYPE:
TIMER = 'TIMER'
VARIABLE_DEFINITION = 'VARIABLE_DEFINITION'
SCRIPT = 'SCRIPT'
HTTP_REQUEST_HEADER_MANAGER = 'HTTP_REQUEST_HEADER_MANAGER'
class CONTENT_TYPE:

View File

@ -867,7 +867,8 @@ class SceneDispatcher(AbstractSceneDispatcher):
"""
if tool.status in [STATUS.NORMAL] and tool.tool_type in [TOOL_TYPE.TIMER,
TOOL_TYPE.SCRIPT,
TOOL_TYPE.VARIABLE_DEFINITION]:
TOOL_TYPE.VARIABLE_DEFINITION,
TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER]:
# ReportToolData表数据字段
report_id = self.dispatcher.report.id
try:
@ -884,6 +885,11 @@ class SceneDispatcher(AbstractSceneDispatcher):
from app.cores.tool.dispatcher import VariableDefinitionToolDispatcher
VariableDefinitionToolDispatcher(tool=tool, dispatcher_type=DISPATCHER_TYPE.BUILD,
logger=self.dispatcher_logger, dispatcher=self.dispatcher).run()
elif tool.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
from app.cores.tool.dispatcher import HTTPRequestHeaderManagerToolDispatcher
HTTPRequestHeaderManagerToolDispatcher(tool=tool, dispatcher_type=DISPATCHER_TYPE.BUILD,
logger=self.dispatcher_logger,
dispatcher=self.dispatcher).run()
finally:
# 工具增加调度子数据
dispatcher_detail_id = DispatcherDetail.add(element_type=ELEMENT_TYPE.TOOL, element_id=tool.id,

View File

@ -5,6 +5,7 @@ from app.cores.dispatcher import AbstractToolDispatcher
from app.cores.tool.script import Script
from app.cores.tool.timer import Timer
from app.cores.tool.variable_definition import VariableDefinition
from app.cores.tool.http_request_header_manager import HTTPRequestHeaderManager
class ScriptToolDispatcher(AbstractToolDispatcher):
@ -95,3 +96,31 @@ class VariableDefinitionToolDispatcher(AbstractToolDispatcher):
def run(self):
super().run()
class HTTPRequestHeaderManagerToolDispatcher(AbstractToolDispatcher):
def __init__(self, tool, dispatcher_type=DISPATCHER_TYPE.BUILD, logger=None, dispatcher=None):
"""
:param tool: 单个HTTPRequestHeaderManager Tool工具组件
:type tool: Tool
:param dispatcher_type: 标识构建是通过单独组件调试(DISPATCHER_TYPE.DEBUG)还是通过模块/项目构建测试(DISPATCHER_TYPE.BUILD)
:type dispatcher_type: str
:param logger: 当dispatcher_type为DISPATCHER_TYPE.BUILD时需要传入调度日志
:type logger: DispatcherLogger
:param dispatcher: 当dispatcher_type为DISPATCHER_TYPE.BUILD时需要传入调度数据
:type dispatcher: Dispatcher
"""
super().__init__(tool=tool, dispatcher_type=dispatcher_type, logger=logger, dispatcher=dispatcher)
def set_up(self):
super().set_up()
def execute(self):
super().execute()
HTTPRequestHeaderManager(tool=self.tool, dispatcher_logger=self.dispatcher_logger).exec_tool()
def tear_down(self):
super().tear_down()
def run(self):
super().run()

View File

@ -0,0 +1,30 @@
# coding=utf-8
from flask import session
from app.cores.case.http.http_request_header_pool_manager import HTTPRequestHeaderPoolManager
class HTTPRequestHeaderManager:
def __init__(self, tool, dispatcher_logger, project_id=None):
"""
初始化HTTP请求头工具对象
:param tool: 工具
:type tool: Tool
:param dispatcher_logger: 日志
:type dispatcher_logger: DispatcherLogger
:param project_id: 工具所在项目id
:type project_id: int
"""
self.http_request_header_manager_tool = tool.specific_tool
self.dispatcher_logger = dispatcher_logger
if project_id is None:
self.project_id = session.get('project_id')
else:
self.project_id = project_id
def exec_tool(self):
self.dispatcher_logger.logger.info('[HTTP请求头管理器][执行]')
variables = HTTPRequestHeaderPoolManager.get_http_request_header(project_id=self.project_id)
for row in self.http_request_header_manager_tool.http_request_header_manager_list:
variables[row.name_] = row.value_

View File

@ -979,6 +979,8 @@ class Tool(db.Model):
return ScriptTool.query.filter_by(tool_id=self.id).first()
if self.tool_type == TOOL_TYPE.VARIABLE_DEFINITION:
return VariableDefinitionTool.query.filter_by(tool_id=self.id).first()
if self.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
return HTTPRequestHeaderManagerTool.query.filter_by(tool_id=self.id).first()
@classmethod
def exist_and_status_not_delete(cls, tool_id) -> bool:
@ -1023,6 +1025,9 @@ class Tool(db.Model):
elif tool_type == TOOL_TYPE.VARIABLE_DEFINITION:
specific_tool = VariableDefinitionTool.new_tool()
specific_tool.tool = tool
elif tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
specific_tool = HTTPRequestHeaderManagerTool.new_tool()
specific_tool.tool = tool
else:
raise ValueError('不支持当前tool_type类型, tool_type=%s' % tool_type)
db.session.add(specific_tool)
@ -1358,6 +1363,10 @@ class VariableDefinitionList(db.Model):
value = db.Column(db.String(512), nullable=False, default='', server_default='')
description = db.Column(db.Text, nullable=False, default='', server_default='')
# relationship
variable_definition_tool_id = db.Column(db.Integer, db.ForeignKey('variable_definition_tool.id'))
variable_definition_tool = db.relationship('VariableDefinitionTool', back_populates='variable_definition_list')
@property
def name_(self):
return _p(self.name)
@ -1366,9 +1375,149 @@ class VariableDefinitionList(db.Model):
def value_(self):
return _p(self.value)
class HTTPRequestHeaderManagerTool(db.Model):
"""
关系说明
tool: HTTP请求头对应的工具对象 HTTPRequestHeaderManagerTool:Tool is 1:1
http_request_header_manager_list: HTTP请求头工具所包含的所有变量与值数据 HTTPRequestHeaderManagerTool:HTTPRequestHeaderManagerList is 1:N
"""
id = db.Column(db.Integer, primary_key=True)
# relationship
variable_definition_tool_id = db.Column(db.Integer, db.ForeignKey('variable_definition_tool.id'))
variable_definition_tool = db.relationship('VariableDefinitionTool', back_populates='variable_definition_list')
tool_id = db.Column(db.Integer, db.ForeignKey('tool.id'))
tool = db.relationship('Tool')
http_request_header_manager_list = db.relationship('HTTPRequestHeaderManagerList',
back_populates='http_request_header_manager_tool',
cascade='all, delete-orphan')
@property
def variables(self):
return [{
'name': row.name,
'value': row.value,
'description': row.description,
} for row in self.http_request_header_manager_list]
@classmethod
def new_tool(cls):
"""新增默认"""
http_request_header_manager_tool = cls()
http_request_header_manager_tool.http_request_header_manager_list = []
http_request_header_manager_tool.http_request_header_manager_list.append(
HTTPRequestHeaderManagerList(name='header_name', value='header_value', description='')
)
db.session.add(http_request_header_manager_tool)
db.session.commit()
return http_request_header_manager_tool
@classmethod
def update(cls, name, description, tool_id, variables):
"""
更新工具数据
:param tool_id: 工具编号
:type tool_id: int
:param name: 名称
:type name: str
:param description: 注释
:type description: str
:param variables: 请求头键值对列表
:type variables: List[Mapping[str, str]]
"""
tool = Tool.query.filter_by(id=tool_id).first()
if tool:
tool.name = name
tool.description = description
http_request_header_manager_tool = tool.specific_tool
http_request_header_manager_tool.http_request_header_manager_list = []
for var in variables:
http_request_header_manager_tool.http_request_header_manager_list.append(
HTTPRequestHeaderManagerList(name=var.get('name', ''),
value=var.get('value', ''),
description=var.get('description', ''))
)
db.session.commit()
@classmethod
def add(cls, name, description, variables, status=STATUS.NORMAL):
"""
新增一条工具数据
:param name: 名称
:type name: str
:param description: 注释
:type description: str
:param variables: 请求头键值对
:type variables: List[Mapping[str, str]]
:param status: 案例状态删除 正常
:type status: str
"""
tool = Tool(
name=name,
description=description,
status=status,
tool_type=TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER,
)
http_request_header_manager_tool = cls()
http_request_header_manager_tool.http_request_header_manager_list = []
for var in variables:
http_request_header_manager_tool.http_request_header_manager_list.append(
HTTPRequestHeaderManagerList(name=var.get('name', ''),
value=var.get('value', ''),
description=var.get('description', ''))
)
http_request_header_manager_tool.tool = tool
db.session.add(tool)
db.session.add(http_request_header_manager_tool)
db.session.commit()
return http_request_header_manager_tool
def copy_from_self(self):
"""
复制一个新的工具
:return: 新的工具
:rtype: Tool
"""
# 先获取变量键值对数据
copy_tool = self.add(
# Tool
name='Copy' + self.tool.name,
description=self.tool.description,
status=self.tool.status,
# HTTPRequestHeaderManagerTool
variables=self.variables,
)
return copy_tool
class HTTPRequestHeaderManagerList(db.Model):
"""
字段说明
name: 名称
value:
description: 注释
关系说明
http_request_header_manager_tool: HTTP请求头数据列表对应的HTTP请求头管理工具对象 HTTPRequestHeaderManagerList:HTTPRequestHeaderManagerTool is N:1
"""
# 需要转换为json数据格式的字段
render_field_list = ['name', 'value', 'description']
# filed
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(512), nullable=False, default='', server_default='')
value = db.Column(db.String(512), nullable=False, default='', server_default='')
description = db.Column(db.Text, nullable=False, default='', server_default='')
# relationship
http_request_header_manager_tool_id = db.Column(db.Integer, db.ForeignKey('http_request_header_manager_tool.id'))
http_request_header_manager_tool = db.relationship('HTTPRequestHeaderManagerTool',
back_populates='http_request_header_manager_list')
@property
def name_(self):
return _p(self.name)
@property
def value_(self):
return _p(self.value)
class Case(db.Model):
@ -2983,6 +3132,10 @@ class ReportToolData(db.Model):
back_populates='report_tool_data',
uselist=False,
cascade='all, delete-orphan')
report_http_request_header_manager_tool_data = db.relationship('ReportHTTPRequestHeaderManagerToolData',
back_populates='report_tool_data',
uselist=False,
cascade='all, delete-orphan')
@classmethod
def add(cls, tool, report_id, dispatcher_detail_id):
@ -2996,6 +3149,9 @@ class ReportToolData(db.Model):
ReportScriptToolData.add(script=tool.specific_tool.script, report_tool_data_id=report_tool_data.id)
elif tool.tool_type == TOOL_TYPE.VARIABLE_DEFINITION:
ReportVariableDefinitionToolData.add(variables=tool.specific_tool.variables, report_tool_data_id=report_tool_data.id)
elif tool.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
ReportHTTPRequestHeaderManagerToolData.add(variables=tool.specific_tool.variables,
report_tool_data_id=report_tool_data.id)
return report_tool_data
@ -3076,6 +3232,53 @@ class ReportVariableDefinitionToolListData(db.Model):
back_populates='report_variable_definition_tool_data_list')
class ReportHTTPRequestHeaderManagerToolData(db.Model):
# field
id = db.Column(db.Integer, primary_key=True)
# relationship
report_tool_data_id = db.Column(db.Integer, db.ForeignKey('report_tool_data.id'))
report_tool_data = db.relationship('ReportToolData', back_populates='report_http_request_header_manager_tool_data')
report_http_request_header_manager_tool_list_data = db.relationship('ReportHTTPRequestHeaderManagerToolListData',
back_populates='report_http_request_header_manager_tool_data',
cascade='all, delete-orphan')
@property
def variables(self):
return [{
'name': row.name,
'value': row.value,
'description': row.description,
} for row in self.report_http_request_header_manager_tool_list_data]
@classmethod
def add(cls, variables, report_tool_data_id):
report_http_request_header_manager_tool_data = ReportHTTPRequestHeaderManagerToolData(report_tool_data_id=report_tool_data_id)
db.session.add(report_http_request_header_manager_tool_data)
db.session.commit() # commit后report_http_request_header_manager_tool_data.id才有值否则为None
for variable in variables:
db.session.add(ReportHTTPRequestHeaderManagerToolListData(
name=variable.get('name', ''),
value=variable.get('value', ''),
description=variable.get('description', ''),
report_http_request_header_manager_tool_data_id=report_http_request_header_manager_tool_data.id,
))
db.session.commit()
class ReportHTTPRequestHeaderManagerToolListData(db.Model):
# field
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(512), nullable=False, default='', server_default='')
value = db.Column(db.String(512), nullable=False, default='', server_default='')
description = db.Column(db.Text, nullable=False, default='', server_default='')
# relationship
report_http_request_header_manager_tool_data_id = db.Column(db.Integer, db.ForeignKey('report_http_request_header_manager_tool_data.id'))
report_http_request_header_manager_tool_data = db.relationship('ReportHTTPRequestHeaderManagerToolData',
back_populates='report_http_request_header_manager_tool_list_data')
class Scheduler(db.Model):
"""
调度定时任务

View File

@ -19,7 +19,7 @@ from app.utils.util import get_form_from_request, exception_handle
from app.models import Case, Project, Module, Scene, HTTPCase, SSHCase, SQLCase, Dispatcher, DispatcherDetail, Report, \
SubElementInLogicController, LogicController, IfController, WhileController, LoopController, SimpleController, \
Scheduler, DingTalkRobotSetting, DingTalkRobotSettingAssociationProject, DebugCase, Tool, TimerTool, ScriptTool, \
VariableDefinitionTool, EmailReceiverSetting, EmailReceiverSettingAssociationProject
VariableDefinitionTool, EmailReceiverSetting, EmailReceiverSettingAssociationProject, HTTPRequestHeaderManagerTool
from app.template_global import render_to_json
from app.extensions import http_cookie_manager, dispatcher_scheduler
from app.template_global import sort_by_order_in_project, sort_by_order_in_module, sort_by_order_in_logic_controller
@ -761,6 +761,39 @@ def save_variable_definition_tool():
})
@bp.route('/tool/http_request_header_manager/save', methods=['POST'])
@login_required
def save_http_request_header_manager_tool():
# 参数校验
exist, form_tool_id = get_form_from_request(request, 'tool_id')
if not exist: return form_tool_id
exist, form_tool_name = get_form_from_request(request, 'tool_name')
if not exist: return form_tool_name
exist, form_tool_description = get_form_from_request(request, 'tool_description')
if not exist: return form_tool_description
exist, form_vars = get_form_from_request(request, 'vars')
if not exist: return form_vars
try:
variables = json.loads(form_vars)
HTTPRequestHeaderManagerTool.update(
tool_id=form_tool_id,
name=form_tool_name,
description=form_tool_description,
variables=variables,
)
except Exception as e:
exception_handle(current_app, e)
return jsonify({
'error_no': -1,
'error_msg': '错误信息 [' + repr(e) + ']',
})
else:
return jsonify({
'error_no': 0,
'error_msg': '',
})
@bp.route('/tool/script/run', methods=['POST'])
@login_required
def run_script_tool():
@ -775,7 +808,7 @@ def run_script_tool():
'error_no': -1,
'error_msg': '错误信息 [脚本工具状态不是正常状态 tool_id=%s, status=%s]' % (form_tool_id, tool.status),
})
result = ScriptToolDispatcher(tool=tool, dispatcher_type=DISPATCHER_TYPE.DEBUG).run()
result = ScriptToolDispatcher(tool=tool, dispatcher_type=DISPATCHER_TYPE.DEBUG).run() # TODO BUG 未传project_id
log_text = result.get('log_text', '')
else:
return jsonify({
@ -2264,6 +2297,11 @@ def get_report_detail_tool():
dispatcher_detail=dispatcher_detail,
report_tool_data=report_tool_data)
variables = report_tool_data.report_variable_definition_tool_data.variables
elif report_tool_data.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
html_text = render_template('report/_report_detail_http_request_header_manager_tool.html',
dispatcher_detail=dispatcher_detail,
report_tool_data=report_tool_data)
variables = report_tool_data.report_http_request_header_manager_tool_data.variables
else:
html_text = ''
except Exception as e:
@ -2508,6 +2546,9 @@ def tool():
elif tool.tool_type == TOOL_TYPE.VARIABLE_DEFINITION:
html_text = render_template('tool/variable_definition.html', tool=tool)
data_variables = json.loads(render_to_json(tool.specific_tool.variable_definition_list))
elif tool.tool_type == TOOL_TYPE.HTTP_REQUEST_HEADER_MANAGER:
html_text = render_template('tool/http_request_header_manager.html', tool=tool)
data_variables = json.loads(render_to_json(tool.specific_tool.http_request_header_manager_list))
else:
return jsonify({
'error_no': -1,

View File

@ -196,6 +196,9 @@ body {
.icon-tool-variable-definition{
background-image: url(/static/icon/variable.svg);
}
.icon-tool-http-request-header-manager{
background-image: url(/static/icon/http-request-header.svg);
}
/*div边框样式*/
.border-left-primary {

View File

@ -0,0 +1,3 @@
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" >
<path d="M372.706 187.621v60.569h429.327v-60.569H372.706z m-185.096 0v60.208h125.356v-60.208H187.61z m740.386 185.096H64.212V64.223h863.783v308.494zM125.911 866.308H64.212v-61.699h61.699v61.699z m0-123.398H64.212v-61.699h61.699v61.699z m0-123.398H64.212v-61.699h61.699v61.699z m0-123.397H64.212v-61.699h61.699v61.699z m0 431.891H64.212v-61.699h61.699v61.699z m61.699 0h-61.699v-61.699h61.699v61.699z m123.397 0h-61.699v-61.699h61.699v61.699z m123.398 0h-61.699v-61.699h61.699v61.699z m308.494 0H681.2v-61.699h61.699v61.699z m-123.397 0h-61.699v-61.699h61.699v61.699z m246.795 0h-61.699v-61.699h61.699v61.699z m61.699 0h-61.699v-61.699h61.699v61.699z m0-61.698h-61.699v-61.699h61.699v61.699z m0-123.398h-61.699v-61.699h61.699v61.699z m0-123.398h-61.699v-61.699h61.699v61.699z m0-123.397h-61.699v-61.699h61.699v61.699z" />
</svg>

After

Width:  |  Height:  |  Size: 969 B

View File

@ -233,6 +233,9 @@ function renderToolReportDetail(node){
}else if(data.tool_type === 'VARIABLE_DEFINITION'){
// 渲染VariableDefinitionTool工具组件页面
renderVariableDefinitionToolPage(node.data.dispatcher_detail_id, data.variables);
}else if(data.tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
// 渲染HTTPRequestHeaderManagerTool工具组件页面
renderHTTPRequestHeaderManagerToolPage(node.data.dispatcher_detail_id, data.variables);
}
resolve(['成功了', 'success']); // 也可以传递其他类型参数
}else{
@ -643,6 +646,81 @@ function renderVariableDefinitionToolPage(dispatcher_detail_id, data_variables)
table_variable_definition = $container.handsontable(option_table_variable_definition).handsontable('getInstance');
}
}
// 渲染HTTPRequestHeaderManagerTool工具组件页面
function renderHTTPRequestHeaderManagerToolPage(dispatcher_detail_id, data_variables) {
// HTTP请求头表格对象
let table_http_request_header_manager = null;
// 渲染HTTP请求头表格
renderHTTPRequestHeaderManagerTable();
// 渲染HTTP请求头表格
function renderHTTPRequestHeaderManagerTable() {
const option_table_http_request_header_manager = {
data: data_variables,
rowHeaders: true,
// colHeaders: true,
licenseKey: 'non-commercial-and-evaluation',
// 表格宽度
// width: '95vw', // 不指定宽度使其自适应容器
// 拉伸方式
stretchH: 'all',
// tab键自动换行切换
autoWrapRow: true,
height: '55vh',
// 最大行数
maxRows: 999,
// 允许手工移动行或列
manualRowResize: true,
manualColumnResize: true,
// 列名
colHeaders: [
'名称',
'值',
'描述',
],
// 为列设置默认值
dataSchema: {
name: '',
value: '',
url_encode: false,
content_type: 'text/plain',
include_equals: true,
},
// 设置列数据类型
columns: [
{
data: 'name',
readOnly: true,
},
{
data: 'value',
readOnly: true,
},
{
data: 'description',
readOnly: true,
},
],
// 列宽比例
colWidths: [1, 1, 1],
manualRowMove: true,
manualColumnMove: false,
// 右键菜单
// contextMenu: ['row_above', 'row_below', '---------', 'remove_row', '---------', 'undo', 'redo', '---------', 'alignment', '---------', 'copy', 'cut'],
// 列是否支持过滤
filters: false,
// 下拉菜单
// dropdownMenu: ['make_read_only', '---------', 'alignment'],
// 语言
language: 'zh-CN',
// 是否允许无效数据 默认 true
allowInvalid: false,
};
let $container = $(`#table-http-request-header-manager-${dispatcher_detail_id}`);
table_http_request_header_manager = $container.handsontable(option_table_http_request_header_manager).handsontable('getInstance');
}
}
// 渲染报告图表
function renderEcharts() {
@ -792,6 +870,8 @@ function renderReportTree() {
$element.css('display', '');
if(element_type === 'TOOL' && node.data.tool_type === 'VARIABLE_DEFINITION'){
$(`#table-variable-definition-${dispatcher_detail_id}`).handsontable('getInstance').render();
}else if(element_type === 'TOOL' && node.data.tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
$(`#table-http-request-header-manager-${dispatcher_detail_id}`).handsontable('getInstance').render();
}
},
1000,
@ -873,6 +953,8 @@ function renderReportTree() {
return 'icon-tool-script';
}else if(tool_type === 'VARIABLE_DEFINITION'){
return 'icon-tool-variable-definition';
}else if(tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
return 'icon-tool-http-request-header-manager';
}
}else if(element_type === undefined) {
return true;

View File

@ -474,6 +474,8 @@ function renderElementCopyTree() {
return 'icon-tool-script';
}else if(tool_type === 'VARIABLE_DEFINITION'){
return 'icon-tool-variable-definition';
}else if(tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
return 'icon-tool-http-request-header-manager';
}
}else if(element_type === undefined) {
return true;
@ -1509,6 +1511,8 @@ function showTool(tool_id, tool_type) {
$element.css('display', '');
if(tool_type === 'VARIABLE_DEFINITION'){
$(`#table-variable-definition-${tool_id}`).handsontable('getInstance').render();
}else if(tool_type === 'HTTP_REQUEST_HEADER_MANAGER'){
$(`#table-http-request-header-manager-${tool_id}`).handsontable('getInstance').render();
}
},
1000,
@ -1882,7 +1886,11 @@ function addToolElement(tool_id) {
let element = getVariableDefinitionToolElement(data.tool_id);
element.init(data.data_variables);
element_tool_dict[data.tool_id] = element;
}
}else if(data.tool_type === 'HTTP_REQUEST_HEADER_MANAGER') {
let element = getHTTPRequestHeaderManagerToolElement(data.tool_id);
element.init(data.data_variables);
element_tool_dict[data.tool_id] = element;
}
resolve(['成功了', 'success']); // 也可以传递其他类型参数
}else{
message("工具组件加载失败: " + data.error_msg, "error");

View File

@ -0,0 +1,150 @@
function getHTTPRequestHeaderManagerToolElement(tool_id) {
let element = new Object;
element.dom = new Object;
element.obj = new Object;
// 案例页面元素
element.dom.$input_tool_name = $(`#input-tool-name-${tool_id}`);
element.dom.$input_tool_description = $(`#input-tool-description-${tool_id}`);
element.dom.$btn_tool_save = $(`#btn-tool-save-${tool_id}`);
element.dom.$div_navigation_tool_name = $(`.tool-name[data-tool-id=${tool_id}]`);
// 对象
element.obj.table_http_request_header_manager = null; // 变量定义表格
// 初始化
element.init = function(data_variables) {
// 事件绑定
eventBinding();
// 渲染HTTP请求头管理器表格
renderHTTPRequestHeaderManagerTable(data_variables);
};
// 事件绑定
function eventBinding() {
element.dom.$input_tool_name.on('change keyup', handleKeyUpAndChange);
element.dom.$btn_tool_save.on('click', saveTool);
function handleKeyUpAndChange(){
let tool_name = element.dom.$input_tool_name.val();
element.dom.$div_navigation_tool_name.children().text(tool_name);
}
}
// 渲染HTTP请求头管理器表格
function renderHTTPRequestHeaderManagerTable(data_variables) {
const option_table_http_request_header_manager = {
data: data_variables,
rowHeaders: true,
// colHeaders: true,
licenseKey: 'non-commercial-and-evaluation',
// 表格宽度
// width: '95vw', // 不指定宽度使其自适应容器
// 拉伸方式
stretchH: 'all',
// tab键自动换行切换
autoWrapRow: true,
height: '65vh',
// 最大行数
maxRows: 999,
// 允许手工移动行或列
manualRowResize: true,
manualColumnResize: true,
// 列名
colHeaders: [
'名称',
'值',
'描述',
],
// 为列设置默认值
dataSchema: {
name: '',
value: '',
url_encode: false,
content_type: 'text/plain',
include_equals: true,
},
// 设置列数据类型
columns: [
{
data: 'name'
},
{
data: 'value',
},
{
data: 'description',
},
],
// 列宽比例
colWidths: [1, 1, 1],
manualRowMove: true,
manualColumnMove: false,
// 右键菜单
contextMenu: ['row_above', 'row_below', '---------', 'remove_row', '---------', 'undo', 'redo', '---------', 'alignment', '---------', 'copy', 'cut'],
// 列是否支持过滤
filters: false,
// 下拉菜单
dropdownMenu: ['make_read_only', '---------', 'alignment'],
// 语言
language: 'zh-CN',
// 是否允许无效数据 默认 true
allowInvalid: false,
};
let $container = $(`#table-http-request-header-manager-${tool_id}`);
element.obj.table_http_request_header_manager = $container.handsontable(option_table_http_request_header_manager).handsontable('getInstance');
}
function saveTool() {
let tool_name = element.dom.$input_tool_name.val();
let tool_description = element.dom.$input_tool_description.val();
$.ajax({
type: 'POST',
url: '/ajax/tool/http_request_header_manager/save',
data: {
tool_id: tool_id,
tool_name: tool_name,
tool_description: tool_description,
vars: JSON.stringify(element.obj.table_http_request_header_manager.getSourceData()),
},
success: function (data, status, xhr) {
if (data.error_no === 0){
message('HTTP请求头保存成功', 'success');
}else{
message("HTTP请求头保存失败: " + data.error_msg, "error");
}
}
});
}
// 关键词查找
element.mark = function (text) {
// 匹配到则返回true
let pat = new RegExp(text);
let value = '';
let markFlag = false;
// 名称
value = element.dom.$input_tool_name.val();
if (pat.test(value)) return true;
// 注释
value = element.dom.$input_tool_description.val();
if (pat.test(value)) return true;
// 期望表格
markFlag = false;
value = element.obj.table_http_request_header_manager.getSourceData();
$.each(value, function (index, row) {
$.each(row, function (column, data) {
if (pat.test(data)){
markFlag = true;
return false;
}
});
});
if (markFlag) return true;
// 未匹配到返回false
return false;
};
return element;
}

View File

@ -0,0 +1,10 @@
<div class="container-fluid report-detail-data" id="dispatcher-detail-{{ dispatcher_detail.id }}" data-element-type="TOOL" style="display: none;">
<h4>定时器名称: {{ dispatcher_detail.element_name }}</h4>
<h6>开始时间: {{ dispatcher_detail.start_time }}</h6>
<h6>调度编号: {{ dispatcher_detail.dispatcher_id }}</h6>
<h6>元素编号: {{ dispatcher_detail.element_id }}</h6>
<h6>HTTP请求头管理器:</h6>
<div class="container-fluid p-0 mt-2">
<div id="table-http-request-header-manager-{{ dispatcher_detail.id }}"></div>
</div>
</div>

View File

@ -100,6 +100,15 @@
</div>
</div>
<div class="tab-pane fade" id="v-pills-tool" role="tabpanel">
<div class="btn btn-outline-primary" data-scene-id="{{ scene.id }}" onclick="addTool({{ scene.scene_controller.logic_controller.id }}, 'HTTP_REQUEST_HEADER_MANAGER')">
<h5 class="text-left">
HTTPRequestHeaderManager
<svg class="icon float-right" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" >
<path d="M372.706 187.621v60.569h429.327v-60.569H372.706z m-185.096 0v60.208h125.356v-60.208H187.61z m740.386 185.096H64.212V64.223h863.783v308.494zM125.911 866.308H64.212v-61.699h61.699v61.699z m0-123.398H64.212v-61.699h61.699v61.699z m0-123.398H64.212v-61.699h61.699v61.699z m0-123.397H64.212v-61.699h61.699v61.699z m0 431.891H64.212v-61.699h61.699v61.699z m61.699 0h-61.699v-61.699h61.699v61.699z m123.397 0h-61.699v-61.699h61.699v61.699z m123.398 0h-61.699v-61.699h61.699v61.699z m308.494 0H681.2v-61.699h61.699v61.699z m-123.397 0h-61.699v-61.699h61.699v61.699z m246.795 0h-61.699v-61.699h61.699v61.699z m61.699 0h-61.699v-61.699h61.699v61.699z m0-61.698h-61.699v-61.699h61.699v61.699z m0-123.398h-61.699v-61.699h61.699v61.699z m0-123.398h-61.699v-61.699h61.699v61.699z m0-123.397h-61.699v-61.699h61.699v61.699z"></path>
</svg>
</h5>
<p class="text-left">定义HTTP请求头.</p>
</div>
<div class="btn btn-outline-primary" data-scene-id="{{ scene.id }}" onclick="addTool({{ scene.scene_controller.logic_controller.id }}, 'VARIABLE_DEFINITION')">
<h5 class="text-left">
VariableDefinition

View File

@ -145,6 +145,7 @@ class="bg-gradient-grey"
<script src="{{ url_for('static', filename='js/tool/timer.js') }}"></script>
<script src="{{ url_for('static', filename='js/tool/script.js') }}"></script>
<script src="{{ url_for('static', filename='js/tool/variable_definition.js') }}"></script>
<script src="{{ url_for('static', filename='js/tool/http_request_header_manager.js') }}"></script>
<script>
let project_id = {{ project.id }};
</script>

View File

@ -0,0 +1,26 @@
<div class="row container-fluid element-data element-tool mt-2 ml-0" data-tool-id="{{ tool.id }}" data-tool-type="{{ tool.tool_type }}" style="display: none">
<h4>HTTP请求头管理器</h4>
<div class="input-group input-group-sm">
<div class="input-group-prepend">
<label class="input-group-text" for="input-tool-name-{{ tool.id }}">名称</label>
</div>
<input id="input-tool-name-{{ tool.id }}" type="text" class="form-control" placeholder="这里填写案例名称" value="{{ tool.name }}">
</div>
<div class="input-group input-group-sm mb-1">
<div class="input-group-prepend">
<label class="input-group-text" for="input-tool-description-{{ tool.id }}">注释</label>
</div>
<input id="input-tool-description-{{ tool.id }}" type="text" class="form-control" placeholder="这里填写注释说明" value="{{ tool.description }}">
</div>
<div class="container-fluid d-flex align-items-center justify-content-between pr-0 mr-0 pl-0 ml-0 mt-2">
<label class=" control-label">定义HTTP请求头:</label>
<div class="btn-toolbar pr-0 mr-2" role="toolbar">
<div class="btn-group" role="group">
<button id="btn-tool-save-{{ tool.id }}" type="button" class="btn btn-primary">保存</button>
</div>
</div>
</div>
<div class="container-fluid p-0 mt-2">
<div id="table-http-request-header-manager-{{ tool.id }}"></div>
</div>
</div>

View File

@ -183,6 +183,7 @@
请求组件 | SSH | 远程执行命令
请求组件 | SQL | 支持MySQL数据库
请求组件 | Debug | 获取执行时上下文中所有定义的变量和值
工具组件 | HTTPRequestHeaderManager | 设置HTTP请求头数据
工具组件 | VariableDefinition | 定义变量
工具组件 | Timer | 定时器, 暂停一段时间后继续执行
工具组件 | Script | 支持编写Python脚本, 灵活处理复杂逻辑和数据