This commit is contained in:
恍兮惚兮 2024-07-08 20:30:14 +08:00
parent 0657cfc6b7
commit 220b8be23c
5 changed files with 46 additions and 54 deletions

View File

@ -154,8 +154,10 @@ class CURLoption(c_int):
CURLOPT_COOKIEFILE = CURLOPTTYPE_STRINGPOINT + 31
CURLOPT_CUSTOMREQUEST = CURLOPTTYPE_STRINGPOINT + 36
CURLOPT_POST = CURLOPTTYPE_LONG + 47
CURLOPT_FOLLOWLOCATION = CURLOPTTYPE_LONG + 52
CURLOPT_POSTFIELDSIZE = CURLOPTTYPE_LONG + 60
CURLOPT_SSL_VERIFYPEER = CURLOPTTYPE_LONG + 64
CURLOPT_MAXREDIRS = CURLOPTTYPE_LONG + 68
CURLOPT_HEADERFUNCTION = CURLOPTTYPE_FUNCTIONPOINT + 79
CURLOPT_HTTPGET = CURLOPTTYPE_LONG + 80
CURLOPT_SSL_VERIFYHOST = CURLOPTTYPE_LONG + 81

View File

@ -86,6 +86,11 @@ class Session(Sessionbase):
self.last_error = curl_easy_perform(curl)
self.raise_for_status()
def _set_allow_redirects(self, curl, allow_redirects):
curl_easy_setopt(curl, CURLoption.CURLOPT_FOLLOWLOCATION, int(allow_redirects))
# curl_easy_setopt(curl, CURLoption.CURLOPT_MAXREDIRS, 100) #默认50够了
@ExceptionFilter
def request_impl(
self,
@ -103,6 +108,7 @@ class Session(Sessionbase):
stream,
verify,
timeout,
allow_redirects,
):
curl = AutoCURLHandle(curl_easy_init())
curl_easy_setopt(curl, CURLoption.CURLOPT_COOKIEJAR, "")
@ -146,6 +152,7 @@ class Session(Sessionbase):
self._set_verify(curl, verify)
self._set_proxy(curl, proxy)
self._set_allow_redirects(curl, allow_redirects)
if datalen:
curl_easy_setopt(curl, CURLoption.CURLOPT_POSTFIELDS, dataptr)
curl_easy_setopt(curl, CURLoption.CURLOPT_POSTFIELDSIZE, datalen)
@ -154,7 +161,9 @@ class Session(Sessionbase):
resp.keeprefs.append(curl)
if stream:
def WriteMemoryCallback(queue, contents, size, nmemb, userp):
def WriteMemoryCallback(headerqueue, queue, contents, size, nmemb, userp):
if headerqueue:
headerqueue.put(0)
realsize = size * nmemb
queue.put(cast(contents, POINTER(c_char))[:realsize])
return realsize
@ -162,9 +171,11 @@ class Session(Sessionbase):
_content = []
_headers = []
headerqueue = queue.Queue()
keepref1 = WRITEFUNCTION(functools.partial(WriteMemoryCallback, resp.queue))
keepref1 = WRITEFUNCTION(
functools.partial(WriteMemoryCallback, headerqueue, resp.queue)
)
keepref2 = WRITEFUNCTION(
functools.partial(WriteMemoryCallback, headerqueue)
functools.partial(WriteMemoryCallback, None, headerqueue)
)
curl_easy_setopt(
curl,
@ -185,7 +196,7 @@ class Session(Sessionbase):
self._perform(curl)
except:
print_exc()
headerqueue.put(None)
headerqueue.put(1)
error = True
resp.queue.put(None)
if error:
@ -195,27 +206,16 @@ class Session(Sessionbase):
threading.Thread(target=___perform, daemon=True).start()
headerb = ""
cnt = 1
while True:
_headerb = headerqueue.get()
if _headerb is None:
if _headerb == 0:
break
elif _headerb == 1:
self.raise_for_status()
_headerb = _headerb.decode("utf8")
if _headerb.endswith(
"200 Connection established\r\n"
): # HTTP/1.1 200 Connection established\r\n
cnt += 1
elif _headerb == "\r\n":
cnt -= 1
if cnt == 0:
break
else:
# 有proxy时proxy也有可能有header.
headerb = ""
else:
headerb += _headerb
if _headerb.startswith("HTTP/"):
headerb = ""
headerb += _headerb
resp.headers = self._update_header_cookie(headerb)
resp.status_code = self._getStatusCode(curl)
else:

View File

@ -313,38 +313,9 @@ class Sessionbase:
stream,
verify,
timeout,
allow_redirects,
)
while allow_redirects and (
_.status_code == 301 or _.status_code == 302 or _.status_code == 307
):
location = _.headers["Location"]
if location.startswith("/"): # vndb
url = url = scheme + "://" + server + location
param = location
elif location.startswith(
"http"
): # https://api.github.com/repos/XXX/XXX/zipball
scheme, server, port, param, url = self._parseurl(location, None)
else:
raise Exception("redirect {}: {}".format(_.status_code, location))
_ = self.request_impl(
method,
scheme,
server,
port,
param,
url,
headers,
cookies,
dataptr,
datalen,
proxy,
stream,
verify,
timeout,
)
return _
def get(self, url, **kwargs):

View File

@ -118,13 +118,25 @@ class Session(Sessionbase):
if proxy:
winhttpsetproxy(hsess, proxy)
def _set_verify(self, curl, verify):
def _set_verify(self, hRequest, verify):
if verify == False:
dwFlags = DWORD(SECURITY_FLAG_IGNORE_ALL_CERT_ERRORS)
WinHttpSetOption(
curl, WINHTTP_OPTION_SECURITY_FLAGS, pointer(dwFlags), sizeof(dwFlags)
hRequest,
WINHTTP_OPTION_SECURITY_FLAGS,
pointer(dwFlags),
sizeof(dwFlags),
)
def _set_allow_redirects(self, hRequest, allow_redirects):
if allow_redirects:
dwFlags = DWORD(WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS)
else:
dwFlags = DWORD(WINHTTP_OPTION_REDIRECT_POLICY_NEVER)
WinHttpSetOption(
hRequest, WINHTTP_OPTION_REDIRECT_POLICY, pointer(dwFlags), sizeof(dwFlags)
)
@ExceptionFilter
def request_impl(
self,
@ -142,6 +154,7 @@ class Session(Sessionbase):
stream,
verify,
timeout,
allow_redirects,
):
headers = self._parseheader(headers, cookies)
flag = WINHTTP_FLAG_SECURE if scheme == "https" else 0
@ -168,7 +181,7 @@ class Session(Sessionbase):
raise WinhttpException(GetLastError())
self._set_verify(hRequest, verify)
self._set_proxy(hRequest, proxy)
self._set_allow_redirects(hRequest, allow_redirects)
succ = WinHttpSendRequest(
hRequest, headers, -1, dataptr, datalen, datalen, None
)

View File

@ -2,6 +2,7 @@ from ctypes import windll, POINTER, pointer, Structure, sizeof
from ctypes.wintypes import LPCWSTR, DWORD, LPVOID, WORD, BOOL, LPCVOID, LPWSTR, USHORT
from network.requests_common import NetWorkException
class WinhttpException(NetWorkException):
ERROR_INVALID_PARAMETER = 87
ERROR_INVALID_OPERATION = 4317
@ -225,3 +226,8 @@ WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE = 3
WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE = 4
ERROR_SUCCESS = 0
WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS = 1000
WINHTTP_OPTION_REDIRECT_POLICY = 88
WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2
WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0