diff --git a/LunaTranslator/LunaTranslator/gui/setting_about.py b/LunaTranslator/LunaTranslator/gui/setting_about.py index ed125a6d..ff469bab 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_about.py +++ b/LunaTranslator/LunaTranslator/gui/setting_about.py @@ -77,9 +77,7 @@ def updatemethod(info, self): savep = gobject.getcachedir("update/LunaTranslator{}.zip".format(bit)) - r2 = requests.get( - url, stream=True, verify=False, proxies=getproxy(("github", "download")) - ) + r2 = requests.head(url, verify=False, proxies=getproxy(("github", "download"))) size = int(r2.headers["Content-Length"]) if check_interrupt(): return diff --git a/LunaTranslator/LunaTranslator/network/libcurl/libcurl.py b/LunaTranslator/LunaTranslator/network/libcurl/libcurl.py index 3a001120..9366c801 100644 --- a/LunaTranslator/LunaTranslator/network/libcurl/libcurl.py +++ b/LunaTranslator/LunaTranslator/network/libcurl/libcurl.py @@ -153,6 +153,7 @@ class CURLoption(c_int): HEADERDATA = CURLOPTTYPE_CBPOINT + 29 COOKIEFILE = CURLOPTTYPE_STRINGPOINT + 31 CUSTOMREQUEST = CURLOPTTYPE_STRINGPOINT + 36 + NOBODY = CURLOPTTYPE_LONG + 44 POST = CURLOPTTYPE_LONG + 47 FOLLOWLOCATION = CURLOPTTYPE_LONG + 52 POSTFIELDSIZE = CURLOPTTYPE_LONG + 60 diff --git a/LunaTranslator/LunaTranslator/network/libcurl/requester.py b/LunaTranslator/LunaTranslator/network/libcurl/requester.py index a92eeb54..8d890245 100644 --- a/LunaTranslator/LunaTranslator/network/libcurl/requester.py +++ b/LunaTranslator/LunaTranslator/network/libcurl/requester.py @@ -154,7 +154,7 @@ class Requester(Requester_common): curl_easy_setopt(curl, CURLoption.COOKIE, cookie.encode("utf8")) @ExceptionFilter - def request( + def request_impl( self, method, scheme, @@ -190,8 +190,9 @@ class Requester(Requester_common): headers["Accept-Encoding"].encode("utf8"), ) - curl_easy_setopt(curl, CURLoption.CUSTOMREQUEST, method.upper().encode("utf8")) - + if method == "HEAD": + curl_easy_setopt(curl, CURLoption.NOBODY, 1) + curl_easy_setopt(curl, CURLoption.CUSTOMREQUEST, method.encode("utf8")) self.last_error = curl_easy_setopt(curl, CURLoption.URL, url.encode("utf8")) self.raise_for_status() curl_easy_setopt(curl, CURLoption.PORT, port) diff --git a/LunaTranslator/LunaTranslator/network/winhttp/requester.py b/LunaTranslator/LunaTranslator/network/winhttp/requester.py index a2050fa8..4eb28ec1 100644 --- a/LunaTranslator/LunaTranslator/network/winhttp/requester.py +++ b/LunaTranslator/LunaTranslator/network/winhttp/requester.py @@ -141,7 +141,7 @@ class Requester(Requester_common): raise WinhttpException(GetLastError()) @ExceptionFilter - def request( + def request_impl( self, method, scheme, diff --git a/LunaTranslator/LunaTranslator/requests.py b/LunaTranslator/LunaTranslator/requests.py index 64e5efed..8fa1f6cb 100644 --- a/LunaTranslator/LunaTranslator/requests.py +++ b/LunaTranslator/LunaTranslator/requests.py @@ -124,65 +124,14 @@ class Requester_common: Accept_Encoding = "gzip, deflate, br" default_UA = default_UA - def request(self, *argc) -> ResponseBase: ... - - def _parseheader(self, headers, cookies): - _x = [] - - if cookies: - cookie = self._parsecookie(cookies) - headers.update({"Cookie": cookie}) - for k in sorted(headers.keys()): - _x.append("{}: {}".format(k, headers[k])) - return _x - - def _parsecookie(self, cookie): - _c = [] - for k, v in cookie.items(): - _c.append("{}={}".format(k, v)) - return "; ".join(_c) - - def _parseheader2dict(self, headerstr): - # print(headerstr) - header = CaseInsensitiveDict() - cookie = {} - for line in headerstr.split("\r\n")[1:]: - idx = line.find(": ") - if idx == -1: - continue - if line[:idx].lower() == "set-cookie": - _c = line[idx + 2 :].split("; ")[0] - _idx = _c.find("=") - cookie[_c[:_idx]] = _c[_idx + 1 :] - else: - header[line[:idx]] = line[idx + 2 :] - return CaseInsensitiveDict(header), cookie - - -class Session: - def __init__(self) -> None: - self.requester = None - self.requester_type = None - self.default_UA = default_UA - - self.last_error = 0 - self.cookies = {} - self.headers = CaseInsensitiveDict( - { - "User-Agent": self.default_UA, - # "Accept-Encoding": "gzip, deflate, br", - "Accept": "*/*", - "Connection": "keep-alive", - } - ) - self._requester = None - self._libidx = -1 - - def __enter__(self): - return self - - def __exit__(self, *args): - pass + default_headers = CaseInsensitiveDict( + { + "User-Agent": default_UA, + # "Accept-Encoding": "gzip, deflate, br", + "Accept": "*/*", + "Connection": "keep-alive", + } + ) @staticmethod def _encode_params(data): @@ -207,6 +156,31 @@ class Session: else: return data + def _parseurl(self, url: str, param): + url = url.strip() + scheme, server, path, query, _ = urlsplit(url) + if scheme not in ["https", "http"]: + raise Exception("unknown scheme " + scheme) + spl = server.split(":") + if len(spl) == 2: + server = spl[0] + port = int(spl[1]) + elif len(spl) == 1: + spl[0] + if scheme == "https": + port = 443 + else: + port = 80 + else: + raise Exception("invalid url") + if param: + param = self._encode_params(param) + query += ("&" if len(query) else "") + param + if len(query): + path += "?" + query + url = scheme + "://" + server + path + return scheme, server, port, path, url + def _parsedata(self, data, headers, js): if data is None and js is None: @@ -232,42 +206,6 @@ class Session: # print(headers,dataptr,datalen) return headers, dataptr, datalen - def _parseurl(self, url, param): - url = url.strip() - scheme, server, path, query, _ = urlsplit(url) - if scheme not in ["https", "http"]: - raise Exception("unknown scheme " + scheme) - spl = server.split(":") - if len(spl) == 2: - server = spl[0] - port = int(spl[1]) - elif len(spl) == 1: - spl[0] - if scheme == "https": - port = 443 - else: - port = 80 - else: - raise Exception("invalid url") - if param: - param = self._encode_params(param) - query += ("&" if len(query) else "") + param - if len(query): - path += "?" + query - url = scheme + "://" + server + path - return scheme, server, port, path, url - - def loadrequester(self) -> Requester_common: - if self._libidx == globalconfig["network"]: - return self._requester - if globalconfig["network"] == 1: - from network.libcurl.requester import Requester - elif globalconfig["network"] == 0: - from network.winhttp.requester import Requester - self._requester = Requester() - self._libidx = globalconfig["network"] - return self._requester - def request( self, method, @@ -286,10 +224,10 @@ class Session: stream=None, verify=False, cert=None, - ): - requester = self.loadrequester() - _h = self.headers.copy() - _h.update({"Accept-Encoding": requester.Accept_Encoding}) + ) -> ResponseBase: + + _h = self.default_headers.copy() + _h.update({"Accept-Encoding": self.Accept_Encoding}) if headers: _h.update(headers) headers = _h @@ -317,9 +255,7 @@ class Session: except: print("Error invalid timeout", timeout) timeout = None - if cookies: - self.cookies.update(cookies) - response = requester.request( + return self.request_impl( method, scheme, server, @@ -327,7 +263,7 @@ class Session: param, url, headers, - self.cookies, + cookies, dataptr, datalen, proxy, @@ -336,6 +272,105 @@ class Session: timeout, allow_redirects, ) + + def request_impl(self, *argc) -> ResponseBase: ... + + def _parseheader(self, headers: CaseInsensitiveDict, cookies: dict): + _x = [] + + if cookies: + cookie = self._parsecookie(cookies) + headers.update({"Cookie": cookie}) + for k in sorted(headers.keys()): + _x.append("{}: {}".format(k, headers[k])) + return _x + + def _parsecookie(self, cookie: dict): + _c = [] + for k, v in cookie.items(): + _c.append("{}={}".format(k, v)) + return "; ".join(_c) + + def _parseheader2dict(self, headerstr: str): + # print(headerstr) + header = CaseInsensitiveDict() + cookie = {} + for line in headerstr.split("\r\n")[1:]: + idx = line.find(": ") + if idx == -1: + continue + if line[:idx].lower() == "set-cookie": + _c = line[idx + 2 :].split("; ")[0] + _idx = _c.find("=") + cookie[_c[:_idx]] = _c[_idx + 1 :] + else: + header[line[:idx]] = line[idx + 2 :] + return CaseInsensitiveDict(header), cookie + + +class Session: + cookies = {} + _requester = None + _libidx = -1 + + def __enter__(self): + return self + + def __exit__(self, *args): + pass + + @property + def requester(self) -> Requester_common: + if self._libidx == globalconfig["network"]: + return self._requester + if globalconfig["network"] == 1: + from network.libcurl.requester import Requester + elif globalconfig["network"] == 0: + from network.winhttp.requester import Requester + self._requester = Requester() + self._libidx = globalconfig["network"] + return self._requester + + def request( + self, + method: str, + url: str, + params=None, + data=None, + headers=None, + proxies=None, + json=None, + cookies=None, + files=None, + auth=None, + timeout=None, + allow_redirects=True, + hooks=None, + stream=None, + verify=False, + cert=None, + ): + + if cookies: + self.cookies.update(cookies) + response = self.requester.request( + method.upper(), + url, + params, + data, + headers, + proxies, + json, + self.cookies, + files, + auth, + timeout, + allow_redirects, + hooks, + stream, + verify, + cert, + ) self.cookies.update(response.cookies) response.cookies.update(self.cookies) return response @@ -355,6 +390,9 @@ class Session: def delete(self, url, **kwargs): return self.request("DELETE", url, **kwargs) + def head(self, url, **kwargs): + return self.request("HEAD", url, **kwargs) + def request(method, url, **kwargs): with Session() as session: @@ -371,3 +409,4 @@ post = partial(request, "POST") options = partial(request, "OPTIONS") patch = partial(request, "PATCH") delete = partial(request, "DELETE") +head = partial(request, "HEAD")