def test_get_304_last_modified(): # Test that we can still handle a 304 # by only using the last-modified cache validator. http = httplib2.Http(cache=tests.get_cache_path()) date = email.utils.formatdate() def handler(read): read() yield tests.http_response_bytes( status=200, body=b'something', headers={ 'date': date, 'last-modified': date, }, ) request2 = read() assert request2.headers['if-modified-since'] == date yield tests.http_response_bytes(status=304) with tests.server_yield(handler, request_count=2) as uri: response, content = http.request(uri, 'GET') assert response.get('last-modified') == date response, content = http.request(uri, 'GET') assert response.status == 200 assert response.fromcache
def test_get_307(): # Test that we do follow 307 redirects but # do not cache the 307 http = httplib2.Http(cache=tests.get_cache_path(), timeout=1) r307 = tests.http_response_bytes(status=307, headers={"location": "/final"}) r200 = tests.http_response_bytes( status=200, add_date=True, body=b"final content\n", headers={"cache-control": "max-age=300"}, ) with tests.server_list_http([r307, r200, r307]) as uri: response, content = http.request(uri, "GET") assert response.previous.status == 307 assert not response.previous.fromcache assert response.status == 200 assert not response.fromcache assert content == b"final content\n" response, content = http.request(uri, "GET") assert response.previous.status == 307 assert not response.previous.fromcache assert response.status == 200 assert response.fromcache assert content == b"final content\n"
def test_etag_ignore(): # Test that we can forcibly ignore ETags http = httplib2.Http(cache=tests.get_cache_path()) response_kwargs = dict(add_date=True, add_etag=True) with tests.server_reflect(request_count=3, **response_kwargs) as uri: response, content = http.request( uri, "GET", headers={"accept-encoding": "identity"}) assert response.status == 200 assert response["etag"] != "" response, content = http.request( uri, "GET", headers={ "accept-encoding": "identity", "cache-control": "max-age=0" }, ) reflected = tests.HttpRequest.from_bytes(content) assert reflected.headers.get("if-none-match") http.ignore_etag = True response, content = http.request( uri, "GET", headers={ "accept-encoding": "identity", "cache-control": "max-age=0" }, ) assert not response.fromcache reflected = tests.HttpRequest.from_bytes(content) assert not reflected.headers.get("if-none-match")
def test_get_301(): # Test that we automatically follow 301 redirects # and that we cache the 301 response http = httplib2.Http(cache=tests.get_cache_path()) destination = "" routes = { "/final": tests.http_response_bytes(body=b"This is the final destination.\n"), "": tests.http_response_bytes( status="301 Now where did I leave that URL", headers={"location": "/final"}, body=b"redirect body", ), } with tests.server_route(routes, request_count=3) as uri: destination = urllib.parse.urljoin(uri, "/final") response1, content1 = http.request(uri, "GET") response2, content2 = http.request(uri, "GET") assert response1.status == 200 assert "content-location" in response2 assert response1["content-location"] == destination assert content1 == b"This is the final destination.\n" assert response1.previous.status == 301 assert not response1.previous.fromcache assert response2.status == 200 assert response2["content-location"] == destination assert content2 == b"This is the final destination.\n" assert response2.previous.status == 301 assert response2.previous.fromcache
def test_get_304_last_modified(): # Test that we can still handle a 304 # by only using the last-modified cache validator. http = httplib2.Http(cache=tests.get_cache_path()) date = email.utils.formatdate() def handler(read): read() yield tests.http_response_bytes(status=200, body=b"something", headers={ "date": date, "last-modified": date }) request2 = read() assert request2.headers["if-modified-since"] == date yield tests.http_response_bytes(status=304) with tests.server_yield(handler, request_count=2) as uri: response, content = http.request(uri, "GET") assert response.get("last-modified") == date response, content = http.request(uri, "GET") assert response.status == 200 assert response.fromcache
def test_get_cache_control_no_cache(): # Test Cache-Control: no-cache on requests http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http(add_date=True, add_etag=True, headers={'cache-control': 'max-age=300'}, request_count=2) as uri: response, _ = http.request(uri, 'GET', headers={'accept-encoding': 'identity'}) assert response.status == 200 assert response['etag'] != '' assert not response.fromcache response, _ = http.request(uri, 'GET', headers={'accept-encoding': 'identity'}) assert response.status == 200 assert response.fromcache response, _ = http.request(uri, 'GET', headers={ 'accept-encoding': 'identity', 'Cache-Control': 'no-cache' }) assert response.status == 200 assert not response.fromcache
def test_get_307(): # Test that we do follow 307 redirects but # do not cache the 307 http = httplib2.Http(cache=tests.get_cache_path(), timeout=1) r307 = tests.http_response_bytes( status=307, headers={'location': '/final'}, ) r200 = tests.http_response_bytes( status=200, add_date=True, body=b'final content\n', headers={'cache-control': 'max-age=300'}, ) with tests.server_list_http([r307, r200, r307]) as uri: response, content = http.request(uri, 'GET') assert response.previous.status == 307 assert not response.previous.fromcache assert response.status == 200 assert not response.fromcache assert content == b'final content\n' response, content = http.request(uri, 'GET') assert response.previous.status == 307 assert not response.previous.fromcache assert response.status == 200 assert response.fromcache assert content == b'final content\n'
def test_change_308(): # 308: follow with same method, cache redirect http = httplib2.Http(cache=tests.get_cache_path(), timeout=1) routes = { "/final": tests.make_http_reflect(), "": tests.http_response_bytes( status="308 Permanent Redirect", add_date=True, headers={ "cache-control": "max-age=300", "location": "/final" }, ), } with tests.server_route(routes, request_count=3) as uri: response, content = http.request(uri, "CHANGE", body=b"hello308") assert response.previous.status == 308 assert not response.previous.fromcache assert response.status == 200 assert not response.fromcache assert content.startswith(b"CHANGE /final HTTP") response, content = http.request(uri, "CHANGE") assert response.previous.status == 308 assert response.previous.fromcache assert response.status == 200 assert not response.fromcache assert content.startswith(b"CHANGE /final HTTP")
def test_get_301(): # Test that we automatically follow 301 redirects # and that we cache the 301 response http = httplib2.Http(cache=tests.get_cache_path()) destination = '' routes = { '/final': tests.http_response_bytes(body=b'This is the final destination.\n'), '': tests.http_response_bytes( status='301 Now where did I leave that URL', headers={'location': '/final'}, body=b'redirect body'), } with tests.server_route(routes, request_count=3) as uri: destination = urllib.parse.urljoin(uri, '/final') response1, content1 = http.request(uri, 'GET') response2, content2 = http.request(uri, 'GET') assert response1.status == 200 assert 'content-location' in response2 assert response1['content-location'] == destination assert content1 == b'This is the final destination.\n' assert response1.previous.status == 301 assert not response1.previous.fromcache assert response2.status == 200 assert response2['content-location'] == destination assert content2 == b'This is the final destination.\n' assert response2.previous.status == 301 assert response2.previous.fromcache
def test_etag_override(): # Test that we can forcibly ignore ETags http = httplib2.Http(cache=tests.get_cache_path()) response_kwargs = dict(add_date=True, add_etag=True) with tests.server_reflect(request_count=3, **response_kwargs) as uri: response, _ = http.request(uri, "GET", headers={"accept-encoding": "identity"}) assert response.status == 200 assert response["etag"] != "" response, content = http.request( uri, "GET", headers={"accept-encoding": "identity", "cache-control": "max-age=0"}, ) assert response.status == 200 reflected = tests.HttpRequest.from_bytes(content) assert reflected.headers.get("if-none-match") assert reflected.headers.get("if-none-match") != "fred" response, content = http.request( uri, "GET", headers={ "accept-encoding": "identity", "cache-control": "max-age=0", "if-none-match": "fred", }, ) assert response.status == 200 reflected = tests.HttpRequest.from_bytes(content) assert reflected.headers.get("if-none-match") == "fred"
def test_etag_override(): # Test that we can forcibly ignore ETags http = httplib2.Http(cache=tests.get_cache_path()) response_kwargs = dict( add_date=True, add_etag=True, ) with tests.server_reflect(request_count=3, **response_kwargs) as uri: response, _ = http.request(uri, 'GET', headers={'accept-encoding': 'identity'}) assert response.status == 200 assert response['etag'] != '' response, content = http.request( uri, 'GET', headers={'accept-encoding': 'identity', 'cache-control': 'max-age=0'}, ) assert response.status == 200 reflected = tests.HttpRequest.from_bytes(content) assert reflected.headers.get('if-none-match') assert reflected.headers.get('if-none-match') != 'fred' response, content = http.request( uri, 'GET', headers={'accept-encoding': 'identity', 'cache-control': 'max-age=0', 'if-none-match': 'fred'}, ) assert response.status == 200 reflected = tests.HttpRequest.from_bytes(content) assert reflected.headers.get('if-none-match') == 'fred'
def test_get_only_if_cached_cache_miss(): # Test that can do a GET with no cache with 'only-if-cached' http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http(request_count=0) as uri: response, content = http.request(uri, 'GET', headers={'cache-control': 'only-if-cached'}) assert not response.fromcache assert response.status == 504
def test_get_301(): # Test that we automatically follow 301 redirects # and that we cache the 301 response http = httplib2.Http(cache=tests.get_cache_path()) destination = '' routes = { '/final': tests.http_response_bytes(body=b'This is the final destination.\n'), '': tests.http_response_bytes(status='301 Now where did I leave that URL', headers={'location': '/final'}, body=b'redirect body'), } with tests.server_route(routes, request_count=3) as uri: destination = urllib.parse.urljoin(uri, '/final') response1, content1 = http.request(uri, 'GET') response2, content2 = http.request(uri, 'GET') assert response1.status == 200 assert 'content-location' in response2 assert response1['content-location'] == destination assert content1 == b'This is the final destination.\n' assert response1.previous.status == 301 assert not response1.previous.fromcache assert response2.status == 200 assert response2['content-location'] == destination assert content2 == b'This is the final destination.\n' assert response2.previous.status == 301 assert response2.previous.fromcache
def test_vary_header_is_sent(): # Verifies RFC 2616 13.6. # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html. http = httplib2.Http(cache=tests.get_cache_path()) response = tests.http_response_bytes(headers={ "vary": "Accept", "cache-control": "max-age=300" }, add_date=True) with tests.server_const_bytes(response, request_count=3) as uri: response, content = http.request(uri, "GET", headers={"accept": "text/plain"}) assert response.status == 200 assert "vary" in response # get the resource again, from the cache since accept header in this # request is the same as the request response, content = http.request(uri, "GET", headers={"Accept": "text/plain"}) assert response.status == 200 assert response.fromcache, "Should be from cache" # get the resource again, not from cache since Accept headers does not match response, content = http.request(uri, "GET", headers={"Accept": "text/html"}) assert response.status == 200 assert not response.fromcache, "Should not be from cache" # get the resource again, without any Accept header, so again no match response, content = http.request(uri, "GET") assert response.status == 200 assert not response.fromcache, "Should not be from cache"
def test_vary_header_double(): http = httplib2.Http(cache=tests.get_cache_path()) response = tests.http_response_bytes( headers={'vary': 'Accept, Accept-Language', 'cache-control': 'max-age=300'}, add_date=True, ) with tests.server_const_bytes(response, request_count=3) as uri: response, content = http.request(uri, 'GET', headers={ 'Accept': 'text/plain', 'Accept-Language': 'da, en-gb;q=0.8, en;q=0.7', }) assert response.status == 200 assert 'vary' in response # we are from cache response, content = http.request(uri, 'GET', headers={ 'Accept': 'text/plain', 'Accept-Language': 'da, en-gb;q=0.8, en;q=0.7'}) assert response.fromcache, "Should be from cache" response, content = http.request(uri, 'GET', headers={'Accept': 'text/plain'}) assert response.status == 200 assert not response.fromcache # get the resource again, not from cache, varied headers don't match exact response, content = http.request(uri, 'GET', headers={'Accept-Language': 'da'}) assert response.status == 200 assert not response.fromcache, "Should not be from cache"
def test_get_cache_control_pragma_no_cache(): # Test Pragma: no-cache on requests http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http( add_date=True, add_etag=True, headers={"cache-control": "max-age=300"}, request_count=2, ) as uri: response, _ = http.request(uri, "GET", headers={"accept-encoding": "identity"}) assert response["etag"] != "" response, _ = http.request(uri, "GET", headers={"accept-encoding": "identity"}) assert response.status == 200 assert response.fromcache response, _ = http.request(uri, "GET", headers={ "accept-encoding": "identity", "Pragma": "no-cache" }) assert response.status == 200 assert not response.fromcache
def test_get_only_if_cached_cache_miss(): # Test that can do a GET with no cache with 'only-if-cached' http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http(request_count=0) as uri: response, content = http.request( uri, "GET", headers={"cache-control": "only-if-cached"}) assert not response.fromcache assert response.status == 504
def test_get_only_if_cached_cache_hit(): # Test that can do a GET with cache and 'only-if-cached' http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http(add_etag=True) as uri: http.request(uri, 'GET') response, content = http.request(uri, 'GET', headers={'cache-control': 'only-if-cached'}) assert response.fromcache assert response.status == 200
def test_get_only_if_cached_cache_hit(): # Test that can do a GET with cache and 'only-if-cached' http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http(add_etag=True) as uri: http.request(uri, "GET") response, content = http.request( uri, "GET", headers={"cache-control": "only-if-cached"}) assert response.fromcache assert response.status == 200
def test_etag_used(): # Test that we use ETags properly to validate our cache cache_path = tests.get_cache_path() http = httplib2.Http(cache=cache_path) response_kwargs = dict( add_date=True, add_etag=True, body=b'something', headers={ 'cache-control': 'public,max-age=300', }, ) def handler(request): if request.headers.get('range'): return tests.http_response_bytes(status=206, **response_kwargs) return tests.http_response_bytes(**response_kwargs) with tests.server_request(handler, request_count=2) as uri: response, _ = http.request(uri, 'GET', headers={'accept-encoding': 'identity'}) assert response['etag'] == '"437b930db84b8079c2dd804a71936b5f"' http.request(uri, 'GET', headers={'accept-encoding': 'identity'}) response, _ = http.request( uri, 'GET', headers={ 'accept-encoding': 'identity', 'cache-control': 'must-revalidate' }, ) assert response.status == 200 assert response.fromcache # TODO: API to read cache item, at least internal to tests cache_file_name = os.path.join( cache_path, httplib2.safename(httplib2.urlnorm(uri)[-1])) with open(cache_file_name, 'r') as f: status_line = f.readline() assert status_line.startswith("status:") response, content = http.request( uri, 'HEAD', headers={'accept-encoding': 'identity'}) assert response.status == 200 assert response.fromcache response, content = http.request(uri, 'GET', headers={ 'accept-encoding': 'identity', 'range': 'bytes=0-0' }) assert response.status == 206 assert not response.fromcache
def test_pickle_http(): http = httplib2.Http(cache=tests.get_cache_path()) new_http = pickle.loads(pickle.dumps(http)) assert tuple(sorted(new_http.__dict__)) == tuple(sorted(http.__dict__)) assert new_http.credentials.credentials == http.credentials.credentials assert new_http.certificates.credentials == http.certificates.credentials assert new_http.cache.cache == http.cache.cache for key in new_http.__dict__: if key not in ("cache", "certificates", "credentials"): assert getattr(new_http, key) == getattr(http, key)
def test_get_cache_control_no_store_response(): # A no-store response means that the response should not be stored. http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http( add_date=True, add_etag=True, headers={'cache-control': 'max-age=300, no-store'}, request_count=2) as uri: response, _ = http.request(uri, 'GET') assert response.status == 200 assert not response.fromcache response, _ = http.request(uri, 'GET') assert response.status == 200 assert not response.fromcache
def test_update_uses_cached_etag_overridden(): # Test that we natively support http://www.w3.org/1999/04/Editing/ http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_request(handler_conditional_update, request_count=2) as uri: response, content = http.request(uri, 'GET') assert response.status == 200 assert not response.fromcache response, content = http.request(uri, 'GET') assert response.status == 200 assert response.fromcache response, content = http.request(uri, 'PUT', body=b'foo', headers={'if-match': 'fred'}) assert response.status == 412
def test_update_uses_cached_etag_and_oc_method(): # Test that we natively support http://www.w3.org/1999/04/Editing/ http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_request(handler_conditional_update, request_count=2) as uri: response, _ = http.request(uri, 'GET') assert response.status == 200 assert not response.fromcache response, _ = http.request(uri, 'GET') assert response.status == 200 assert response.fromcache http.optimistic_concurrency_methods.append('DELETE') response, _ = http.request(uri, 'DELETE') assert response.status == 200
def test_get_cache_control_pragma_no_cache(): # Test Pragma: no-cache on requests http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http( add_date=True, add_etag=True, headers={'cache-control': 'max-age=300'}, request_count=2) as uri: response, _ = http.request(uri, 'GET', headers={'accept-encoding': 'identity'}) assert response['etag'] != '' response, _ = http.request(uri, 'GET', headers={'accept-encoding': 'identity'}) assert response.status == 200 assert response.fromcache response, _ = http.request(uri, 'GET', headers={'accept-encoding': 'identity', 'Pragma': 'no-cache'}) assert response.status == 200 assert not response.fromcache
def test_update_uses_cached_etag(method): # Test that we natively support http://www.w3.org/1999/04/Editing/ http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_request(handler_conditional_update, request_count=3) as uri: response, _ = http.request(uri, 'GET') assert response.status == 200 assert not response.fromcache response, _ = http.request(uri, 'GET') assert response.status == 200 assert response.fromcache response, _ = http.request(uri, method, body=b'foo') assert response.status == 200 response, _ = http.request(uri, method, body=b'foo') assert response.status == 412
def test_update_uses_cached_etag_and_oc_method(): # Test that we natively support http://www.w3.org/1999/04/Editing/ http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_request(handler_conditional_update, request_count=2) as uri: response, _ = http.request(uri, "GET") assert response.status == 200 assert not response.fromcache response, _ = http.request(uri, "GET") assert response.status == 200 assert response.fromcache http.optimistic_concurrency_methods.append("DELETE") response, _ = http.request(uri, "DELETE") assert response.status == 200
def test_update_uses_cached_etag(method): # Test that we natively support http://www.w3.org/1999/04/Editing/ http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_request(handler_conditional_update, request_count=3) as uri: response, _ = http.request(uri, "GET") assert response.status == 200 assert not response.fromcache response, _ = http.request(uri, "GET") assert response.status == 200 assert response.fromcache response, _ = http.request(uri, method, body=b"foo") assert response.status == 200 response, _ = http.request(uri, method, body=b"foo") assert response.status == 412
def test_vary_unused_header(): http = httplib2.Http(cache=tests.get_cache_path()) response = tests.http_response_bytes( headers={'vary': 'X-No-Such-Header', 'cache-control': 'max-age=300'}, add_date=True, ) with tests.server_const_bytes(response, request_count=1) as uri: # A header's value is not considered to vary if it's not used at all. response, content = http.request(uri, 'GET', headers={'Accept': 'text/plain'}) assert response.status == 200 assert 'vary' in response # we are from cache response, content = http.request(uri, 'GET', headers={'Accept': 'text/plain'}) assert response.fromcache, "Should be from cache"
def test_etag_used(): # Test that we use ETags properly to validate our cache cache_path = tests.get_cache_path() http = httplib2.Http(cache=cache_path) response_kwargs = dict( add_date=True, add_etag=True, body=b"something", headers={"cache-control": "public,max-age=300"}, ) def handler(request): if request.headers.get("range"): return tests.http_response_bytes(status=206, **response_kwargs) return tests.http_response_bytes(**response_kwargs) with tests.server_request(handler, request_count=2) as uri: response, _ = http.request(uri, "GET", headers={"accept-encoding": "identity"}) assert response["etag"] == '"437b930db84b8079c2dd804a71936b5f"' http.request(uri, "GET", headers={"accept-encoding": "identity"}) response, _ = http.request( uri, "GET", headers={"accept-encoding": "identity", "cache-control": "must-revalidate"}, ) assert response.status == 200 assert response.fromcache # TODO: API to read cache item, at least internal to tests cache_file_name = os.path.join( cache_path, httplib2.safename(httplib2.urlnorm(uri)[-1]) ) with open(cache_file_name, "r") as f: status_line = f.readline() assert status_line.startswith("status:") response, content = http.request( uri, "HEAD", headers={"accept-encoding": "identity"} ) assert response.status == 200 assert response.fromcache response, content = http.request( uri, "GET", headers={"accept-encoding": "identity", "range": "bytes=0-0"} ) assert response.status == 206 assert not response.fromcache
def test_update_uses_cached_etag_overridden(): # Test that we natively support http://www.w3.org/1999/04/Editing/ http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_request(handler_conditional_update, request_count=2) as uri: response, content = http.request(uri, "GET") assert response.status == 200 assert not response.fromcache response, content = http.request(uri, "GET") assert response.status == 200 assert response.fromcache response, content = http.request(uri, "PUT", body=b"foo", headers={"if-match": "fred"}) assert response.status == 412
def test_get_cache_control_no_cache_no_store_request(): # Test that a no-store, no-cache clears the entry from the cache # even if it was cached previously. http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http( add_date=True, add_etag=True, headers={'cache-control': 'max-age=300'}, request_count=3) as uri: response, _ = http.request(uri, 'GET') response, _ = http.request(uri, 'GET') assert response.fromcache response, _ = http.request(uri, 'GET', headers={'Cache-Control': 'no-store, no-cache'}) assert response.status == 200 assert not response.fromcache response, _ = http.request(uri, 'GET', headers={'Cache-Control': 'no-store, no-cache'}) assert response.status == 200 assert not response.fromcache
def test_get_301_no_redirect(): # Test that we cache the 301 response http = httplib2.Http(cache=tests.get_cache_path(), timeout=0.5) http.follow_redirects = False response = tests.http_response_bytes( status='301 Now where did I leave that URL', headers={'location': '/final', 'cache-control': 'max-age=300'}, body=b'redirect body', add_date=True, ) with tests.server_const_bytes(response) as uri: response, _ = http.request(uri, 'GET') assert response.status == 301 assert not response.fromcache response, _ = http.request(uri, 'GET') assert response.status == 301 assert response.fromcache
def test_get_301_no_redirect(): # Test that we cache the 301 response http = httplib2.Http(cache=tests.get_cache_path(), timeout=0.5) http.follow_redirects = False response = tests.http_response_bytes( status="301 Now where did I leave that URL", headers={"location": "/final", "cache-control": "max-age=300"}, body=b"redirect body", add_date=True, ) with tests.server_const_bytes(response) as uri: response, _ = http.request(uri, "GET") assert response.status == 301 assert not response.fromcache response, _ = http.request(uri, "GET") assert response.status == 301 assert response.fromcache
def test_vary_header_simple(): """ RFC 2616 13.6 When the cache receives a subsequent request whose Request-URI specifies one or more cache entries including a Vary header field, the cache MUST NOT use such a cache entry to construct a response to the new request unless all of the selecting request-headers present in the new request match the corresponding stored request-headers in the original request. """ # test that the vary header is sent http = httplib2.Http(cache=tests.get_cache_path()) response = tests.http_response_bytes( headers={ 'vary': 'Accept', 'cache-control': 'max-age=300' }, add_date=True, ) with tests.server_const_bytes(response, request_count=3) as uri: response, content = http.request(uri, 'GET', headers={'accept': 'text/plain'}) assert response.status == 200 assert 'vary' in response # get the resource again, from the cache since accept header in this # request is the same as the request response, content = http.request(uri, 'GET', headers={'Accept': 'text/plain'}) assert response.status == 200 assert response.fromcache, "Should be from cache" # get the resource again, not from cache since Accept headers does not match response, content = http.request(uri, 'GET', headers={'Accept': 'text/html'}) assert response.status == 200 assert not response.fromcache, "Should not be from cache" # get the resource again, without any Accept header, so again no match response, content = http.request(uri, 'GET') assert response.status == 200 assert not response.fromcache, "Should not be from cache"
def test_vary_header_double(): http = httplib2.Http(cache=tests.get_cache_path()) response = tests.http_response_bytes( headers={ "vary": "Accept, Accept-Language", "cache-control": "max-age=300" }, add_date=True, ) with tests.server_const_bytes(response, request_count=3) as uri: response, content = http.request( uri, "GET", headers={ "Accept": "text/plain", "Accept-Language": "da, en-gb;q=0.8, en;q=0.7", }, ) assert response.status == 200 assert "vary" in response # we are from cache response, content = http.request( uri, "GET", headers={ "Accept": "text/plain", "Accept-Language": "da, en-gb;q=0.8, en;q=0.7", }, ) assert response.fromcache, "Should be from cache" response, content = http.request(uri, "GET", headers={"Accept": "text/plain"}) assert response.status == 200 assert not response.fromcache # get the resource again, not from cache, varied headers don't match exact response, content = http.request(uri, "GET", headers={"Accept-Language": "da"}) assert response.status == 200 assert not response.fromcache, "Should not be from cache"
def test_get_302(): # Test that we automatically follow 302 redirects # and that we DO NOT cache the 302 response http = httplib2.Http(cache=tests.get_cache_path()) second_url, final_url = '', '' routes = { '/final': tests.http_response_bytes(body=b'This is the final destination.\n'), '/second': tests.http_response_bytes(status='302 Found', headers={'location': '/final'}, body=b'second redirect'), '': tests.http_response_bytes(status='302 Found', headers={'location': '/second'}, body=b'redirect body'), } with tests.server_route(routes, request_count=7) as uri: second_url = urllib.parse.urljoin(uri, '/second') final_url = urllib.parse.urljoin(uri, '/final') response1, content1 = http.request(second_url, 'GET') response2, content2 = http.request(second_url, 'GET') response3, content3 = http.request(uri, 'GET') assert response1.status == 200 assert response1['content-location'] == final_url assert content1 == b'This is the final destination.\n' assert response1.previous.status == 302 assert not response1.previous.fromcache assert response2.status == 200 # FIXME: # assert response2.fromcache assert response2['content-location'] == final_url assert content2 == b'This is the final destination.\n' assert response2.previous.status == 302 assert not response2.previous.fromcache assert response2.previous['content-location'] == second_url assert response3.status == 200 # FIXME: # assert response3.fromcache assert content3 == b'This is the final destination.\n' assert response3.previous.status == 302 assert not response3.previous.fromcache
def test_vary_header_double(): http = httplib2.Http(cache=tests.get_cache_path()) response = tests.http_response_bytes( headers={ 'vary': 'Accept, Accept-Language', 'cache-control': 'max-age=300' }, add_date=True, ) with tests.server_const_bytes(response, request_count=3) as uri: response, content = http.request(uri, 'GET', headers={ 'Accept': 'text/plain', 'Accept-Language': 'da, en-gb;q=0.8, en;q=0.7', }) assert response.status == 200 assert 'vary' in response # we are from cache response, content = http.request(uri, 'GET', headers={ 'Accept': 'text/plain', 'Accept-Language': 'da, en-gb;q=0.8, en;q=0.7' }) assert response.fromcache, "Should be from cache" response, content = http.request(uri, 'GET', headers={'Accept': 'text/plain'}) assert response.status == 200 assert not response.fromcache # get the resource again, not from cache, varied headers don't match exact response, content = http.request(uri, 'GET', headers={'Accept-Language': 'da'}) assert response.status == 200 assert not response.fromcache, "Should not be from cache"
def test_get_302(): # Test that we automatically follow 302 redirects # and that we DO NOT cache the 302 response http = httplib2.Http(cache=tests.get_cache_path()) second_url, final_url = "", "" routes = { "/final": tests.http_response_bytes(body=b"This is the final destination.\n"), "/second": tests.http_response_bytes(status="302 Found", headers={"location": "/final"}, body=b"second redirect"), "": tests.http_response_bytes(status="302 Found", headers={"location": "/second"}, body=b"redirect body"), } with tests.server_route(routes, request_count=7) as uri: second_url = urllib.parse.urljoin(uri, "/second") final_url = urllib.parse.urljoin(uri, "/final") response1, content1 = http.request(second_url, "GET") response2, content2 = http.request(second_url, "GET") response3, content3 = http.request(uri, "GET") assert response1.status == 200 assert response1["content-location"] == final_url assert content1 == b"This is the final destination.\n" assert response1.previous.status == 302 assert not response1.previous.fromcache assert response2.status == 200 # FIXME: # assert response2.fromcache assert response2["content-location"] == final_url assert content2 == b"This is the final destination.\n" assert response2.previous.status == 302 assert not response2.previous.fromcache assert response2.previous["content-location"] == second_url assert response3.status == 200 # FIXME: # assert response3.fromcache assert content3 == b"This is the final destination.\n" assert response3.previous.status == 302 assert not response3.previous.fromcache
def test_get_cache_control_no_cache_no_store_request(): # Test that a no-store, no-cache clears the entry from the cache # even if it was cached previously. http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http(add_date=True, add_etag=True, headers={'cache-control': 'max-age=300'}, request_count=3) as uri: response, _ = http.request(uri, 'GET') response, _ = http.request(uri, 'GET') assert response.fromcache response, _ = http.request( uri, 'GET', headers={'Cache-Control': 'no-store, no-cache'}) assert response.status == 200 assert not response.fromcache response, _ = http.request( uri, 'GET', headers={'Cache-Control': 'no-store, no-cache'}) assert response.status == 200 assert not response.fromcache
def test_get_cache_control_no_store_request(): # A no-store request means that the response should not be stored. http = httplib2.Http(cache=tests.get_cache_path()) with tests.server_const_http( add_date=True, add_etag=True, headers={"cache-control": "max-age=300"}, request_count=2, ) as uri: response, _ = http.request(uri, "GET", headers={"Cache-Control": "no-store"}) assert response.status == 200 assert not response.fromcache response, _ = http.request(uri, "GET", headers={"Cache-Control": "no-store"}) assert response.status == 200 assert not response.fromcache
def test_get_301_no_redirect(): # Test that we cache the 301 response http = httplib2.Http(cache=tests.get_cache_path(), timeout=0.5) http.follow_redirects = False response = tests.http_response_bytes( status='301 Now where did I leave that URL', headers={ 'location': '/final', 'cache-control': 'max-age=300' }, body=b'redirect body', add_date=True, ) with tests.server_const_bytes(response) as uri: response, _ = http.request(uri, 'GET') assert response.status == 301 assert not response.fromcache response, _ = http.request(uri, 'GET') assert response.status == 301 assert response.fromcache
def test_update_invalidates_cache(): # Test that calling PUT or DELETE on a # URI that is cache invalidates that cache. http = httplib2.Http(cache=tests.get_cache_path()) def handler(request): if request.method in ('PUT', 'PATCH', 'DELETE'): return tests.http_response_bytes(status=405) return tests.http_response_bytes( add_date=True, add_etag=True, headers={'cache-control': 'max-age=300'}) with tests.server_request(handler, request_count=3) as uri: response, _ = http.request(uri, 'GET') response, _ = http.request(uri, 'GET') assert response.fromcache response, _ = http.request(uri, 'DELETE') assert response.status == 405 assert not response.fromcache response, _ = http.request(uri, 'GET') assert not response.fromcache
def test_get_302(): # Test that we automatically follow 302 redirects # and that we DO NOT cache the 302 response http = httplib2.Http(cache=tests.get_cache_path()) second_url, final_url = "", "" routes = { "/final": tests.http_response_bytes(body=b"This is the final destination.\n"), "/second": tests.http_response_bytes( status="302 Found", headers={"location": "/final"}, body=b"second redirect" ), "": tests.http_response_bytes( status="302 Found", headers={"location": "/second"}, body=b"redirect body" ), } with tests.server_route(routes, request_count=7) as uri: second_url = urllib.parse.urljoin(uri, "/second") final_url = urllib.parse.urljoin(uri, "/final") response1, content1 = http.request(second_url, "GET") response2, content2 = http.request(second_url, "GET") response3, content3 = http.request(uri, "GET") assert response1.status == 200 assert response1["content-location"] == final_url assert content1 == b"This is the final destination.\n" assert response1.previous.status == 302 assert not response1.previous.fromcache assert response2.status == 200 # FIXME: # assert response2.fromcache assert response2["content-location"] == final_url assert content2 == b"This is the final destination.\n" assert response2.previous.status == 302 assert not response2.previous.fromcache assert response2.previous["content-location"] == second_url assert response3.status == 200 # FIXME: # assert response3.fromcache assert content3 == b"This is the final destination.\n" assert response3.previous.status == 302 assert not response3.previous.fromcache
def test_post_307(): # 307: follow with same method http = httplib2.Http(cache=tests.get_cache_path(), timeout=1) http.follow_all_redirects = True r307 = tests.http_response_bytes(status=307, headers={"location": "/final"}) r200 = tests.http_response_bytes(status=200, body=b"final content\n") with tests.server_list_http([r307, r200, r307, r200]) as uri: response, content = http.request(uri, "POST") assert response.previous.status == 307 assert not response.previous.fromcache assert response.status == 200 assert not response.fromcache assert content == b"final content\n" response, content = http.request(uri, "POST") assert response.previous.status == 307 assert not response.previous.fromcache assert response.status == 200 assert not response.fromcache assert content == b"final content\n"
def test_get_302(): # Test that we automatically follow 302 redirects # and that we DO NOT cache the 302 response http = httplib2.Http(cache=tests.get_cache_path()) second_url, final_url = '', '' routes = { '/final': tests.http_response_bytes(body=b'This is the final destination.\n'), '/second': tests.http_response_bytes( status='302 Found', headers={'location': '/final'}, body=b'second redirect'), '': tests.http_response_bytes( status='302 Found', headers={'location': '/second'}, body=b'redirect body'), } with tests.server_route(routes, request_count=7) as uri: second_url = urllib.parse.urljoin(uri, '/second') final_url = urllib.parse.urljoin(uri, '/final') response1, content1 = http.request(second_url, 'GET') response2, content2 = http.request(second_url, 'GET') response3, content3 = http.request(uri, 'GET') assert response1.status == 200 assert response1['content-location'] == final_url assert content1 == b'This is the final destination.\n' assert response1.previous.status == 302 assert not response1.previous.fromcache assert response2.status == 200 # FIXME: # assert response2.fromcache assert response2['content-location'] == final_url assert content2 == b'This is the final destination.\n' assert response2.previous.status == 302 assert not response2.previous.fromcache assert response2.previous['content-location'] == second_url assert response3.status == 200 # FIXME: # assert response3.fromcache assert content3 == b'This is the final destination.\n' assert response3.previous.status == 302 assert not response3.previous.fromcache
def test_etag_override(): # Test that we can forcibly ignore ETags http = httplib2.Http(cache=tests.get_cache_path()) response_kwargs = dict( add_date=True, add_etag=True, ) with tests.server_reflect(request_count=3, **response_kwargs) as uri: response, _ = http.request(uri, 'GET', headers={'accept-encoding': 'identity'}) assert response.status == 200 assert response['etag'] != '' response, content = http.request( uri, 'GET', headers={ 'accept-encoding': 'identity', 'cache-control': 'max-age=0' }, ) assert response.status == 200 reflected = tests.HttpRequest.from_bytes(content) assert reflected.headers.get('if-none-match') assert reflected.headers.get('if-none-match') != 'fred' response, content = http.request( uri, 'GET', headers={ 'accept-encoding': 'identity', 'cache-control': 'max-age=0', 'if-none-match': 'fred' }, ) assert response.status == 200 reflected = tests.HttpRequest.from_bytes(content) assert reflected.headers.get('if-none-match') == 'fred'
def test_vary_unused_header(): http = httplib2.Http(cache=tests.get_cache_path()) response = tests.http_response_bytes( headers={ "vary": "X-No-Such-Header", "cache-control": "max-age=300" }, add_date=True, ) with tests.server_const_bytes(response, request_count=1) as uri: # A header's value is not considered to vary if it's not used at all. response, content = http.request(uri, "GET", headers={"Accept": "text/plain"}) assert response.status == 200 assert "vary" in response # we are from cache response, content = http.request(uri, "GET", headers={"Accept": "text/plain"}) assert response.fromcache, "Should be from cache"
def test_update_invalidates_cache(): # Test that calling PUT or DELETE on a # URI that is cache invalidates that cache. http = httplib2.Http(cache=tests.get_cache_path()) def handler(request): if request.method in ("PUT", "PATCH", "DELETE"): return tests.http_response_bytes(status=405) return tests.http_response_bytes( add_date=True, add_etag=True, headers={"cache-control": "max-age=300"}) with tests.server_request(handler, request_count=3) as uri: response, _ = http.request(uri, "GET") response, _ = http.request(uri, "GET") assert response.fromcache response, _ = http.request(uri, "DELETE") assert response.status == 405 assert not response.fromcache response, _ = http.request(uri, "GET") assert not response.fromcache
def test_vary_header_simple(): """ RFC 2616 13.6 When the cache receives a subsequent request whose Request-URI specifies one or more cache entries including a Vary header field, the cache MUST NOT use such a cache entry to construct a response to the new request unless all of the selecting request-headers present in the new request match the corresponding stored request-headers in the original request. """ # test that the vary header is sent http = httplib2.Http(cache=tests.get_cache_path()) response = tests.http_response_bytes( headers={'vary': 'Accept', 'cache-control': 'max-age=300'}, add_date=True, ) with tests.server_const_bytes(response, request_count=3) as uri: response, content = http.request(uri, 'GET', headers={'accept': 'text/plain'}) assert response.status == 200 assert 'vary' in response # get the resource again, from the cache since accept header in this # request is the same as the request response, content = http.request(uri, 'GET', headers={'Accept': 'text/plain'}) assert response.status == 200 assert response.fromcache, "Should be from cache" # get the resource again, not from cache since Accept headers does not match response, content = http.request(uri, 'GET', headers={'Accept': 'text/html'}) assert response.status == 200 assert not response.fromcache, "Should not be from cache" # get the resource again, without any Accept header, so again no match response, content = http.request(uri, 'GET') assert response.status == 200 assert not response.fromcache, "Should not be from cache"