diff --git a/CHANGES.rst b/CHANGES.rst index da27287..03c6e39 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,7 @@ Changelog for Isso 0.10.3 (unreleased) ------------------- -- Nothing changed yet. +- follow redirects, #193 0.10.2 (2016-02-21) diff --git a/isso/utils/http.py b/isso/utils/http.py index 3f4f879..48b968b 100644 --- a/isso/utils/http.py +++ b/isso/utils/http.py @@ -4,12 +4,16 @@ import socket try: import httplib + from urlparse import urlparse except ImportError: import http.client as httplib + from urllib.parse import urlparse from isso import dist from isso.wsgi import urlsplit +MAX_RETRY_COUNT = 3 + class curl(object): """Easy to use wrapper around :module:`httplib`. Use as context-manager @@ -23,7 +27,7 @@ class curl(object): """ headers = { - "User-Agent": "Isso/{0} (+http://posativ.org/isso)".format(dist.version) + "User-Agent": "Isso/{0} (+https://posativ.org/isso)".format(dist.version) } def __init__(self, method, host, path, timeout=3): @@ -33,21 +37,29 @@ class curl(object): self.timeout = timeout def __enter__(self): - host, port, ssl = urlsplit(self.host) http = httplib.HTTPSConnection if ssl else httplib.HTTPConnection - self.con = http(host, port, timeout=self.timeout) - - try: - self.con.request(self.method, self.path, headers=self.headers) - except (httplib.HTTPException, socket.error): - return None + for _ in range(MAX_RETRY_COUNT): + self.con = http(host, port, timeout=self.timeout) + try: + self.con.request(self.method, self.path, headers=self.headers) + except (httplib.HTTPException, socket.error) as e: + return None - try: - return self.con.getresponse() - except (httplib.HTTPException, socket.timeout, socket.error): - return None + try: + resp = self.con.getresponse() + if resp.status == 301: + location = resp.getheader('Location') + if location: + self.con.close() + self.path = urlparse(location).path + else: + return None + else: + return resp + except (httplib.HTTPException, socket.timeout, socket.error): + return None def __exit__(self, exc_type, exc_value, traceback): self.con.close()