Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions test/modules/filters/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ class FiltersTestSetup(HttpdTestSetup):
def __init__(self, env: 'HttpdTestEnv'):
super().__init__(env=env)
self.add_source_dir(os.path.dirname(inspect.getfile(FiltersTestSetup)))
self.add_modules(["substitute", "sed", "buffer"])
self.add_modules(["substitute", "sed", "buffer", "brotli"])
self.add_cgi_module()


class FiltersTestEnv(HttpdTestEnv):

def __init__(self, pytestconfig=None):
super().__init__(pytestconfig=pytestconfig)
self.add_httpd_log_modules(["substitute", "sed", "core"])
self.add_httpd_log_modules(["substitute", "sed", "buffer", "brotli", "core"])

def setup_httpd(self, setup: HttpdTestSetup = None):
super().setup_httpd(setup=FiltersTestSetup(env=self))
1 change: 1 addition & 0 deletions test/modules/filters/htdocs/test1/greeting.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Good morning, fellow!
19 changes: 19 additions & 0 deletions test/modules/filters/htdocs/test1/lorem.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
est laborum.

Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius,
turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis
sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac
tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam
tempor. Ut ullamcorper, ligula ut dictum pharetra, nisi nunc fringilla
magna, in commodo elit erat nec turpis. Ut pharetra augue nec augue.
Nam elit agna, endrerit sit amet, tincidunt ac, viverra sed, nulla.
Donec porta diam eu massa. Quisque diam lorem, interdum vitae, dapibus
ac, scelerisque vitae, pede. Donec eget tellus non erat lacinia fermentum.
Donec in velit vel ipsum auctor pulvinar. Class aptent taciti sociosqu ad
litora torquent per conubia nostra, per inceptos hymenaeos.
89 changes: 89 additions & 0 deletions test/modules/filters/test_004_brotli_compression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import os

import pytest

from pyhttpd.conf import HttpdConf


class TestBrotliCompression:

@pytest.fixture(autouse=True, scope='class')
def _class_scope(self, env):
conf = HttpdConf(env, extras={
f"test1.{env.http_tld}": """
<Location "/">
AddOutputFilterByType BROTLI_COMPRESS text/plain text/html text/css
</Location>
""",
})
conf.add_vhost_test1()
conf.install()
assert env.apache_restart() == 0

# Request a small text file with Accept-Encoding: br.
# Verify Content-Encoding: br header is present.
def test_brotli_004_01_br_header_present(self, env):
url = env.mkurl("http", "test1", "/greeting.txt")
r = env.curl_get(url, options=[
"-H", "Accept-Encoding: br",
])
assert r.response, "no response"
assert r.response["status"] == 200
assert r.response["header"].get("content-encoding") == "br", \
f"expected Content-Encoding: br, got: {r.response['header']}"
raw_body = r.response["body"]
assert len(raw_body) > 0, "compressed body should not be empty"
original = b"Good morning, fellow!"
assert len(raw_body) != len(original) or raw_body != original, \
"body should be compressed, not plain text"

# Request a larger text file; verify brotli compression is applied.
def test_brotli_004_02_large_file(self, env):
url = env.mkurl("http", "test1", "/lorem.txt")
r = env.curl_get(url, options=[
"-H", "Accept-Encoding: br",
])
assert r.response, "no response"
assert r.response["status"] == 200
assert r.response["header"].get("content-encoding") == "br", \
f"expected Content-Encoding: br, got: {r.response['header']}"
lorem_path = os.path.join(env.server_dir, "htdocs", "test1",
"lorem.txt")
orig_size = os.path.getsize(lorem_path)
assert len(r.response["body"]) < orig_size, \
"compressed response should be smaller than the original"

# When the client does not advertise Accept-Encoding: br the response
# must be served uncompressed -- no Content-Encoding header.
def test_brotli_004_03_response_uncompressd(self, env):
url = env.mkurl("http", "test1", "/greeting.txt")
r = env.curl_get(url)
assert r.response, "no response"
assert r.response["status"] == 200
assert "content-encoding" not in r.response["header"], \
f"unexpected Content-Encoding present: " \
f"{r.response['header'].get('content-encoding')}"
body = r.response["body"].decode()
assert body.strip() == "Good morning, fellow!"

# Binary / non-matching content types must not be compressed.
def test_brotli_004_04_binary_no_match_no_compression(self, env):
bin_dir = os.path.join(env.server_dir, "htdocs", "test1")
bin_path = os.path.join(bin_dir, "pixel.png")
with open(bin_path, "wb") as f:
f.write(
b'\x89PNG\r\n\x1a\n'
b'\x00\x00\x00\rIHDR\x00\x00\x00\x01'
b'\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde'
b'\x00\x00\x00\x0cIDATx'
b'\x9cc\xf8\x0f\x00\x00\x01\x01\x00\x05'
b'\x18\xd8N\x00\x00\x00\x00IEND\xaeB`\x82'
)
url = env.mkurl("http", "test1", "/pixel.png")
r = env.curl_get(url, options=[
"-H", "Accept-Encoding: br",
])
assert r.response, "no response"
assert r.response["status"] == 200
assert r.response["header"].get("content-encoding") != "br", \
"binary content should not be brotli-compressed"
4 changes: 1 addition & 3 deletions test/pyhttpd/build-win.bat

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep the brotli change present in this file too.

Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ if NOT EXIST vcpkg\ (
)

@REM For some reason using the manifest doesn't install the default-features
vcpkg.exe install --triplet %VCPKG_TRIPLET% apr[private-headers] apr-util pcre2 openssl nghttp2 curl libxml2 jansson brotli
vcpkg.exe install --triplet %VCPKG_TRIPLET% apr[private-headers] apr-util pcre2 openssl nghttp2 curl libxml2 jansson

POPD

Expand Down Expand Up @@ -329,9 +329,7 @@ cmake "%HTTPD_SRC%" -B . ^
-DNGHTTP2_INCLUDE_DIR=%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/include ^
-DAPR_INCLUDE_DIR=%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/include ^
-DJANSSON_INCLUDE_DIR=%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/include ^
-DBROTLI_INCLUDE_DIR=%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/include ^
"-DAPR_LIBRARIES=%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/lib/libapr-1.lib;%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/lib/libaprutil-1.lib" ^
"-DBROTLI_LIBRARIES=%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/lib/brotlienc.lib;%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/lib/brotlidec.lib" ^
-DNGHTTP2_LIBRARIES=%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/lib/nghttp2.lib ^
-DJANSSON_LIBRARIES=%CWD%/vcpkg/installed/%VCPKG_TRIPLET%/lib/jansson.lib ^
-DENABLE_MIME_MAGIC=A ^
Expand Down
Loading