def test_expiration_model_date_and_expires(): now = time.time() response_headers = { "date": email.utils.formatdate(now, usegmt=True), "expires": email.utils.formatdate(now + 2, usegmt=True), } assert httplib2._entry_disposition(response_headers, {}) == "FRESH" time.sleep(3) assert httplib2._entry_disposition(response_headers, {}) == "STALE"
def test_expiration_model_date_and_expires(): now = time.time() response_headers = { 'date': email.utils.formatdate(now, usegmt=True), 'expires': email.utils.formatdate(now + 2, usegmt=True), } assert httplib2._entry_disposition(response_headers, {}) == 'FRESH' time.sleep(3) assert httplib2._entry_disposition(response_headers, {}) == 'STALE'
def test_expiration_model_fresh(): response_headers = { "date": email.utils.formatdate(usegmt=True), "cache-control": "max-age=2", } assert httplib2._entry_disposition(response_headers, {}) == "FRESH" # TODO: add current time as _entry_disposition argument to avoid sleep in tests time.sleep(3) assert httplib2._entry_disposition(response_headers, {}) == "STALE"
def test_expiration_model_fresh(): response_headers = { 'date': email.utils.formatdate(usegmt=True), 'cache-control': 'max-age=2' } assert httplib2._entry_disposition(response_headers, {}) == 'FRESH' # TODO: add current time as _entry_disposition argument to avoid sleep in tests time.sleep(3) assert httplib2._entry_disposition(response_headers, {}) == 'STALE'
def test_entry_disposition(data): now = time.time() nowre = re.compile(r"{now([\+\-]\d+)?}") def render(s): m = nowre.match(s) if m: offset = int(m.expand(r"\1")) if m.group(1) else 0 s = email.utils.formatdate(now + offset, usegmt=True) return s request, response, expected = data request = {k: render(v) for k, v in request.items()} response = {k: render(v) for k, v in response.items()} assert httplib2._entry_disposition(response, request) == expected
def test_entry_disposition(data): now = time.time() nowre = re.compile(r'{now([\+\-]\d+)?}') def render(s): m = nowre.match(s) if m: offset = int(m.expand(r'\1')) if m.group(1) else 0 s = email.utils.formatdate(now + offset, usegmt=True) return s request, response, expected = data request = {k: render(v) for k, v in request.items()} response = {k: render(v) for k, v in response.items()} assert httplib2._entry_disposition(response, request) == expected
def request(self, uri, method="GET", body=None, headers=None, redirections=httplib2.DEFAULT_MAX_REDIRECTS, connection_type=None): """request handler with thread safety hacked in""" try: if headers is None: headers = {} else: headers = httplib2._normalize_headers(headers) if not headers.has_key('user-agent'): headers['user-agent'] = "Python-httplib2/%s" % httplib2.__version__ uri = httplib2.iri2uri(uri) (scheme, authority, request_uri, defrag_uri) = httplib2.urlnorm(uri) domain_port = authority.split(":")[0:2] if len(domain_port) == 2 and domain_port[1] == '443' and scheme == 'http': scheme = 'https' authority = domain_port[0] conn_key = scheme+":"+authority def get_conn(conn_key): if conn_key in self.connections: conn = self.connections[conn_key] if type(conn) is list: for c in conn: if not getattr(c, 'busy', True): return c else: return c if type(conn) is list: return None conn = get_conn(conn_key) if conn is None: if not connection_type: connection_type = (scheme == 'https') and httplib2.HTTPSConnectionWithTimeout or httplib2.HTTPConnectionWithTimeout certs = list(self.certificates.iter(authority)) if scheme == 'https' and certs: conn = connection_type(authority, key_file=certs[0][0], cert_file=certs[0][1], timeout=self.timeout, proxy_info=self.proxy_info) self.connections.setdefault(conn_key, []).append(conn) else: conn = connection_type(authority, timeout=self.timeout, proxy_info=self.proxy_info) self.connections.setdefault(conn_key, []).append(conn) conn.set_debuglevel(httplib2.debuglevel) conn.busy = True if method in ["GET", "HEAD"] and 'range' not in headers and 'accept-encoding' not in headers: headers['accept-encoding'] = 'deflate, gzip' info = httplib2.email.Message.Message() cached_value = None if self.cache: cachekey = defrag_uri cached_value = self.cache.get(cachekey) if cached_value: try: info, content = cached_value.split('\r\n\r\n', 1) feedparser = httplib2.email.FeedParser.FeedParser() feedparser.feed(info) info = feedparser.close() feedparser._parse = None except IndexError: self.cache.delete(cachekey) cachekey = None cached_value = None else: cachekey = None if method not in ["GET", "HEAD"] and self.cache and cachekey: # RFC 2616 Section 13.10 self.cache.delete(cachekey) if cached_value and method in ["GET", "HEAD"] and self.cache and 'range' not in headers: if info.has_key('-x-permanent-redirect-url'): (response, new_content) = self.request(info['-x-permanent-redirect-url'], "GET", headers = headers, redirections = redirections - 1) response.previous = Response(info) response.previous.fromcache = True else: entry_disposition = httplib2._entry_disposition(info, headers) if entry_disposition == "FRESH": if not cached_value: info['status'] = '504' content = "" response = Response(info) if cached_value: response.fromcache = True return (response, content) if entry_disposition == "STALE": if info.has_key('etag') and not self.ignore_etag and not 'if-none-match' in headers: headers['if-none-match'] = info['etag'] if info.has_key('last-modified') and not 'last-modified' in headers: headers['if-modified-since'] = info['last-modified'] elif entry_disposition == "TRANSPARENT": pass (response, new_content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) if response.status == 304 and method == "GET": # Rewrite the cache entry with the new end-to-end headers # Take all headers that are in response # and overwrite their values in info. # unless they are hop-by-hop, or are listed in the connection header. for key in httplib2._get_end2end_headers(response): info[key] = response[key] merged_response = Response(info) if hasattr(response, "_stale_digest"): merged_response._stale_digest = response._stale_digest httplib2._updateCache(headers, merged_response, content, self.cache, cachekey) response = merged_response response.status = 200 response.fromcache = True elif response.status == 200: content = new_content else: self.cache.delete(cachekey) content = new_content else: cc = httplib2._parse_cache_control(headers) if cc.has_key('only-if-cached'): info['status'] = '504' response = Response(info) content = "" else: (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) except Exception, e: if self.force_exception_to_status_code: if isinstance(e, httplib2.HttpLib2ErrorWithResponse): response = e.response content = e.content response.status = 500 response.reason = str(e) elif isinstance(e, socket.timeout): content = "Request Timeout" response = Response( { "content-type": "text/plain", "status": "408", "content-length": len(content) }) response.reason = "Request Timeout" else: content = str(e) response = Response( { "content-type": "text/plain", "status": "400", "content-length": len(content) }) response.reason = "Bad Request" else: raise