重命名HTTPCookieManager,并简化HTTPCookieManager实现(不再通过Cookie中http_cookie_manager_id实现)
This commit is contained in:
parent
3db0ae1b24
commit
3e84aecc60
|
@ -9,7 +9,7 @@ from logging.handlers import QueueHandler, QueueListener
|
|||
import click
|
||||
|
||||
from app.config import Config, proj_dir
|
||||
from app.extensions import (db, migrate, login_manager, mail, csrf, bootstrap, http_cookie_manager, session_id_manager,
|
||||
from app.extensions import (db, migrate, login_manager, mail, csrf, bootstrap, session_id_manager,
|
||||
socketio, dispatcher_scheduler)
|
||||
from app import models
|
||||
from app.template_global import (render_to_json, sort_by_order_in_module, sort_by_order_in_logic_controller,
|
||||
|
@ -68,7 +68,6 @@ def register_extensions(app: Flask):
|
|||
csrf.init_app(app=app)
|
||||
bootstrap.init_app(app=app)
|
||||
socketio.init_app(app=app, async_mode='threading')
|
||||
http_cookie_manager.init_app(app=app)
|
||||
session_id_manager.init_app(app=app)
|
||||
dispatcher_scheduler.init_app(app=app)
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# coding=utf-8
|
||||
|
||||
from app.models import Case, Dispatcher
|
||||
from app.extensions import http_cookie_manager
|
||||
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_cookie_pool_manager import HTTPCookiePoolManager
|
||||
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
|
||||
|
@ -61,7 +61,7 @@ class HTTPCaseDispatcher(AbstractCaseDispatcher):
|
|||
def set_up(self):
|
||||
super().set_up()
|
||||
# 获取cookie
|
||||
self.rcj = http_cookie_manager.get_request_cookie_jar(type=self.dispatcher_type)
|
||||
self.rcj = HTTPCookiePoolManager.get_request_cookie_jar(type=self.dispatcher_type)
|
||||
# 获取HTTP请求头
|
||||
self.headers = HTTPRequestHeaderPoolManager.get_http_request_header(project_id=self.case.scene.module.project.id)
|
||||
# 预处理脚本执行
|
||||
|
@ -128,7 +128,7 @@ class HTTPCaseDispatcher(AbstractCaseDispatcher):
|
|||
# 更新结果数据2
|
||||
LastResult.update_result_to_last_result(result=self.expectations_result)
|
||||
# cookie处理
|
||||
http_cookie_manager.update_cookie_pool(
|
||||
HTTPCookiePoolManager.update_cookie_pool(
|
||||
rcj=self.request_.response.cookies,
|
||||
type=self.dispatcher_type,
|
||||
)
|
||||
|
|
|
@ -1,27 +1,26 @@
|
|||
# coding=utf-8
|
||||
|
||||
from flask import request, session
|
||||
from flask import session
|
||||
from requests.cookies import RequestsCookieJar
|
||||
from datetime import timedelta, datetime
|
||||
import uuid
|
||||
from typing import Optional, List, Mapping
|
||||
|
||||
from app.extensions import session_id_manager
|
||||
from app.cores.dictionaries import DISPATCHER_TYPE, DISPATCHER_TRIGGER_TYPE
|
||||
|
||||
# requests库会在发起请求时根据请求服务器的domain选择合适的cookie作为请求头中的cookie数据发出
|
||||
# 可参考代码 requests.models.prepare_cookies()
|
||||
|
||||
|
||||
class HTTPCookieManager:
|
||||
class HTTPCookiePoolManager:
|
||||
"""
|
||||
管理自动化测试中请求头Cookie数据
|
||||
|
||||
CookiePool = {
|
||||
http_cookie_manager_id1: {
|
||||
session_id1: {
|
||||
DISPATCHER_TYPE.DEBUG: RequestsCookieJar(),
|
||||
DISPATCHER_TYPE.BUILD: RequestsCookieJar(),
|
||||
},
|
||||
http_cookie_manager_id1: {
|
||||
session_id2: {
|
||||
DISPATCHER_TYPE.DEBUG: RequestsCookieJar(),
|
||||
DISPATCHER_TYPE.BUILD: RequestsCookieJar(),
|
||||
},
|
||||
|
@ -41,15 +40,8 @@ class HTTPCookieManager:
|
|||
# 对于定时构建的项目,使用另一个Cookie池保存,key为项目id
|
||||
ScheduleCookiePool = {}
|
||||
|
||||
def __init__(self, app=None):
|
||||
if app is not None:
|
||||
self.init_app(app)
|
||||
|
||||
def init_app(self, app):
|
||||
app.http_cookie_manager = self
|
||||
app.after_request(self._update_cookie)
|
||||
|
||||
def update_cookie_pool(self, rcj: RequestsCookieJar = None, type: str = None):
|
||||
@classmethod
|
||||
def update_cookie_pool(cls, rcj: RequestsCookieJar = None, type: str = None):
|
||||
"""
|
||||
:param rcj: RequestsCookieJar对象,一般由应答头获得 response.cookies
|
||||
:param type: 需要更新到的cookie类型 DISPATCHER_TYPE.BUILD或DISPATCHER_TYPE.DEBUG
|
||||
|
@ -60,11 +52,11 @@ class HTTPCookieManager:
|
|||
project_id = session.get('project_id')
|
||||
if project_id:
|
||||
if project_id not in __class__.ScheduleCookiePool:
|
||||
self._add_empty_to_cookie_pool()
|
||||
cls._add_empty_to_cookie_pool()
|
||||
else:
|
||||
http_cookie_manager_id = self._get_http_cookie_manager_id()
|
||||
if http_cookie_manager_id not in __class__.CookiePool:
|
||||
self._add_empty_to_cookie_pool()
|
||||
session_id = session_id_manager.get_session_id()
|
||||
if session_id not in __class__.CookiePool:
|
||||
cls._add_empty_to_cookie_pool()
|
||||
# 如果入参rcj为空的RequestsCookieJar则不更新直接返回
|
||||
if len(rcj) == 0:
|
||||
return
|
||||
|
@ -77,22 +69,24 @@ class HTTPCookieManager:
|
|||
if old_rcj is None:
|
||||
__class__.ScheduleCookiePool[project_id] = rcj
|
||||
else:
|
||||
self._update_request_cookie_jar(old_rcj=old_rcj, new_rcj=rcj)
|
||||
cls._update_request_cookie_jar(old_rcj=old_rcj, new_rcj=rcj)
|
||||
else:
|
||||
http_cookie_manager_id = self._get_http_cookie_manager_id()
|
||||
old_rcj = __class__.CookiePool[http_cookie_manager_id][type]
|
||||
session_id = session_id_manager.get_session_id()
|
||||
old_rcj = __class__.CookiePool[session_id][type]
|
||||
if old_rcj is None:
|
||||
__class__.CookiePool[http_cookie_manager_id][type] = rcj
|
||||
__class__.CookiePool[session_id][type] = rcj
|
||||
else:
|
||||
self._update_request_cookie_jar(old_rcj=old_rcj, new_rcj=rcj)
|
||||
cls._update_request_cookie_jar(old_rcj=old_rcj, new_rcj=rcj)
|
||||
else:
|
||||
raise ValueError('不支持传入type值为%s,只支持type=single_case 或 type=build_case' % type)
|
||||
|
||||
def _update_request_cookie_jar(self, old_rcj: RequestsCookieJar, new_rcj: RequestsCookieJar):
|
||||
@classmethod
|
||||
def _update_request_cookie_jar(cls, old_rcj: RequestsCookieJar, new_rcj: RequestsCookieJar):
|
||||
"""将新的rcj更新到老的rcj上"""
|
||||
old_rcj.update(other=new_rcj)
|
||||
|
||||
def _add_empty_to_cookie_pool(self):
|
||||
@classmethod
|
||||
def _add_empty_to_cookie_pool(cls):
|
||||
"""
|
||||
为当前会话在cookie pool中添加一个新的,默认值为RequestsCookieJar()
|
||||
:return: None
|
||||
|
@ -104,15 +98,16 @@ class HTTPCookieManager:
|
|||
project_id: RequestsCookieJar(),
|
||||
})
|
||||
else:
|
||||
http_cookie_manager_id = self._get_http_cookie_manager_id()
|
||||
session_id = session_id_manager.get_session_id()
|
||||
__class__.CookiePool.update({
|
||||
http_cookie_manager_id: {
|
||||
session_id: {
|
||||
DISPATCHER_TYPE.DEBUG: RequestsCookieJar(),
|
||||
DISPATCHER_TYPE.BUILD: RequestsCookieJar(),
|
||||
}
|
||||
})
|
||||
|
||||
def get_request_cookie_jar(self, type: str) -> Optional[RequestsCookieJar]:
|
||||
@classmethod
|
||||
def get_request_cookie_jar(cls, type: str) -> Optional[RequestsCookieJar]:
|
||||
"""
|
||||
获取当前会话中指定类型的cookie数据
|
||||
:param type: cookie类型 DISPATCHER_TYPE.BUILD或DISPATCHER_TYPE.DEBUG
|
||||
|
@ -125,12 +120,13 @@ class HTTPCookieManager:
|
|||
return
|
||||
return __class__.ScheduleCookiePool[project_id]
|
||||
else:
|
||||
http_cookie_manager_id = self._get_http_cookie_manager_id()
|
||||
if http_cookie_manager_id not in __class__.CookiePool:
|
||||
session_id = session_id_manager.get_session_id()
|
||||
if session_id not in __class__.CookiePool:
|
||||
return
|
||||
return __class__.CookiePool[http_cookie_manager_id][type]
|
||||
return __class__.CookiePool[session_id][type]
|
||||
|
||||
def clear_and_reset(self, rcj: RequestsCookieJar, cookies: List[Mapping]):
|
||||
@classmethod
|
||||
def clear_and_reset(cls, rcj: RequestsCookieJar, cookies: List[Mapping]):
|
||||
"""
|
||||
清除并重置RequestsCookieJar
|
||||
:param rcj: 待重置的RequestsCookieJar,来自cookie pool中该会话cookie
|
||||
|
@ -143,63 +139,21 @@ class HTTPCookieManager:
|
|||
for cookie in cookies:
|
||||
rcj.set(**cookie)
|
||||
|
||||
def _update_cookie(self, response):
|
||||
"""注册到app.after_request, 当浏览器没有该cookie时,将会在应答头中带上该cookie"""
|
||||
# 判断当前浏览器是否保存有HTTPCookieManager ID的Cookie
|
||||
# 如果没有的话则会在该浏览器中新增一个HTTPCookieManager ID的Cookie,并将ID值保存在CookiePool中
|
||||
if HTTPCookieManagerConfig.COOKIE_NAME not in request.cookies:
|
||||
duration = HTTPCookieManagerConfig.COOKIE_DURATION
|
||||
if isinstance(duration, int):
|
||||
duration = timedelta(seconds=duration)
|
||||
try:
|
||||
expires = datetime.utcnow() + duration
|
||||
except TypeError:
|
||||
raise Exception('HTTPCookieManagerConfig.COOKIE_DURATION must be a ' +
|
||||
'datetime.timedelta, instead got: {0}'.format(duration))
|
||||
uuid_ = str(uuid.uuid1())
|
||||
response.set_cookie(HTTPCookieManagerConfig.COOKIE_NAME,
|
||||
value=uuid_, # 唯一标识
|
||||
expires=expires,
|
||||
domain=None,
|
||||
path='/',
|
||||
secure=HTTPCookieManagerConfig.COOKIE_SECURE,
|
||||
httponly=HTTPCookieManagerConfig.COOKIE_HTTPONLY)
|
||||
else:
|
||||
pass
|
||||
return response
|
||||
|
||||
def clear_cookie_pool(self, type: str = None):
|
||||
@classmethod
|
||||
def clear_cookie_pool(cls, type: str = None):
|
||||
"""
|
||||
清空当前会话中的cookie数据
|
||||
:param type: cookie类型 DISPATCHER_TYPE.BUILD或DISPATCHER_TYPE.DEBUG
|
||||
:return:
|
||||
"""
|
||||
if self.get_request_cookie_jar(type=type) is not None:
|
||||
if cls.get_request_cookie_jar(type=type) is not None:
|
||||
if type in [DISPATCHER_TYPE.DEBUG, DISPATCHER_TYPE.BUILD]:
|
||||
if session.get('dispatcher_trigger_type') == DISPATCHER_TRIGGER_TYPE.BY_SCHEDULE:
|
||||
project_id = session.get('project_id')
|
||||
if project_id:
|
||||
__class__.ScheduleCookiePool[project_id] = RequestsCookieJar()
|
||||
else:
|
||||
http_cookie_manager_id = self._get_http_cookie_manager_id()
|
||||
__class__.CookiePool[http_cookie_manager_id][type] = RequestsCookieJar()
|
||||
session_id = session_id_manager.get_session_id()
|
||||
__class__.CookiePool[session_id][type] = RequestsCookieJar()
|
||||
else:
|
||||
raise ValueError('不支持传入type值为%s,只支持type=single_case 或 type=build_case' % type)
|
||||
|
||||
def _get_http_cookie_manager_id(self):
|
||||
"""获取请求上下文中的http_cookie_manager_id"""
|
||||
try:
|
||||
return request.cookies.get(HTTPCookieManagerConfig.COOKIE_NAME)
|
||||
except KeyError:
|
||||
raise KeyError('在请求上下文cookies中未找到名为%s的cookie' % HTTPCookieManagerConfig.COOKIE_NAME)
|
||||
|
||||
|
||||
class HTTPCookieManagerConfig:
|
||||
# 标识HTTPCookieManager在当前浏览器客户端对应id的cookie
|
||||
COOKIE_NAME = 'http_cookie_manager_id'
|
||||
|
||||
COOKIE_DURATION = timedelta(days=365)
|
||||
|
||||
COOKIE_SECURE = None
|
||||
|
||||
COOKIE_HTTPONLY = False
|
|
@ -11,7 +11,6 @@ from functools import partial
|
|||
import contextlib
|
||||
|
||||
from app.template_global import sort_by_order_in_module, sort_by_order_in_project, sort_by_order_in_logic_controller
|
||||
from app.extensions import http_cookie_manager
|
||||
from app.cores.dictionaries import (ELEMENT_TYPE, STATUS, CASE_TYPE, DISPATCHER_STATUS, DISPATCHER_TYPE,
|
||||
DISPATCHER_END_TYPE, REPORT_RESULT, TOOL_TYPE, LOGIC_CONTROLLER_TYPE,
|
||||
DISPATCHER_TRIGGER_TYPE)
|
||||
|
@ -23,6 +22,7 @@ from app.cores.ws import emit_dispatcher_result, emit_dispatcher_end, emit_dispa
|
|||
from app.cores.exceptions import *
|
||||
from app.cores import dingtalk
|
||||
from app.cores.email import send_email_report
|
||||
from app.cores.case.http.http_cookie_pool_manager import HTTPCookiePoolManager
|
||||
|
||||
|
||||
class AbstractDispatcher(ABC):
|
||||
|
@ -418,7 +418,7 @@ class AbstractDispatcher(ABC):
|
|||
if project_advanced_configuration:
|
||||
if project_advanced_configuration.clear_http_cookie:
|
||||
try:
|
||||
http_cookie_manager.clear_cookie_pool(type=DISPATCHER_TYPE.BUILD)
|
||||
HTTPCookiePoolManager.clear_cookie_pool(type=DISPATCHER_TYPE.BUILD)
|
||||
except Exception as e:
|
||||
self.dispatcher_logger.logger.warning(f'清理HTTPCookie数据失败,错误信息:\n{traceback.format_exc()}')
|
||||
else:
|
||||
|
|
|
@ -8,7 +8,6 @@ from flask_wtf import CSRFProtect
|
|||
from flask_bootstrap import Bootstrap
|
||||
from flask_socketio import SocketIO
|
||||
|
||||
from app.cores.case.http.http_cookie_manager import HTTPCookieManager
|
||||
from app.cores.session_id_manager import SessionIDManager
|
||||
from app.cores.dispatcher_scheduler import DispatcherScheduler
|
||||
|
||||
|
@ -24,7 +23,6 @@ mail = Mail()
|
|||
csrf = CSRFProtect()
|
||||
bootstrap = Bootstrap()
|
||||
socketio = SocketIO()
|
||||
http_cookie_manager = HTTPCookieManager()
|
||||
session_id_manager = SessionIDManager()
|
||||
dispatcher_scheduler = DispatcherScheduler()
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ from datetime import datetime, timedelta
|
|||
from app.cores.dictionaries import (STATUS, DISPATCHER_STATUS, ELEMENT_TYPE, DISPATCHER_TYPE, CASE_TYPE, REPORT_RESULT,
|
||||
EXPECTATION_LOGIC, LOGIC_CONTROLLER_TYPE, TOOL_TYPE, CONTENT_TYPE)
|
||||
from app.cores.case.http.dispatcher import HTTPCaseDispatcher
|
||||
from app.cores.case.http.http_cookie_pool_manager import HTTPCookiePoolManager
|
||||
from app.cores.case.ssh.dispatcher import SSHCaseDispatcher
|
||||
from app.cores.case.sql.dispatcher import SQLCaseDispatcher
|
||||
from app.cores.case.debug.dispatcher import DebugCaseDispatcher
|
||||
|
@ -21,7 +22,7 @@ from app.models import Case, Project, Module, Scene, HTTPCase, SSHCase, SQLCase,
|
|||
Scheduler, DingTalkRobotSetting, DingTalkRobotSettingAssociationProject, DebugCase, Tool, TimerTool, ScriptTool, \
|
||||
VariableDefinitionTool, EmailReceiverSetting, EmailReceiverSettingAssociationProject, HTTPRequestHeaderManagerTool
|
||||
from app.template_global import render_to_json
|
||||
from app.extensions import http_cookie_manager, dispatcher_scheduler
|
||||
from app.extensions import dispatcher_scheduler
|
||||
from app.template_global import sort_by_order_in_project, sort_by_order_in_module, sort_by_order_in_logic_controller
|
||||
|
||||
|
||||
|
@ -155,7 +156,7 @@ def execute_http_case():
|
|||
@bp.route('/case/http/cookie/get', methods=['POST'])
|
||||
def get_cookie():
|
||||
try:
|
||||
rcj = http_cookie_manager.get_request_cookie_jar(type=DISPATCHER_TYPE.DEBUG)
|
||||
rcj = HTTPCookiePoolManager.get_request_cookie_jar(type=DISPATCHER_TYPE.DEBUG)
|
||||
cookies = []
|
||||
if rcj is not None:
|
||||
for cookie in rcj:
|
||||
|
@ -199,7 +200,7 @@ def save_cookie():
|
|||
if not exist: return form_cookies
|
||||
try:
|
||||
cookies = json.loads(form_cookies)
|
||||
rcj = http_cookie_manager.get_request_cookie_jar(type=DISPATCHER_TYPE.DEBUG)
|
||||
rcj = HTTPCookiePoolManager.get_request_cookie_jar(type=DISPATCHER_TYPE.DEBUG)
|
||||
for cookie in cookies:
|
||||
if cookie.get('domain') is None:
|
||||
return jsonify({
|
||||
|
@ -208,7 +209,7 @@ def save_cookie():
|
|||
})
|
||||
if 'Delete' in cookie: cookie.pop('Delete')
|
||||
if cookie['expires'] == '': cookie['expires'] = None
|
||||
http_cookie_manager.clear_and_reset(rcj=rcj, cookies=cookies)
|
||||
HTTPCookiePoolManager.clear_and_reset(rcj=rcj, cookies=cookies)
|
||||
except Exception as e:
|
||||
exception_handle(current_app, e)
|
||||
return jsonify({
|
||||
|
|
Loading…
Reference in New Issue