import os import pytest from .env import H2Conf, H2TestEnv # The push tests depend on "nghttp" @pytest.mark.skipif(condition=H2TestEnv.is_unsupported, reason="mod_http2 not supported here") class TestPush: @pytest.fixture(autouse=True, scope='class') def _class_scope(self, env): H2Conf(env).start_vhost(domains=[f"push.{env.http_tld}"], port=env.https_port, doc_root="htdocs/test1" ).add(r""" RewriteEngine on RewriteRule ^/006-push(.*)?\.html$ /006.html Header add Link ";rel=preload" Header add Link ";rel=preloadX" Header add Link ";rel=preloadX, ; rel=preload" Header add Link ";rel=preloa,;rel=preload" Header add Link "; preload" Header add Link ';rel="preload push"' Header add Link ';rel="push preload"' Header add Link ';rel="abc preload push"' Header add Link ';rel="preload"; nopush' H2PushResource "/006/006.css" critical H2PushResource "/006/006.js" H2Push off Header add Link ';rel="preload"' H2PushResource "/006/006.css" critical Header add Link ";rel=preload" """).end_vhost( ).install() assert env.apache_restart() == 0 ############################ # Link: header handling, various combinations # plain resource without configured pushes def test_h2_400_00(self, env): url = env.mkurl("https", "push", "/006.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 0 == len(promises) # 2 link headers configured, only 1 triggers push def test_h2_400_01(self, env): url = env.mkurl("https", "push", "/006-push.html") r = env.nghttp().get(url, options=["-Haccept-encoding: none"]) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises) assert '/006/006.css' == promises[0]["request"]["header"][":path"] assert 216 == len(promises[0]["response"]["body"]) # Same as 400_01, but with single header line configured def test_h2_400_02(self, env): url = env.mkurl("https", "push", "/006-push2.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises) assert '/006/006.js' == promises[0]["request"]["header"][":path"] # 2 Links, only one with correct rel attribute def test_h2_400_03(self, env): url = env.mkurl("https", "push", "/006-push3.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises) assert '/006/006.js' == promises[0]["request"]["header"][":path"] # Missing > in Link header, PUSH not triggered def test_h2_400_04(self, env): url = env.mkurl("https", "push", "/006-push4.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 0 == len(promises) # More than one value in "rel" parameter def test_h2_400_05(self, env): url = env.mkurl("https", "push", "/006-push5.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises) assert '/006/006.css' == promises[0]["request"]["header"][":path"] # Another "rel" parameter variation def test_h2_400_06(self, env): url = env.mkurl("https", "push", "/006-push6.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises) assert '/006/006.css' == promises[0]["request"]["header"][":path"] # Another "rel" parameter variation def test_h2_400_07(self, env): url = env.mkurl("https", "push", "/006-push7.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises) assert '/006/006.css' == promises[0]["request"]["header"][":path"] # Pushable link header with "nopush" attribute def test_h2_400_08(self, env): url = env.mkurl("https", "push", "/006-push8.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 0 == len(promises) # 2 H2PushResource config trigger on GET, but not on POST def test_h2_400_20(self, env): url = env.mkurl("https", "push", "/006-push20.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 2 == len(promises) fpath = os.path.join(env.gen_dir, "data-400-20") with open(fpath, 'w') as f: f.write("test upload data") r = env.nghttp().upload(url, fpath) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 0 == len(promises) # H2Push configured Off in location def test_h2_400_30(self, env): url = env.mkurl("https", "push", "/006-push30.html") r = env.nghttp().get(url) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 0 == len(promises) # - suppress PUSH def test_h2_400_50(self, env): url = env.mkurl("https", "push", "/006-push.html") r = env.nghttp().get(url, options=['-H', 'accept-push-policy: none']) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 0 == len(promises) # - default pushes desired def test_h2_400_51(self, env): url = env.mkurl("https", "push", "/006-push.html") r = env.nghttp().get(url, options=['-H', 'accept-push-policy: default']) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises) # - HEAD pushes desired def test_h2_400_52(self, env): url = env.mkurl("https", "push", "/006-push.html") r = env.nghttp().get(url, options=['-H', 'accept-push-policy: head']) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises) assert '/006/006.css' == promises[0]["request"]["header"][":path"] assert b"" == promises[0]["response"]["body"] assert 0 == len(promises[0]["response"]["body"]) # - fast-load pushes desired def test_h2_400_53(self, env): url = env.mkurl("https", "push", "/006-push.html") r = env.nghttp().get(url, options=['-H', 'accept-push-policy: fast-load']) assert r.response["status"] == 200 promises = r.results["streams"][r.response["id"]]["promises"] assert 1 == len(promises)