#!/usr/bin/env python # -*- encoding: utf-8 -*- # @Author : qiaoxinjiu # @Time : 2021/07/13 # @File : websocket_api.py import time import json from functools import wraps import requests from websocket import create_connection from base_framework.public_tools.log import get_logger from base_framework.public_tools.sqlhelper import MySqLHelper from base_framework.public_tools.read_config import InitConfig def check_conn(func): @wraps(func) def wrap_check_conn(self, *args, **kwargs): self.ws = self.get_ws_conn() self.logger.info('%s connected websocket server' % func.__name__) return func(self, *args, **kwargs) return wrap_check_conn class WebSocketAPI(InitConfig): def __init__(self, user_name=None, env_name=None, timeout=30): # super().__init__(run_user_name=user_name, current_evn=env_name) InitConfig.__init__(self, run_user_name=user_name, current_evn=env_name) self.sso_url = self.all_cfg[self.current_evn]['sso_url'] self.code_url = self.all_cfg[self.current_evn]['code_url'] self.token_url = self.all_cfg[self.current_evn]['token_url'] self.redirect_url = self.all_cfg[self.current_evn]['teach_opt_url'] self.auth_code = self.all_cfg['Authorization']['sparkle-manage'] self.logger = get_logger() self.db_conn = MySqLHelper() def get_session(self): session = requests.Session() session.headers.update({'Authorization': self.auth_code}) if not hasattr(self, 'access_token'): self.access_token = self._get_access_token() session.headers.update({'accesstoken': self.access_token}) return session def _get_access_token(self): token_session = requests.Session() post_data = {'showUsername': self.show_username, 'username': self.username, 'password': self.password} resp1 = token_session.post(self.sso_url, data=post_data, allow_redirects=False) assert resp1.status_code == 302, 'incorrect response code %s' % resp1.status_code get_data = {'client_id': 'tm-manage', 'response_type': 'code', 'redirect_uri': self.redirect_url} resp2 = token_session.get(self.code_url, params=get_data, allow_redirects=False) assert resp2.status_code == 302, 'incorrect response code %s' % resp2.status_code tmp = resp2.headers code = tmp.get('Location').split('=')[1] post_data2 = {'grant_type': 'authorization_code', 'code': code, 'redirect_uri': self.redirect_url} token_session.headers.update({'Authorization': self.auth_code}) resp3 = token_session.post(self.token_url, data=post_data2) token = json.loads(resp3.text).get('access_token') return token def get_ws_conn(self, timeout=60): self.logger.info('websocket connecting...') self.access_token = self._get_access_token() uri = self.all_cfg[self.current_evn]['websocket_server'] if 'accesstoken' in uri: self.uri = uri else: self.uri = uri + '/?accesstoken=%s' % self.access_token if uri.endswith( '/') else uri + '/?accesstoken=%s' % self.access_token ws_conn = create_connection(self.uri, timeout=timeout) if ws_conn.getstatus() == 101: return ws_conn else: raise Exception('connect websocket server failed!') def _close_ws(self): if hasattr(self, 'ws'): self.ws.close() self.logger.info('connection closed success!') @check_conn def send_msg_and_get_response(self, send_data: [dict, str], timeout=3): if isinstance(send_data, dict): data = json.dumps(send_data) self.ws.send(data) self.logger.info(">>> heart beat!") self.logger.info(">>> send message:%s" % data) return self.get_response(ws_conn=self.ws, tm_stamp=send_data.get("timestamp"), timeout=timeout) elif isinstance(send_data, str): data = send_data self.ws.send(data) self.logger.info(">>> heart beat!") self.logger.info(">>> send message:%s" % data) return self.get_response(ws_conn=self.ws, tm_stamp=json.loads(send_data).get("timestamp"), timeout=timeout) else: raise Exception('send_data can only support dict or str type') def get_response(self, ws_conn, tm_stamp=None, timeout=3): t0 = time.time() while time.time() - t0 <= int(timeout): time.sleep(0.2) out_put = ws_conn.recv() if tm_stamp: if str(tm_stamp) in out_put: self.logger.info(">>> received message:%s" % out_put) return json.loads(out_put) elif out_put: return json.loads(out_put) else: continue else: self._close_ws() raise Exception('>>> received no response, please check ws connect!')