APISenderBase.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import logging
  2. import ssl
  3. import time
  4. import json
  5. import urllib.request, urllib.parse, urllib.error
  6. import urllib.request, urllib.error, urllib.parse
  7. from Service.VivoPushService.push_admin.APIConstants import Constants
  8. from Service.VivoPushService.push_admin.APIError import APIError
  9. _MAX_BACKOFF_DELAY = 1024000
  10. class JsonDict(dict):
  11. def __getattr__(self, item):
  12. try:
  13. return self[item]
  14. except KeyError:
  15. raise AttributeError(r"'JsonDict' object has no attribute %s'" % item)
  16. def __setattr__(self, key, value):
  17. self[key] = value
  18. def _parse_json(body):
  19. """
  20. convert json object to python object
  21. :param body: response data
  22. """
  23. def _obj_hook(pairs):
  24. o = JsonDict()
  25. for k, v in pairs.items():
  26. o[str(k)] = v
  27. return o
  28. return json.loads(body, object_hook=_obj_hook)
  29. def _build_request_url(request_path):
  30. return Constants.http_server + request_path[0]
  31. def _http_call(url, method, token, **message):
  32. """
  33. :param url: http request url
  34. :param method: http request method
  35. :param message: params
  36. """
  37. params = _encode_params(message) if method == Constants.__HTTP_GET__ else ''
  38. http_url = '%s?%s' % (url, params) if method == Constants.__HTTP_GET__ else url
  39. http_body = None if method == Constants.__HTTP_GET__ else message
  40. req = urllib.request.Request(http_url, data=json.dumps(http_body).encode("utf-8"))
  41. if token:
  42. req.add_header('authToken', token)
  43. req.add_header('Content-Type', 'application/json;charset=UTF-8')
  44. try:
  45. context = ssl._create_unverified_context()
  46. resp = urllib.request.urlopen(req, context=context, timeout=10)
  47. r = _parse_json(resp.read().decode())
  48. return r
  49. except urllib.error.HTTPError as e:
  50. # 处理HTTPError
  51. raise APIError('-5', str(e.reason), 'http error ' + str(e.code))
  52. except urllib.error.URLError as e:
  53. # 处理URLError
  54. raise APIError('-5', str(e.reason), 'http error: ' + str(e.reason))
  55. except Exception as e:
  56. # 处理其他未知错误
  57. raise APIError('-5', str(e), 'Unknown error')
  58. def _encode_params(kw):
  59. """
  60. splic get request url
  61. :param kw: params
  62. """
  63. args = ''
  64. s = ''
  65. for k, v in kw.items():
  66. for t in v:
  67. s = s+ str(t) + ','
  68. args = '%s=%s' %(k, s[:-1])
  69. return args
  70. class Base(object):
  71. def __init__(self, secret, token=None):
  72. self.secret = secret
  73. self.token = token
  74. def set_token(self, token):
  75. self.token = token
  76. def _http_request(self, request_path, method, **message):
  77. """
  78. :param request_path: http interface
  79. :param method: GET|POST
  80. :param message: params
  81. """
  82. request_url = _build_request_url(request_path)
  83. try:
  84. ret = _http_call(request_url, method, self.token, **message)
  85. return ret
  86. except APIError as ex:
  87. logging.error("%s request: [%s] error [%s]" % (Constants.http_server, request_url, ex))
  88. raise ex
  89. def http_post(self, request_path, **message):
  90. logging.info("POST %s" % request_path[0])
  91. return self._http_request(request_path, Constants.__HTTP_POST__, **message)
  92. def http_get(self, request_path, **message):
  93. logging.info("GET %s" % request_path[0])
  94. return self._http_request(request_path, Constants.__HTTP_GET__, **message)
  95. def _try_http_request(self, request_path, retry_times, method=Constants.__HTTP_POST__, **message):
  96. is_fail, try_time, result, sleep_time = True, 0, None, 1
  97. while is_fail and try_time < retry_times:
  98. try:
  99. if method == Constants.__HTTP_POST__:
  100. result = self.http_post(request_path, **message)
  101. elif method == Constants.__HTTP_GET__:
  102. result = self.http_get(request_path, **message)
  103. else:
  104. raise APIError('-2', 'not support %s http request' % method, 'http error')
  105. is_fail = False
  106. except APIError as ex:
  107. '''
  108. failure retry
  109. '''
  110. if ex.error_code == '-5':
  111. is_fail = True
  112. try_time += 1
  113. logging.error('code:[%s] - description:[%s] - reason:[%s] - try_time:[%s]' % (ex.error_code, ex.error, ex.request, try_time))
  114. time.sleep(sleep_time)
  115. if 2 * sleep_time < _MAX_BACKOFF_DELAY:
  116. sleep_time *= 2
  117. if not result:
  118. raise APIError('-3', 'retry %s time failure' % retry_times, 'request error')
  119. return result