diff --git a/apps/indeedhub/manifest.yml b/apps/indeedhub/manifest.yml index 31605ef9..b4f059cd 100644 --- a/apps/indeedhub/manifest.yml +++ b/apps/indeedhub/manifest.yml @@ -73,6 +73,8 @@ app: - exec: ["sh", "-c", "if ! grep -qE ']*nostr-provider' /usr/share/nginx/html/index.html && ! grep -qE '(sub_filter|##' /usr/share/nginx/html/index.html; fi"] - exec: ["sed", "-i", "s#tab-signer-v2#tab-signer-v4#g; s#tab-signer-v3#tab-signer-v4#g", "/etc/nginx/conf.d/default.conf", "/usr/share/nginx/html/index.html"] - exec: ["sed", "-i", "s#src=\"/nostr-provider.js\"#src=\"/nostr-provider.js?v=tab-signer-v4\"#g", "/etc/nginx/conf.d/default.conf", "/usr/share/nginx/html/index.html"] + # Compose the outer app-proxy prefix for NIP-98 signed URL verification. + - exec: ["sed", "-i", "s|proxy_set_header X-Forwarded-Prefix /api;|proxy_set_header X-Forwarded-Prefix $http_x_forwarded_prefix/api;|", "/etc/nginx/conf.d/default.conf"] - exec: ["nginx", "-s", "reload"] # TCP liveness on the nginx port, NOT an http GET of /. nginx binds 7777 at diff --git a/scripts/tests/test_indeehub_prefix_hook.py b/scripts/tests/test_indeehub_prefix_hook.py new file mode 100644 index 00000000..501bda94 --- /dev/null +++ b/scripts/tests/test_indeehub_prefix_hook.py @@ -0,0 +1,43 @@ +"""Offline behavior checks for the native post-install proxy prefix hook.""" +import pathlib +import subprocess +import tempfile +import unittest +import yaml + +ROOT = pathlib.Path(__file__).resolve().parents[2] + + +def prefix_hook(): + hooks = yaml.safe_load((ROOT / "apps/indeedhub/manifest.yml").read_text())["app"]["hooks"]["post_install"] + matches = [index for index, hook in enumerate(hooks) if "X-Forwarded-Prefix" in " ".join(hook.get("exec", []))] + assert len(matches) == 1 + index = matches[0] + assert hooks[index + 1] == {"exec": ["nginx", "-s", "reload"]} + return hooks[index]["exec"] + + +class IndeeHubPrefixHook(unittest.TestCase): + def test_composes_prefix_before_reload_and_is_idempotent(self): + original = "server {\n proxy_set_header Host $http_host;\n proxy_set_header X-Forwarded-Prefix /api;\n}\n" + expected = original.replace("X-Forwarded-Prefix /api;", "X-Forwarded-Prefix $http_x_forwarded_prefix/api;") + with tempfile.TemporaryDirectory() as directory: + config = pathlib.Path(directory) / "default.conf" + config.write_text(original) + args = prefix_hook() + self.assertEqual(args[-1], "/etc/nginx/conf.d/default.conf") + for _ in range(2): + subprocess.run([*args[:-1], str(config)], check=True) + self.assertEqual(config.read_text(), expected) + + def test_existing_composed_prefix_is_preserved(self): + original = "proxy_set_header X-Forwarded-Prefix $http_x_forwarded_prefix/api;\n" + with tempfile.TemporaryDirectory() as directory: + config = pathlib.Path(directory) / "default.conf" + config.write_text(original) + subprocess.run([*prefix_hook()[:-1], str(config)], check=True) + self.assertEqual(config.read_text(), original) + + +if __name__ == "__main__": + unittest.main()