nixpkgs-suyu/nixos/tests/nginx-etag-compression.nix

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

46 lines
1.7 KiB
Nix
Raw Normal View History

nginx: change etags for statically compressed files served from store Per RFC 9110, [section 8.8.1][1], different representations of the same resource should have different Etags: > A strong validator is unique across all versions of all > representations associated with a particular resource over time. > However, there is no implication of uniqueness across representations > of different resources (i.e., the same strong validator might be in > use for representations of multiple resources at the same time and > does not imply that those representations are equivalent) When serving statically compressed files (ie, when there is an existing corresponding .gz/.br/etc. file on disk), Nginx sends the Etag marked as strong. These tags should be different for each compressed format (as shown in an explicit example in section [8.8.3.3][2] of the RFC). Upstream Etags are composed of the file modification timestamp and content length, and the latter generally changes between these representations. Previous implementation of Nix-specific Etags for things served from store used the store hash. This is fine to share between different files, but it becomes a problem for statically compressed versions of the same file, as it means Nginx was serving different representations of the same resource with the same Etag, marked as strong. This patch addresses this by imitating the upstream Nginx behavior, and appending the value of content length to the store hash. [1]: https://www.rfc-editor.org/rfc/rfc9110.html#name-validator-fields [2]: https://www.rfc-editor.org/rfc/rfc9110.html#name-example-entity-tags-varying
2024-01-02 20:29:15 +01:00
import ./make-test-python.nix {
name = "nginx-etag-compression";
nodes.machine = { pkgs, lib, ... }: {
services.nginx = {
enable = true;
recommendedGzipSettings = true;
virtualHosts.default = {
root = pkgs.runCommandLocal "testdir" {} ''
mkdir "$out"
cat > "$out/index.html" <<EOF
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!
EOF
${pkgs.gzip}/bin/gzip -k "$out/index.html"
'';
};
};
};
testScript = { nodes, ... }: ''
machine.wait_for_unit("nginx")
machine.wait_for_open_port(80)
etag_plain = machine.succeed("curl -s -w'%header{etag}' -o/dev/null -H 'Accept-encoding:' http://127.0.0.1/")
etag_gzip = machine.succeed("curl -s -w'%header{etag}' -o/dev/null -H 'Accept-encoding:gzip' http://127.0.0.1/")
with subtest("different representations have different etags"):
assert etag_plain != etag_gzip, f"etags should differ: {etag_plain} == {etag_gzip}"
with subtest("etag for uncompressed response is reproducible"):
etag_plain_repeat = machine.succeed("curl -s -w'%header{etag}' -o/dev/null -H 'Accept-encoding:' http://127.0.0.1/")
assert etag_plain == etag_plain_repeat, f"etags should be the same: {etag_plain} != {etag_plain_repeat}"
with subtest("etag for compressed response is reproducible"):
etag_gzip_repeat = machine.succeed("curl -s -w'%header{etag}' -o/dev/null -H 'Accept-encoding:gzip' http://127.0.0.1/")
assert etag_gzip == etag_gzip_repeat, f"etags should be the same: {etag_gzip} != {etag_gzip_repeat}"
'';
}