import logging import traceback import uuid import requests from requests.exceptions import RequestException from django.conf import settings from rest_framework.exceptions import APIException, ParseError from apps.third.errors import KING_REQUEST_ERROR from apps.utils.tools import print_roundtrip from django.utils.timezone import now from apps.third.king.king_api import kapis from apps.utils.tools import singleton from django.core.cache import cache from apps.third.mixins import HandleLogMixin import time requests.packages.urllib3.disable_warnings() myLogger = logging.getLogger('log') @singleton class KingClient(HandleLogMixin): """ 亚控数采 """ def __init__(self) -> None: self.king_enabled = getattr(settings, 'KING_ENABLED', False) if self.king_enabled: self.headers = {} self.log = {} # self._get_token() def _get_token(self): # is_ok, _ = self.request(**kapis['heartbeat'], raise_exception=False, timeout=10) # if is_ok == 'success': # return current_val:str = cache.get('king_token') is_ok = 'success' if current_val != 'requesting': json = { 'username': settings.KING_USERNAME, 'password': settings.KING_PASSWORD } cache.set('king_token', 'requesting', timeout=None) is_ok, res = self.request( **kapis['login'], json=json, timeout=10, need_auth=False, raise_exception=False) if is_ok == "success": current_val = res['Authorization'] else: myLogger.error(f'获取token失败: {is_ok}-{res}') cache.set('king_token', current_val, timeout=None) return is_ok, current_val def request(self, url: str, method: str = 'post', params=dict(), json=dict(), timeout=20, raise_exception=True, need_auth=True): if not self.king_enabled: raise ParseError('亚控对接未启用') if need_auth: count = 6 while count > 0: token = cache.get('king_token') if token != 'requesting': self.headers['Authorization'] = token break time.sleep(0.5) count = count -1 self.log = {"requested_at": now(), "id": uuid.uuid4(), "path": url, "method": method, "params": params, "body": json, "target": "king", "result": 10, "headers": self.headers} try: r = getattr(requests, method)('{}{}'.format(settings.KING_BASE_URL, url), headers=self.headers, params=params, json=json, timeout=timeout, verify=False) # if settings.DEBUG: # print_roundtrip(r) ret = r.text if 300 > r.status_code >= 200: ret = r.json() if 'code' in ret: if ret['code'] != 0: if need_auth and ret['code'] in [-1, -2]: # and url != '/api/v1/variables': # 认证失败 # 如果这里没有判断准确,可能会导致多次触发login myLogger.error(f"亚控认证失败: {self.headers}-{url}-{ret}") is_ok, _ = self._get_token() if is_ok == "success": return self.request(url, method, params, json, timeout, raise_exception, need_auth) err_detail = dict(detail=f"亚控错误: {ret['message']}", code='king_' + str(ret['code'])) self.handle_log(result='fail', response=ret) if raise_exception: raise ParseError(**err_detail) return 'fail', err_detail return 'success', ret['data'] return 'success', ret else: self.handle_log(result='error', response=ret) except RequestException: self.handle_log(result='error', errors=traceback.format_exc()) if raise_exception: raise APIException(**KING_REQUEST_ERROR) return 'error', KING_REQUEST_ERROR kingClient = KingClient()