[Add] 我觉得还是有onFail好,不过不再是用自定义callback的形式,而是重载的形式。对应的,RequestStatus中的状态也增加了。

This commit is contained in:
nanoric 2018-10-09 06:07:50 -04:00
parent 7e56c3fd49
commit 54b93a89b5

View File

@ -1,7 +1,6 @@
# encoding: UTF-8
########################################################################
import sys
from Queue import Empty, Queue
from abc import abstractmethod
@ -9,14 +8,14 @@ from multiprocessing.dummy import Pool
import requests
from enum import Enum
########################################################################
from typing import Any, Callable
class RequestStatus(Enum):
ready = 0 # 刚刚构建
finished = 1 # 请求成功 code == 200
error = 2 # 发生错误 网络错误、json解析错误等等
success = 1 # 请求成功 code == 200
failed = 2
error = 3 # 发生错误 网络错误、json解析错误等等
########################################################################
@ -39,6 +38,18 @@ class Request(object):
def id(self):
return self._id
#----------------------------------------------------------------------
@property
def success(self):
assert self.finished, "'success' property is only available after request is finished"
return self._status == RequestStatus.success
#----------------------------------------------------------------------
@property
def failed(self):
assert self.finished, "'failed' property is only available after request is finished"
return self._status == RequestStatus.failed
#----------------------------------------------------------------------
@property
def finished(self):
@ -54,7 +65,10 @@ class Request(object):
class HttpClient(object):
"""
HTTP 客户端目前是为了对接各种RESTFulAPI而设计的
一般情况下应该
如果需要给请求加上签名请重载beforeRequest函数
如果需要处理非200的请求请重载onFailed函数
如果捕获Python内部错误例如网络连接失败等等请重载onError函数
"""
#----------------------------------------------------------------------
@ -69,11 +83,11 @@ class HttpClient(object):
self._queue = Queue()
self._pool = None # type: Pool
#----------------------------------------------------------------------
def init(self, urlBase):
self.urlBase = urlBase
#----------------------------------------------------------------------
def setSessionProvider(self, sessionProvider):
"""
@ -102,7 +116,7 @@ class HttpClient(object):
#----------------------------------------------------------------------
def addReq(self, method, path, callback, params=None, data=None,
extra=None): # type: (str, str, Callable[[int, dict, Request], Any], dict, dict, Any)->Any
extra=None): # type: (str, str, Callable[[dict, Request], Any], dict, dict, Any)->Request
"""
发送一个请求
:param method: GET, POST, PUT, DELETE, QUERY
@ -113,7 +127,7 @@ class HttpClient(object):
:param data: dict for body
:return:
"""
req = Request(extra=extra)
self._queue.put((method, path, callback, params, data, req))
return req
@ -130,20 +144,31 @@ class HttpClient(object):
#----------------------------------------------------------------------
@abstractmethod
def beforeRequest(self, method, path, params, data): # type: (str, str, dict, dict)->(str, dict, dict, dict)
def beforeRequest(self, method, path, params, data): # type: (str, str, dict, dict)->(str, str, dict, dict, dict)
"""
所有请求在发送之前都会经过这个函数
签名之类的前奏可以在这里面实现
@:return (method, path, params, body, headers) body可以是request中data参数能接收的任意类型例如bytes,str,dict都可以
"""
pass
return method, path, params, data, {}
#----------------------------------------------------------------------
def onFailed(self, httpStatusCode, data, req):
"""
请求失败处理函数HttpStatusCode!=200.
默认行为是打印到stderr
@:param data 这个data是原始数据并不是dict而且有可能为null
"""
print("req {} failed with {}: \n"
"{}\n".format(req.id, httpStatusCode, data))
#----------------------------------------------------------------------
def onError(self, exceptionType, exceptionValue, tb, req):
"""
Python内部错误处理默认行为是仍给excepthook
"""
sys.stderr.write("on req : {}".format(req.id))
print("error in req : {}\n".format(req.id))
sys.excepthook(exceptionType, exceptionValue, tb)
#----------------------------------------------------------------------
@ -151,21 +176,20 @@ class HttpClient(object):
session): # type: (str, str, callable, dict, dict, Request, requests.Session)->None
"""处理请求"""
try:
res = self.beforeRequest(method, path, params, data)
if res is None:
headers = {}
else:
method, path, params, data, headers = res
method, path, params, data, headers = self.beforeRequest(method, path, params, data)
url = self.urlBase + path
resp = session.request(method, url, headers=headers, params=params, data=data)
code = resp.status_code
jsonBody = resp.json()
req._status = RequestStatus.finished
callback(code, jsonBody, req)
httpStatusCode = resp.status_code
if httpStatusCode == 200:
jsonBody = resp.json()
callback(jsonBody, req)
req._status = RequestStatus.success
else:
req._status = RequestStatus.failed
self.onFailed(httpStatusCode, data, req)
except:
req._status = RequestStatus.error
t, v, tb = sys.exc_info()