Пример #1
0
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
Пример #2
0
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"
Пример #3
0
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")
Пример #4
0
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
Пример #5
0
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
Пример #6
0
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
Пример #7
0
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
Пример #8
0
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'
Пример #9
0
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")
Пример #10
0
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
Пример #11
0
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"
Пример #12
0
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'
Пример #13
0
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
Пример #14
0
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"
Пример #16
0
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
Пример #19
0
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
Пример #21
0
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
Пример #22
0
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)
Пример #23
0
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
Пример #24
0
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
Пример #25
0
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
Пример #26
0
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
Пример #27
0
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
Пример #28
0
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_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
Пример #31
0
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"
Пример #32
0
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
Пример #34
0
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
Пример #35
0
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
Пример #37
0
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
Пример #38
0
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"
Пример #40
0
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
Пример #41
0
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"
Пример #42
0
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
Пример #43
0
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
Пример #45
0
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
Пример #46
0
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
Пример #47
0
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
Пример #48
0
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"
Пример #49
0
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
Пример #50
0
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
Пример #53
0
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"