addproject
This commit is contained in:
365
base_framework/public_tools/runner.py
Normal file
365
base_framework/public_tools/runner.py
Normal file
@@ -0,0 +1,365 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import requests
|
||||
import json
|
||||
import time
|
||||
from urllib import parse
|
||||
from base_framework.public_tools.get_token import LoginSys, SparkleLogin, AgentApiLogin, MarketApiLogin, token_dict, \
|
||||
AllSchool, \
|
||||
ParentLogin, student_token_cache, StudentLogin, SparkEduLogin, SparkSaasLogin, SparkSaasTeacherLogin
|
||||
from base_framework.public_tools import log
|
||||
from base_framework.public_tools.read_config import ReadConfig, get_current_env
|
||||
from base_framework.base_config.current_pth import *
|
||||
from base_framework.public_tools.read_config import get_current_config
|
||||
from base_framework.public_tools.sqlhelper import MySqLHelper
|
||||
|
||||
obj_log = log.get_logger()
|
||||
evn_cfg = ReadConfig(env_choose_path)
|
||||
base_cfg = ReadConfig(config_file_path)
|
||||
all_school_api_host = ['api.qa.allschool.com', 'api.sim.allschool.com', 'api.allschool.com']
|
||||
|
||||
|
||||
class Runner(LoginSys):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
# self.env = get_current_config(section="run_evn_name", key="current_evn")
|
||||
self.env = get_current_env()
|
||||
self.is_need_sso = ["teach-api"]
|
||||
self.team = get_current_config(section="run_evn_name", key="current_team")
|
||||
self.db_con = MySqLHelper()
|
||||
self.sql_data = [] # 存放接口响应时间
|
||||
self.week = time.strftime("%w", time.localtime())
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
|
||||
if not hasattr(cls, 'instance'):
|
||||
cls.instance = super().__new__(cls)
|
||||
|
||||
return cls.instance
|
||||
|
||||
def __del__(self):
|
||||
if self.sql_data: # 如果有数据未插入
|
||||
# sql_str = ("insert into sparkatp.interface_response_time(team, in_type, rp_time, in_url,in_id) "
|
||||
# "values (%s,%s,%s,%s,%s);")
|
||||
# self.db_con.insert_many(sql=sql_str, param=self.sql_data)
|
||||
# self.sql_data.clear()
|
||||
pass
|
||||
|
||||
def __call_api(self, session, api_url, req_type, **kwargs):
|
||||
try:
|
||||
if req_type == "GET":
|
||||
req = session.get(api_url, verify=False, **kwargs)
|
||||
elif req_type == "POST":
|
||||
req = session.post(api_url, verify=False, **kwargs)
|
||||
elif req_type == "PUT":
|
||||
req = session.put(api_url, verify=False, **kwargs)
|
||||
elif req_type == "DELETE":
|
||||
req = session.delete(api_url, verify=False, **kwargs)
|
||||
elif req_type == "PATCH":
|
||||
req = session.patch(api_url, verify=False, **kwargs)
|
||||
else:
|
||||
obj_log.info(f'req_type,输入错误!不支持请求方法{req_type}')
|
||||
raise Exception(f'req_type,输入错误!不支持请求方法{req_type}')
|
||||
except Exception as e:
|
||||
obj_log.info('返回数据:{}'.format(e))
|
||||
return e
|
||||
|
||||
if self.env.lower() != "sim": # 非sim环境才记录接口响应时间
|
||||
# 每周六,记录一次所有接口的响应时间
|
||||
if self.week in ['6']:
|
||||
current_time = int(time.strftime("%H", time.localtime()))
|
||||
if current_time >= 5: # 5点之前的404校验脚本不统计,因为都是非正常参数,详见:http://10.250.200.1:8080/jenkins/view/2-%E8%BE%85%E5%8A%A9%E7%A8%8B%E5%BA%8F/job/%E6%8E%A5%E5%8F%A3404%E6%A3%80%E6%9F%A5/
|
||||
run_time = int(req.elapsed.total_seconds() * 1000)
|
||||
if run_time > 200: # 超过200ms的接口记录到数据库
|
||||
in_data = (self.team, req_type, run_time, api_url, 0)
|
||||
self.sql_data.append(in_data)
|
||||
if len(self.sql_data) >= 10: # 每10条数据插入一次, 最后一次不足100条时在__del__中插入
|
||||
sql_str = (
|
||||
"insert into sparkatp.interface_response_time(team, in_type, rp_time, in_url,in_id) "
|
||||
"values (%s,%s,%s,%s,%s);")
|
||||
self.db_con.insert_many(sql=sql_str, param=self.sql_data)
|
||||
self.sql_data.clear()
|
||||
return req
|
||||
|
||||
def call_rest_api(self, API_URL, req_type, user=None,
|
||||
token=None, current_evn=None, is_file=False, **kwargs):
|
||||
'''
|
||||
功能:所有接口访问入口
|
||||
'''
|
||||
if self.env.lower() == "sim":
|
||||
API_URL = API_URL.replace(".qa.", ".sim.")
|
||||
return self._call_zhyy_api(API_URL, req_type, user,
|
||||
token, current_evn, is_file, **kwargs)
|
||||
|
||||
def _call_zhyy_api(self, api_url, req_type, user=None, token=None, current_evn=None, is_file=False, **kwargs):
|
||||
"""
|
||||
功能:模拟走ruoyi登录模式,带token访问接口
|
||||
:param API_URL:
|
||||
:param req_type:
|
||||
:param user: 使用的自定义用户登录
|
||||
:param token: 从SSO获取的token,此字段使用默认值None,不是的情况使用False
|
||||
:param current_evn: QA or SIM
|
||||
:param is_file:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
req_type = req_type.upper()
|
||||
retry_num = 4
|
||||
cnt = 0
|
||||
if 'as_login_type' in kwargs.keys():
|
||||
kwargs.pop('as_login_type')
|
||||
options_dict = dict(**kwargs)
|
||||
result = parse.urlparse(url=api_url, allow_fragments=True)
|
||||
host = result.hostname
|
||||
if not user:
|
||||
user = self.curt_user
|
||||
obj_log.info('登录系统为{},用户名为手动输入:{}'.format(host, user))
|
||||
obj_log.info('请求地址:{}'.format(api_url))
|
||||
obj_log.info('请求数据:{}'.format(options_dict))
|
||||
header = {"Authorization": "Basic c3BhcmtsZS13ZWI6c3BhcmtsZS13ZWI=", "tenant-id": "1"}
|
||||
session = requests.session()
|
||||
session.headers.update(header)
|
||||
while cnt < retry_num:
|
||||
if token is None:
|
||||
if not user:
|
||||
user = evn_cfg.get_value(sections='run_user_name', options='default_user')
|
||||
tenant_name = base_cfg.get_value(sections=user, options='tenant')
|
||||
usr_name = base_cfg.get_value(sections=user, options='username')
|
||||
usr_pwd = base_cfg.get_value(sections=user, options='password')
|
||||
# 检查 kwargs 中是否包含登录信息(tenantName/username 和 password)
|
||||
# 如果包含,使用传入的参数;否则使用配置文件中的登录信息
|
||||
json_data = kwargs.get('json', {})
|
||||
is_login_params = isinstance(json_data, dict) and 'password' in json_data and (
|
||||
'tenantName' in json_data or 'username' in json_data)
|
||||
|
||||
if is_login_params:
|
||||
# 使用传入的登录参数
|
||||
obj_log.info('检测到 kwargs 中包含登录信息,使用传入的参数进行登录')
|
||||
login_req = self.__call_api(session, api_url, req_type='POST', **kwargs)
|
||||
else:
|
||||
# 使用配置文件中的登录信息
|
||||
obj_log.info('使用配置文件中的登录信息进行登录')
|
||||
request_body = {'json': {'tenantName': tenant_name, 'username': usr_name, 'password': usr_pwd,
|
||||
'rememberMe': 'true'}}
|
||||
api_login_url = self.zhyy_host
|
||||
login_req = self.__call_api(session, api_login_url, req_type='POST', **request_body)
|
||||
try:
|
||||
req_json = login_req.json()
|
||||
except Exception:
|
||||
# 如果 json() 失败,尝试将 text 转成 JSON
|
||||
try:
|
||||
if isinstance(login_req, Exception):
|
||||
obj_log.warning("登录请求失败: {}".format(login_req))
|
||||
req_json = {}
|
||||
else:
|
||||
req_json = json.loads(login_req.text)
|
||||
except Exception:
|
||||
if isinstance(login_req, Exception):
|
||||
obj_log.warning("登录请求失败: {}".format(login_req))
|
||||
else:
|
||||
obj_log.warning("登录响应无法解析为JSON: {}".format(login_req.text))
|
||||
req_json = {}
|
||||
# 判断登录是否成功:code为0或200表示成功,或者data中包含accessToken
|
||||
login_code = req_json.get("code")
|
||||
if login_code not in [0, 200] and not req_json.get("data", {}).get('accessToken'):
|
||||
raise Exception("SSO登录失败: {}".format(req_json))
|
||||
user_token = req_json.get("data", {}).get('accessToken')
|
||||
# 如果 api_url 本身就是登录接口,登录成功后直接返回登录响应
|
||||
if is_login_params:
|
||||
obj_log.info('api_url 是登录接口,直接返回登录响应')
|
||||
if not is_file:
|
||||
return req_json
|
||||
else:
|
||||
return login_req.content
|
||||
else:
|
||||
user_token = token
|
||||
if user_token:
|
||||
session.headers.update({'ssotoken': user_token})
|
||||
session.headers.update({'sso-token': user_token})
|
||||
session.headers.update({'accesstoken': user_token})
|
||||
session.headers.update({'Accesstoken': user_token})
|
||||
session.headers.update({'access-token': user_token})
|
||||
session.headers.update({'Authorization': user_token})
|
||||
session.headers.update({'token': user_token})
|
||||
obj_log.info(f'请求头headers:{session.headers}')
|
||||
req = self.__call_api(session, api_url, req_type, **kwargs)
|
||||
if isinstance(req, Exception):
|
||||
obj_log.error('请求失败:{}'.format(req))
|
||||
return req
|
||||
if not is_file:
|
||||
try:
|
||||
rtn_temp = req.json()
|
||||
except Exception as e:
|
||||
# 如果 json() 失败,尝试将 text 转成 JSON
|
||||
try:
|
||||
rtn_temp = json.loads(req.text)
|
||||
except Exception:
|
||||
# 如果都失败,保持为 text 字符串
|
||||
rtn_temp = req.text
|
||||
else:
|
||||
rtn_temp = req.content
|
||||
# SSO登录过期处理开始
|
||||
status_code = str(req.status_code)
|
||||
obj_log.info('------状态码:{}, 返回信息:{}'.format(status_code, rtn_temp))
|
||||
try:
|
||||
# 如果 rtn_temp 是字典,才能使用 .get() 方法
|
||||
if isinstance(rtn_temp, dict):
|
||||
resp_code = str(rtn_temp.get('code', '200'))
|
||||
else:
|
||||
resp_code = '200'
|
||||
except:
|
||||
resp_code = '200'
|
||||
if not is_file:
|
||||
token_dict.clear() # 缓存session过期清理
|
||||
student_token_cache.clear() # 缓存session过期清理
|
||||
obj_log.warning("--缓存session过期,清理缓存!")
|
||||
cnt += 1
|
||||
if cnt <= 1:
|
||||
continue
|
||||
if status_code == "401" or resp_code == '401':
|
||||
token_dict.clear() # 缓存session过期清理
|
||||
student_token_cache.clear() # 缓存session过期清理
|
||||
obj_log.warning("缓存session过期,清理缓存!")
|
||||
cnt += 1
|
||||
if cnt <= 1:
|
||||
continue
|
||||
if status_code == "200" and "<!DOCTYPE html>" in str(rtn_temp):
|
||||
token_dict.clear() # 缓存session过期清理
|
||||
student_token_cache.clear() # 缓存session过期清理
|
||||
obj_log.warning("--缓存session过期,清理缓存!")
|
||||
cnt += 1
|
||||
if cnt <= 1:
|
||||
continue
|
||||
# SSO登录过期处理完成
|
||||
req.close()
|
||||
if not is_file:
|
||||
obj_log.info('返回数据:{}'.format(rtn_temp))
|
||||
else:
|
||||
obj_log.info('返回数据:文件字节流')
|
||||
return rtn_temp
|
||||
return False
|
||||
|
||||
def _call_sso_api(self, api_url, req_type, user=None, token=None, current_evn=None, is_file=False, **kwargs):
|
||||
"""
|
||||
功能:模拟走sso登录模式,带token访问接口
|
||||
:param API_URL:
|
||||
:param req_type:
|
||||
:param user: 使用的自定义用户登录
|
||||
:param token: 从SSO获取的token,此字段使用默认值None,不是的情况使用False
|
||||
:param current_evn: QA or SIM
|
||||
:param is_file:
|
||||
:param kwargs:
|
||||
:return:
|
||||
"""
|
||||
req_type = req_type.upper()
|
||||
retry_num = 4
|
||||
cnt = 0
|
||||
if 'as_login_type' in kwargs.keys():
|
||||
kwargs.pop('as_login_type')
|
||||
options_dict = dict(**kwargs)
|
||||
result = parse.urlparse(url=api_url, allow_fragments=True)
|
||||
host = result.hostname
|
||||
if not user:
|
||||
user = self.curt_user
|
||||
obj_log.info('登录系统为{},用户名为手动输入:{}'.format(host, user))
|
||||
obj_log.info('请求地址:{}'.format(api_url))
|
||||
obj_log.info('请求数据:{}'.format(options_dict))
|
||||
|
||||
header = {"Authorization": "Basic c3BhcmtsZS13ZWI6c3BhcmtsZS13ZWI=", "tenant-id": "1"}
|
||||
session = requests.session()
|
||||
session.headers.update(header)
|
||||
while cnt < retry_num:
|
||||
if token is None:
|
||||
if not user:
|
||||
user = evn_cfg.get_value(sections='run_user_name', options='default_user')
|
||||
usr_name = base_cfg.get_value(sections=user, options='show_username')
|
||||
usr_pwd = base_cfg.get_value(sections=user, options='password')
|
||||
sso_url = "{}?username={}&password={}".format(self.sparkle_pc_token_url, usr_name, usr_pwd)
|
||||
sso_rsp = session.post(sso_url).json()
|
||||
if sso_rsp.get("code") != 200:
|
||||
raise Exception("SSO登录失败: {}".format(sso_rsp))
|
||||
user_token = sso_rsp.get("data").get('accessToken')
|
||||
else:
|
||||
user_token = token
|
||||
if user_token:
|
||||
session.headers.update({'ssotoken': user_token})
|
||||
session.headers.update({'sso-token': user_token})
|
||||
session.headers.update({'accesstoken': user_token})
|
||||
session.headers.update({'Accesstoken': user_token})
|
||||
session.headers.update({'access-token': user_token})
|
||||
session.headers.update({'token': user_token})
|
||||
obj_log.info(f'请求头headers:{session.headers}')
|
||||
|
||||
req = self.__call_api(session, api_url, req_type, **kwargs)
|
||||
|
||||
if not is_file:
|
||||
try:
|
||||
rtn_temp = req.json()
|
||||
except Exception as e:
|
||||
# 如果 json() 失败,尝试将 text 转成 JSON
|
||||
try:
|
||||
rtn_temp = json.loads(req.text)
|
||||
except Exception:
|
||||
# 如果都失败,保持为 text 字符串
|
||||
rtn_temp = req.text
|
||||
else:
|
||||
rtn_temp = req.content
|
||||
# SSO登录过期处理开始
|
||||
status_code = str(req.status_code)
|
||||
obj_log.info('------状态码:{}, 返回信息:{}'.format(status_code, rtn_temp))
|
||||
try:
|
||||
# 如果 rtn_temp 是字典,才能使用 .get() 方法
|
||||
if isinstance(rtn_temp, dict):
|
||||
resp_code = str(rtn_temp.get('code', '200'))
|
||||
else:
|
||||
resp_code = '200'
|
||||
except:
|
||||
resp_code = '200'
|
||||
if not is_file:
|
||||
token_dict.clear() # 缓存session过期清理
|
||||
student_token_cache.clear() # 缓存session过期清理
|
||||
obj_log.warning("--缓存session过期,清理缓存!")
|
||||
cnt += 1
|
||||
if cnt <= 1:
|
||||
continue
|
||||
|
||||
if status_code == "401" or resp_code == '401':
|
||||
token_dict.clear() # 缓存session过期清理
|
||||
student_token_cache.clear() # 缓存session过期清理
|
||||
obj_log.warning("缓存session过期,清理缓存!")
|
||||
cnt += 1
|
||||
if cnt <= 1:
|
||||
continue
|
||||
if status_code == "200" and "<!DOCTYPE html>" in str(rtn_temp) and "https://sso.qa.huohua.cn" in str(
|
||||
rtn_temp):
|
||||
token_dict.clear() # 缓存session过期清理
|
||||
student_token_cache.clear() # 缓存session过期清理
|
||||
obj_log.warning("--缓存session过期,清理缓存!")
|
||||
cnt += 1
|
||||
if cnt <= 1:
|
||||
continue
|
||||
# SSO登录过期处理完成
|
||||
req.close()
|
||||
if not is_file:
|
||||
obj_log.info('返回数据:{}'.format(rtn_temp))
|
||||
else:
|
||||
obj_log.info('返回数据:文件字节流')
|
||||
return rtn_temp
|
||||
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
obj_runner = Runner()
|
||||
# url = "https://api.qa.sparkedu.com/user_language/"
|
||||
# url = "https://api.qa.sparkedu.com/third/student"
|
||||
url = "https://api.qa.sparkedu.com/user/appoint/add"
|
||||
phone = '13716640630'
|
||||
# post_data = {"avatar":"https://stalegacy.huohua.cn/image/huohua/avatar/default/default_avatar1.png",
|
||||
# "birthday":"2021-01-03 00:00:00",
|
||||
# "id":21434807,
|
||||
# "nickname":"hute222",
|
||||
# "sex":0}
|
||||
post_data = {"subjectType": 1}
|
||||
# resp = obj_runner.call_rest_api(API_URL=url, phone=phone, req_type="POST", json=post_data)
|
||||
resp = obj_runner.week
|
||||
print(resp)
|
||||
Reference in New Issue
Block a user