Hello community,
here is the log from the commit of package python-httplib2 for openSUSE:Factory
checked in at 2020-04-09 23:14:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-httplib2 (Old)
and /work/SRC/openSUSE:Factory/.python-httplib2.new.3248 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-httplib2"
Thu Apr 9 23:14:19 2020 rev:45 rq:791798 version:0.17.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-httplib2/python-httplib2.changes
2019-11-04 17:04:44.780154718 +0100
+++
/work/SRC/openSUSE:Factory/.python-httplib2.new.3248/python-httplib2.changes
2020-04-09 23:14:20.522205905 +0200
@@ -1,0 +2,14 @@
+Mon Apr 6 14:02:25 UTC 2020 - Marketa Calabkova <[email protected]>
+
+- Update to 0.17.1
+ * python3: no_proxy was not checked with https
+ * feature: Http().redirect_codes set, works after follow(_all)_redirects
check
+ This allows one line workaround for old gcloud library that uses 308
+ response without redirect semantics.
+ * IMPORTANT cache invalidation change, fix 307 keep method, add 308 Redirects
+ * proxy: username/password as str compatible with pysocks
+ * python2: regression in connect() error handling
+ * add support for password protected certificate files
+ * feature: Http.close() to clean persistent connections and sensitive data
+
+-------------------------------------------------------------------
Old:
----
httplib2-0.14.0.tar.gz
New:
----
httplib2-0.17.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-httplib2.spec ++++++
--- /var/tmp/diff_new_pack.MrWjrw/_old 2020-04-09 23:14:21.166206277 +0200
+++ /var/tmp/diff_new_pack.MrWjrw/_new 2020-04-09 23:14:21.170206280 +0200
@@ -1,7 +1,7 @@
#
# spec file for package python-httplib2
#
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -20,7 +20,7 @@
# Tests require network connection
%bcond_with tests
Name: python-httplib2
-Version: 0.14.0
+Version: 0.17.1
Release: 0
Summary: A Python HTTP client library
License: MIT AND Apache-2.0 AND (MPL-1.1 OR GPL-2.0-or-later OR
LGPL-2.1-or-later)
++++++ httplib2-0.14.0.tar.gz -> httplib2-0.17.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/httplib2-0.14.0/PKG-INFO new/httplib2-0.17.1/PKG-INFO
--- old/httplib2-0.14.0/PKG-INFO 2019-09-27 06:52:00.000000000 +0200
+++ new/httplib2-0.17.1/PKG-INFO 2020-04-02 20:28:49.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: httplib2
-Version: 0.14.0
+Version: 0.17.1
Summary: A comprehensive HTTP client library.
Home-page: https://github.com/httplib2/httplib2
Author: Joe Gregorio
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/httplib2-0.14.0/python2/httplib2/__init__.py
new/httplib2-0.17.1/python2/httplib2/__init__.py
--- old/httplib2-0.14.0/python2/httplib2/__init__.py 2019-09-27
06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/python2/httplib2/__init__.py 2020-04-02
20:28:24.000000000 +0200
@@ -19,7 +19,7 @@
"Alex Yu",
]
__license__ = "MIT"
-__version__ = '0.14.0'
+__version__ = '0.17.1'
import base64
import calendar
@@ -76,7 +76,7 @@
def _ssl_wrap_socket(
- sock, key_file, cert_file, disable_validation, ca_certs, ssl_version,
hostname
+ sock, key_file, cert_file, disable_validation, ca_certs, ssl_version,
hostname, key_password
):
if disable_validation:
cert_reqs = ssl.CERT_NONE
@@ -90,11 +90,16 @@
context.verify_mode = cert_reqs
context.check_hostname = cert_reqs != ssl.CERT_NONE
if cert_file:
- context.load_cert_chain(cert_file, key_file)
+ if key_password:
+ context.load_cert_chain(cert_file, key_file, key_password)
+ else:
+ context.load_cert_chain(cert_file, key_file)
if ca_certs:
context.load_verify_locations(ca_certs)
return context.wrap_socket(sock, server_hostname=hostname)
else:
+ if key_password:
+ raise NotSupportedOnThisPlatform("Certificate with password is not
supported.")
return ssl.wrap_socket(
sock,
keyfile=key_file,
@@ -106,7 +111,7 @@
def _ssl_wrap_socket_unsupported(
- sock, key_file, cert_file, disable_validation, ca_certs, ssl_version,
hostname
+ sock, key_file, cert_file, disable_validation, ca_certs, ssl_version,
hostname, key_password
):
if not disable_validation:
raise CertificateValidationUnsupported(
@@ -114,6 +119,8 @@
"the ssl module installed. To avoid this error, install "
"the ssl module, or explicity disable validation."
)
+ if key_password:
+ raise NotSupportedOnThisPlatform("Certificate with password is not
supported.")
ssl_sock = socket.ssl(sock, key_file, cert_file)
return httplib.FakeSocket(sock, ssl_sock)
@@ -284,6 +291,12 @@
"upgrade",
]
+# https://tools.ietf.org/html/rfc7231#section-8.1.3
+SAFE_METHODS = ("GET", "HEAD") # TODO add "OPTIONS", "TRACE"
+
+# To change, assign to `Http().redirect_codes`
+REDIRECT_CODES = frozenset((300, 301, 302, 303, 307, 308))
+
def _get_end2end_headers(response):
hopbyhop = list(HOP_BY_HOP)
@@ -978,8 +991,13 @@
class KeyCerts(Credentials):
"""Identical to Credentials except that
name/password are mapped to key/cert."""
+ def add(self, key, cert, domain, password):
+ self.credentials.append((domain.lower(), key, cert, password))
- pass
+ def iter(self, domain):
+ for (cdomain, key, cert, password) in self.credentials:
+ if cdomain == "" or domain == cdomain:
+ yield (key, cert, password)
class AllHosts(object):
@@ -1150,7 +1168,6 @@
raise ProxiesUnavailableError(
"Proxy support missing but proxy use was requested!"
)
- msg = "getaddrinfo returns an empty list"
if self.proxy_info and self.proxy_info.isgood():
use_proxy = True
proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user,
proxy_pass, proxy_headers = (
@@ -1165,6 +1182,8 @@
host = self.host
port = self.port
+ socket_err = None
+
for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
@@ -1206,7 +1225,8 @@
self.sock.connect((self.host, self.port) + sa[2:])
else:
self.sock.connect(sa)
- except socket.error as msg:
+ except socket.error as e:
+ socket_err = e
if self.debuglevel > 0:
print("connect fail: (%s, %s)" % (self.host, self.port))
if use_proxy:
@@ -1229,7 +1249,7 @@
continue
break
if not self.sock:
- raise socket.error(msg)
+ raise socket_err or socket.error("getaddrinfo returns an empty
list")
class HTTPSConnectionWithTimeout(httplib.HTTPSConnection):
@@ -1253,10 +1273,19 @@
ca_certs=None,
disable_ssl_certificate_validation=False,
ssl_version=None,
+ key_password=None,
):
- httplib.HTTPSConnection.__init__(
- self, host, port=port, key_file=key_file, cert_file=cert_file,
strict=strict
- )
+ if key_password:
+ httplib.HTTPSConnection.__init__(self, host, port=port,
strict=strict)
+ self._context.load_cert_chain(cert_file, key_file, key_password)
+ self.key_file = key_file
+ self.cert_file = cert_file
+ self.key_password = key_password
+ else:
+ httplib.HTTPSConnection.__init__(
+ self, host, port=port, key_file=key_file, cert_file=cert_file,
strict=strict
+ )
+ self.key_password = None
self.timeout = timeout
self.proxy_info = proxy_info
if ca_certs is None:
@@ -1317,7 +1346,6 @@
def connect(self):
"Connect to a host on a given (SSL) port."
- msg = "getaddrinfo returns an empty list"
if self.proxy_info and self.proxy_info.isgood():
use_proxy = True
proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user,
proxy_pass, proxy_headers = (
@@ -1332,6 +1360,8 @@
host = self.host
port = self.port
+ socket_err = None
+
address_info = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
for family, socktype, proto, canonname, sockaddr in address_info:
try:
@@ -1366,6 +1396,7 @@
self.ca_certs,
self.ssl_version,
self.host,
+ self.key_password,
)
if self.debuglevel > 0:
print("connect: (%s, %s)" % (self.host, self.port))
@@ -1413,7 +1444,8 @@
raise
except (socket.timeout, socket.gaierror):
raise
- except socket.error as msg:
+ except socket.error as e:
+ socket_err = e
if self.debuglevel > 0:
print("connect fail: (%s, %s)" % (self.host, self.port))
if use_proxy:
@@ -1436,7 +1468,7 @@
continue
break
if not self.sock:
- raise socket.error(msg)
+ raise socket_err or socket.error("getaddrinfo returns an empty
list")
SCHEME_TO_CONNECTION = {
@@ -1515,7 +1547,10 @@
ca_certs=None,
disable_ssl_certificate_validation=False,
ssl_version=None,
+ key_password=None,
):
+ if key_password:
+ raise NotSupportedOnThisPlatform("Certificate with password is not
supported.")
httplib.HTTPSConnection.__init__(
self,
host,
@@ -1632,10 +1667,14 @@
# If set to False then no redirects are followed, even safe ones.
self.follow_redirects = True
+ self.redirect_codes = REDIRECT_CODES
+
# Which HTTP methods do we apply optimistic concurrency to, i.e.
# which methods get an "if-match:" etag header added to them.
self.optimistic_concurrency_methods = ["PUT", "PATCH"]
+ self.safe_methods = list(SAFE_METHODS)
+
# If 'follow_redirects' is True, and this is set to True then
# all redirecs are followed, including unsafe ones.
self.follow_all_redirects = False
@@ -1649,6 +1688,16 @@
# Keep Authorization: headers on a redirect.
self.forward_authorization_headers = False
+ def close(self):
+ """Close persistent connections, clear sensitive data.
+ Not thread-safe, requires external synchronization against concurrent
requests.
+ """
+ existing, self.connections = self.connections, {}
+ for _, c in existing.iteritems():
+ c.close()
+ self.certificates.clear()
+ self.clear_credentials()
+
def __getstate__(self):
state_dict = copy.copy(self.__dict__)
# In case request is augmented by some foreign object such as
@@ -1680,10 +1729,10 @@
any time a request requires authentication."""
self.credentials.add(name, password, domain)
- def add_certificate(self, key, cert, domain):
+ def add_certificate(self, key, cert, domain, password=None):
"""Add a key and cert that will be used
any time a request requires authentication."""
- self.certificates.add(key, cert, domain)
+ self.certificates.add(key, cert, domain, password)
def clear_credentials(self):
"""Remove all the names and passwords
@@ -1819,10 +1868,10 @@
if (
self.follow_all_redirects
- or (method in ["GET", "HEAD"])
- or response.status == 303
+ or method in self.safe_methods
+ or response.status in (303, 308)
):
- if self.follow_redirects and response.status in [300, 301, 302,
303, 307]:
+ if self.follow_redirects and response.status in
self.redirect_codes:
# Pick out the location header and basically start from the
beginning
# remembering first to strip the ETag header and decrement our
'depth'
if redirections:
@@ -1842,7 +1891,7 @@
response["location"] = urlparse.urljoin(
absolute_uri, location
)
- if response.status == 301 and method in ["GET", "HEAD"]:
+ if response.status == 308 or (response.status == 301 and
method in self.safe_methods):
response["-x-permanent-redirect-url"] =
response["location"]
if "content-location" not in response:
response["content-location"] = absolute_uri
@@ -1879,7 +1928,7 @@
response,
content,
)
- elif response.status in [200, 203] and method in ["GET", "HEAD"]:
+ elif response.status in [200, 203] and method in self.safe_methods:
# Don't cache 206's since we aren't going to handle byte range
requests
if "content-location" not in response:
response["content-location"] = absolute_uri
@@ -1925,7 +1974,7 @@
a string that contains the response entity body.
"""
conn_key = ''
-
+
try:
if headers is None:
headers = {}
@@ -1958,6 +2007,7 @@
ca_certs=self.ca_certs,
disable_ssl_certificate_validation=self.disable_ssl_certificate_validation,
ssl_version=self.ssl_version,
+ key_password=certs[0][2],
)
else:
conn = self.connections[conn_key] = connection_type(
@@ -1978,6 +2028,7 @@
headers["accept-encoding"] = "gzip, deflate"
info = email.Message.Message()
+ cachekey = None
cached_value = None
if self.cache:
cachekey = defrag_uri.encode("utf-8")
@@ -1998,8 +2049,6 @@
self.cache.delete(cachekey)
cachekey = None
cached_value = None
- else:
- cachekey = None
if (
method in self.optimistic_concurrency_methods
@@ -2011,13 +2060,15 @@
# http://www.w3.org/1999/04/Editing/
headers["if-match"] = info["etag"]
- if method not in ["GET", "HEAD"] and self.cache and cachekey:
- # RFC 2616 Section 13.10
+ # https://tools.ietf.org/html/rfc7234
+ # A cache MUST invalidate the effective Request URI as well as
[...] Location and Content-Location
+ # when a non-error status code is received in response to an
unsafe request method.
+ if self.cache and cachekey and method not in self.safe_methods:
self.cache.delete(cachekey)
# Check the vary header in the cache to see if this request
# matches what varies in the cache.
- if method in ["GET", "HEAD"] and "vary" in info:
+ if method in self.safe_methods and "vary" in info:
vary = info["vary"]
vary_headers = vary.lower().replace(" ", "").split(",")
for header in vary_headers:
@@ -2028,11 +2079,14 @@
break
if (
- cached_value
- and method in ["GET", "HEAD"]
- and self.cache
+ self.cache
+ and cached_value
+ and (method in self.safe_methods or info["status"] == "308")
and "range" not in headers
):
+ redirect_method = method
+ if info["status"] not in ("307", "308"):
+ redirect_method = "GET"
if "-x-permanent-redirect-url" in info:
# Should cached permanent redirects be counted in our
redirection count? For now, yes.
if redirections <= 0:
@@ -2043,7 +2097,7 @@
)
(response, new_content) = self.request(
info["-x-permanent-redirect-url"],
- method="GET",
+ method=redirect_method,
headers=headers,
redirections=redirections - 1,
)
@@ -2140,7 +2194,7 @@
conn = self.connections.pop(conn_key, None)
if conn:
conn.close()
-
+
if self.force_exception_to_status_code:
if isinstance(e, HttpLib2ErrorWithResponse):
response = e.response
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/httplib2-0.14.0/python2/httplib2/socks.py
new/httplib2-0.17.1/python2/httplib2/socks.py
--- old/httplib2-0.14.0/python2/httplib2/socks.py 2019-09-27
06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/python2/httplib2/socks.py 2020-04-02
20:28:24.000000000 +0200
@@ -238,7 +238,15 @@
headers - Additional or modified headers for the proxy connect
request.
"""
- self.__proxy = (proxytype, addr, port, rdns, username, password,
headers)
+ self.__proxy = (
+ proxytype,
+ addr,
+ port,
+ rdns,
+ username.encode() if username else None,
+ password.encode() if password else None,
+ headers,
+ )
def __negotiatesocks5(self, destaddr, destport):
"""__negotiatesocks5(self,destaddr,destport)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/httplib2-0.14.0/python3/httplib2/__init__.py
new/httplib2-0.17.1/python3/httplib2/__init__.py
--- old/httplib2-0.14.0/python3/httplib2/__init__.py 2019-09-27
06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/python3/httplib2/__init__.py 2020-04-02
20:28:24.000000000 +0200
@@ -15,7 +15,7 @@
"Alex Yu",
]
__license__ = "MIT"
-__version__ = '0.14.0'
+__version__ = '0.17.1'
import base64
import calendar
@@ -161,6 +161,13 @@
"upgrade",
]
+# https://tools.ietf.org/html/rfc7231#section-8.1.3
+SAFE_METHODS = ("GET", "HEAD", "OPTIONS", "TRACE")
+
+# To change, assign to `Http().redirect_codes`
+REDIRECT_CODES = frozenset((300, 301, 302, 303, 307, 308))
+
+
from httplib2 import certs
CA_CERTS = certs.where()
@@ -175,7 +182,7 @@
def _build_ssl_context(
disable_ssl_certificate_validation, ca_certs, cert_file=None,
key_file=None,
- maximum_version=None, minimum_version=None,
+ maximum_version=None, minimum_version=None, key_password=None,
):
if not hasattr(ssl, "SSLContext"):
raise RuntimeError("httplib2 requires Python 3.2+ for ssl.SSLContext")
@@ -207,7 +214,7 @@
context.load_verify_locations(ca_certs)
if cert_file:
- context.load_cert_chain(cert_file, key_file)
+ context.load_cert_chain(cert_file, key_file, key_password)
return context
@@ -315,7 +322,7 @@
# Whether to use a strict mode to parse WWW-Authenticate headers
# Might lead to bad results in case of ill-formed header value,
# so disabled by default, falling back to relaxed parsing.
-# Set to true to turn on, usefull for testing servers.
+# Set to true to turn on, useful for testing servers.
USE_WWW_AUTH_STRICT_PARSING = 0
# In regex below:
@@ -959,8 +966,13 @@
class KeyCerts(Credentials):
"""Identical to Credentials except that
name/password are mapped to key/cert."""
+ def add(self, key, cert, domain, password):
+ self.credentials.append((domain.lower(), key, cert, password))
- pass
+ def iter(self, domain):
+ for (cdomain, key, cert, password) in self.credentials:
+ if cdomain == "" or domain == cdomain:
+ yield (key, cert, password)
class AllHosts(object):
@@ -999,10 +1011,10 @@
proxy_headers: Additional or modified headers for the proxy connect
request.
"""
- if isinstance(proxy_user, str):
- proxy_user = proxy_user.encode()
- if isinstance(proxy_pass, str):
- proxy_pass = proxy_pass.encode()
+ if isinstance(proxy_user, bytes):
+ proxy_user = proxy_user.decode()
+ if isinstance(proxy_pass, bytes):
+ proxy_pass = proxy_pass.decode()
self.proxy_type, self.proxy_host, self.proxy_port, self.proxy_rdns,
self.proxy_user, self.proxy_pass, self.proxy_headers = (
proxy_type,
proxy_host,
@@ -1245,6 +1257,7 @@
disable_ssl_certificate_validation=False,
tls_maximum_version=None,
tls_minimum_version=None,
+ key_password=None,
):
self.disable_ssl_certificate_validation =
disable_ssl_certificate_validation
@@ -1257,19 +1270,21 @@
context = _build_ssl_context(
self.disable_ssl_certificate_validation, self.ca_certs, cert_file,
key_file,
maximum_version=tls_maximum_version,
minimum_version=tls_minimum_version,
+ key_password=key_password,
)
super(HTTPSConnectionWithTimeout, self).__init__(
host,
port=port,
- key_file=key_file,
- cert_file=cert_file,
timeout=timeout,
context=context,
)
+ self.key_file = key_file
+ self.cert_file = cert_file
+ self.key_password = key_password
def connect(self):
"""Connect to a host on a given (SSL) port."""
- if self.proxy_info and self.proxy_info.isgood():
+ if self.proxy_info and self.proxy_info.isgood() and
self.proxy_info.applies_to(self.host):
use_proxy = True
proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user,
proxy_pass, proxy_headers = (
self.proxy_info.astuple()
@@ -1459,10 +1474,14 @@
# If set to False then no redirects are followed, even safe ones.
self.follow_redirects = True
+ self.redirect_codes = REDIRECT_CODES
+
# Which HTTP methods do we apply optimistic concurrency to, i.e.
# which methods get an "if-match:" etag header added to them.
self.optimistic_concurrency_methods = ["PUT", "PATCH"]
+ self.safe_methods = list(SAFE_METHODS)
+
# If 'follow_redirects' is True, and this is set to True then
# all redirecs are followed, including unsafe ones.
self.follow_all_redirects = False
@@ -1476,6 +1495,16 @@
# Keep Authorization: headers on a redirect.
self.forward_authorization_headers = False
+ def close(self):
+ """Close persistent connections, clear sensitive data.
+ Not thread-safe, requires external synchronization against concurrent
requests.
+ """
+ existing, self.connections = self.connections, {}
+ for _, c in existing.items():
+ c.close()
+ self.certificates.clear()
+ self.clear_credentials()
+
def __getstate__(self):
state_dict = copy.copy(self.__dict__)
# In case request is augmented by some foreign object such as
@@ -1507,10 +1536,10 @@
any time a request requires authentication."""
self.credentials.add(name, password, domain)
- def add_certificate(self, key, cert, domain):
+ def add_certificate(self, key, cert, domain, password=None):
"""Add a key and cert that will be used
any time a request requires authentication."""
- self.certificates.add(key, cert, domain)
+ self.certificates.add(key, cert, domain, password)
def clear_credentials(self):
"""Remove all the names and passwords
@@ -1645,10 +1674,10 @@
if (
self.follow_all_redirects
- or (method in ["GET", "HEAD"])
- or response.status == 303
+ or method in self.safe_methods
+ or response.status in (303, 308)
):
- if self.follow_redirects and response.status in [300, 301, 302,
303, 307]:
+ if self.follow_redirects and response.status in
self.redirect_codes:
# Pick out the location header and basically start from the
beginning
# remembering first to strip the ETag header and decrement our
'depth'
if redirections:
@@ -1668,7 +1697,7 @@
response["location"] = urllib.parse.urljoin(
absolute_uri, location
)
- if response.status == 301 and method in ["GET", "HEAD"]:
+ if response.status == 308 or (response.status == 301 and
(method in self.safe_methods)):
response["-x-permanent-redirect-url"] =
response["location"]
if "content-location" not in response:
response["content-location"] = absolute_uri
@@ -1705,7 +1734,7 @@
response,
content,
)
- elif response.status in [200, 203] and method in ["GET", "HEAD"]:
+ elif response.status in [200, 203] and method in self.safe_methods:
# Don't cache 206's since we aren't going to handle byte range
requests
if "content-location" not in response:
response["content-location"] = absolute_uri
@@ -1782,6 +1811,7 @@
disable_ssl_certificate_validation=self.disable_ssl_certificate_validation,
tls_maximum_version=self.tls_maximum_version,
tls_minimum_version=self.tls_minimum_version,
+ key_password=certs[0][2],
)
else:
conn = self.connections[conn_key] = connection_type(
@@ -1803,6 +1833,7 @@
headers["accept-encoding"] = "gzip, deflate"
info = email.message.Message()
+ cachekey = None
cached_value = None
if self.cache:
cachekey = defrag_uri
@@ -1820,8 +1851,6 @@
self.cache.delete(cachekey)
cachekey = None
cached_value = None
- else:
- cachekey = None
if (
method in self.optimistic_concurrency_methods
@@ -1833,13 +1862,15 @@
# http://www.w3.org/1999/04/Editing/
headers["if-match"] = info["etag"]
- if method not in ["GET", "HEAD"] and self.cache and cachekey:
- # RFC 2616 Section 13.10
+ # https://tools.ietf.org/html/rfc7234
+ # A cache MUST invalidate the effective Request URI as well as
[...] Location and Content-Location
+ # when a non-error status code is received in response to an
unsafe request method.
+ if self.cache and cachekey and method not in self.safe_methods:
self.cache.delete(cachekey)
# Check the vary header in the cache to see if this request
# matches what varies in the cache.
- if method in ["GET", "HEAD"] and "vary" in info:
+ if method in self.safe_methods and "vary" in info:
vary = info["vary"]
vary_headers = vary.lower().replace(" ", "").split(",")
for header in vary_headers:
@@ -1850,11 +1881,14 @@
break
if (
- cached_value
- and method in ["GET", "HEAD"]
- and self.cache
+ self.cache
+ and cached_value
+ and (method in self.safe_methods or info["status"] == "308")
and "range" not in headers
):
+ redirect_method = method
+ if info["status"] not in ("307", "308"):
+ redirect_method = "GET"
if "-x-permanent-redirect-url" in info:
# Should cached permanent redirects be counted in our
redirection count? For now, yes.
if redirections <= 0:
@@ -1865,7 +1899,7 @@
)
(response, new_content) = self.request(
info["-x-permanent-redirect-url"],
- method="GET",
+ method=redirect_method,
headers=headers,
redirections=redirections - 1,
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/httplib2-0.14.0/python3/httplib2/socks.py
new/httplib2-0.17.1/python3/httplib2/socks.py
--- old/httplib2-0.14.0/python3/httplib2/socks.py 2019-09-27
06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/python3/httplib2/socks.py 2020-04-02
20:28:24.000000000 +0200
@@ -238,7 +238,15 @@
headers - Additional or modified headers for the proxy connect
request.
"""
- self.__proxy = (proxytype, addr, port, rdns, username, password,
headers)
+ self.__proxy = (
+ proxytype,
+ addr,
+ port,
+ rdns,
+ username.encode() if username else None,
+ password.encode() if password else None,
+ headers,
+ )
def __negotiatesocks5(self, destaddr, destport):
"""__negotiatesocks5(self,destaddr,destport)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/httplib2-0.14.0/python3/httplib2.egg-info/PKG-INFO
new/httplib2-0.17.1/python3/httplib2.egg-info/PKG-INFO
--- old/httplib2-0.14.0/python3/httplib2.egg-info/PKG-INFO 2019-09-27
06:52:00.000000000 +0200
+++ new/httplib2-0.17.1/python3/httplib2.egg-info/PKG-INFO 2020-04-02
20:28:48.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: httplib2
-Version: 0.14.0
+Version: 0.17.1
Summary: A comprehensive HTTP client library.
Home-page: https://github.com/httplib2/httplib2
Author: Joe Gregorio
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/httplib2-0.14.0/setup.py new/httplib2-0.17.1/setup.py
--- old/httplib2-0.14.0/setup.py 2019-09-27 06:51:36.000000000 +0200
+++ new/httplib2-0.17.1/setup.py 2020-04-02 20:28:24.000000000 +0200
@@ -4,7 +4,7 @@
import sys
pkgdir = {"": "python%s" % sys.version_info[0]}
-VERSION = '0.14.0'
+VERSION = '0.17.1'
# `python setup.py test` uses existing Python environment, no virtualenv, no
pip.