feat: X-Redirect pages
This commit is contained in:
+23
-1
@@ -109,7 +109,7 @@ class TestDataDir(BaseTestCase):
|
||||
self.assert_file_content(self.tmp_path / "test_1" / "value", "value")
|
||||
assert not (self.tmp_path / "test_1" / ".value").exists()
|
||||
assert not (self.tmp_path / "test_1" / ".git").exists()
|
||||
assert (self.tmp_path / "test_1" / "dir").exists()
|
||||
assert (self.tmp_path / "test_1" / "dir").is_dir()
|
||||
assert not (self.tmp_path / "test_1" / "dir" / ".invalid").exists()
|
||||
assert not (self.tmp_path / "test_1" / "dir" / ".test").exists()
|
||||
|
||||
@@ -128,6 +128,28 @@ class TestDataDir(BaseTestCase):
|
||||
self.data_dir.extract_tar_bytes("~test", tar_bytes)
|
||||
assert not (self.tmp_path / "~test").exists()
|
||||
|
||||
def test_empty_create(self) -> None:
|
||||
self.data_dir.empty("test_1")
|
||||
assert (self.tmp_path / "test_1").is_dir()
|
||||
self.assertListEqual(list((self.tmp_path / "test_1").iterdir()), [])
|
||||
|
||||
def test_empty_existing(self) -> None:
|
||||
self.__create_path("test_1", {".host": "value"})
|
||||
self.data_dir.empty("test_1")
|
||||
assert (self.tmp_path / "test_1").is_dir()
|
||||
self.assertListEqual(list((self.tmp_path / "test_1").iterdir()), [])
|
||||
|
||||
def test_exists_invalid_dir(self) -> None:
|
||||
self.__create_path(".certbot")
|
||||
assert not self.data_dir.exists(".certbot")
|
||||
|
||||
def test_exists_ok(self) -> None:
|
||||
self.__create_path("test_1")
|
||||
assert self.data_dir.exists("test_1")
|
||||
|
||||
def test_exists_fail(self) -> None:
|
||||
assert not self.data_dir.exists("test_1")
|
||||
|
||||
def __create_path(self, path: str, files: dict[str, str] | None = None) -> None:
|
||||
(self.tmp_path / path).mkdir()
|
||||
if files is not None:
|
||||
|
||||
+151
-11
@@ -156,6 +156,24 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
handler.data_dir = self.data_dir
|
||||
return handler
|
||||
|
||||
def test_do_head_redirect(self) -> None:
|
||||
handler = self._get_handler("/path")
|
||||
with (
|
||||
self.mock_call(
|
||||
self.registry.get_from_path,
|
||||
["path"],
|
||||
Page("path", redirect="https://example.com"),
|
||||
),
|
||||
self.expects_status_only(
|
||||
handler,
|
||||
http.HTTPStatus.MOVED_PERMANENTLY,
|
||||
headers={"Location": "https://example.com"},
|
||||
),
|
||||
self.patch("http.server.SimpleHTTPRequestHandler.do_HEAD", count=0),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
handler.do_HEAD()
|
||||
|
||||
def test_do_head_proxy(self) -> None:
|
||||
handler = self._get_handler()
|
||||
with (
|
||||
@@ -165,9 +183,28 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
handler.do_HEAD()
|
||||
|
||||
def test_do_get_index(self) -> None:
|
||||
handler = self._get_handler("/")
|
||||
handler = self._get_handler()
|
||||
with (
|
||||
self.expects_basic_body(handler, handler.server_signature()),
|
||||
self.patch("http.server.SimpleHTTPRequestHandler.do_GET", count=0),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
handler.do_GET()
|
||||
|
||||
def test_do_get_redirect(self) -> None:
|
||||
handler = self._get_handler("/path")
|
||||
with (
|
||||
self.mock_call(
|
||||
self.registry.get_from_path,
|
||||
["path"],
|
||||
Page("path", redirect="https://example.com"),
|
||||
),
|
||||
self.expects_status_only(
|
||||
handler,
|
||||
http.HTTPStatus.MOVED_PERMANENTLY,
|
||||
headers={"Location": "https://example.com"},
|
||||
),
|
||||
self.patch("http.server.SimpleHTTPRequestHandler.do_GET", count=0),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
handler.do_GET()
|
||||
@@ -175,6 +212,10 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
def test_do_get_proxy_on_other_path(self) -> None:
|
||||
handler = self._get_handler("/file")
|
||||
with (
|
||||
self.mock_call(
|
||||
self.registry.get_from_path,
|
||||
["file"],
|
||||
),
|
||||
self.patch("http.server.SimpleHTTPRequestHandler.do_GET"),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
@@ -183,6 +224,10 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
def test_do_get_proxy_on_other_host(self) -> None:
|
||||
handler = self._get_handler("/", {"Host": "other_host"})
|
||||
with (
|
||||
self.mock_call(
|
||||
self.registry.get_from_host,
|
||||
["other_host"],
|
||||
),
|
||||
self.patch("http.server.SimpleHTTPRequestHandler.do_GET"),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
@@ -271,7 +316,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
):
|
||||
handler.do_PUT()
|
||||
|
||||
def test_do_put_no_content(self) -> None:
|
||||
def test_do_put_extract_no_content(self) -> None:
|
||||
handler = self._get_handler("/path", {"X-Token": "secret"})
|
||||
with (
|
||||
self.mock_call(self.token_manager.is_valid, ["secret"], True), # noqa: FBT003
|
||||
@@ -287,7 +332,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
):
|
||||
handler.do_PUT()
|
||||
|
||||
def test_do_put_content_too_large(self) -> None:
|
||||
def test_do_put_extract_content_too_large(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path", {"X-Token": "secret", "Content-Length": "999999999"}
|
||||
)
|
||||
@@ -307,7 +352,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
):
|
||||
handler.do_PUT()
|
||||
|
||||
def test_do_put_tar_error(self) -> None:
|
||||
def test_do_put_extract_tar_error(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path", {"X-Token": "secret", "Content-Length": "1"}
|
||||
)
|
||||
@@ -328,7 +373,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
handler.do_PUT()
|
||||
self.data_dir.extract_tar_bytes.assert_called_once()
|
||||
|
||||
def test_do_put_extract_error(self) -> None:
|
||||
def test_do_put_extract_other_error(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path", {"X-Token": "secret", "Content-Length": "1"}
|
||||
)
|
||||
@@ -347,7 +392,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
handler.do_PUT()
|
||||
self.data_dir.extract_tar_bytes.assert_called_once()
|
||||
|
||||
def test_do_put_ok(self) -> None:
|
||||
def test_do_put_extract_ok(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path", {"X-Token": "secret", "Content-Length": "1"}
|
||||
)
|
||||
@@ -361,7 +406,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
),
|
||||
self.mock_call_unchecked(self.data_dir.extract_tar_bytes),
|
||||
self.mock_call(self.registry.add, ["path"]),
|
||||
self.mock_call(self.token_manager.set_token, ["secret", "path"]),
|
||||
self.mock_call(self.token_manager.set_token, ["path", "secret"]),
|
||||
self.expects_status_only(
|
||||
handler, http.HTTPStatus.CREATED, "Resource /path/ updated"
|
||||
),
|
||||
@@ -369,7 +414,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
):
|
||||
handler.do_PUT()
|
||||
|
||||
def test_do_put_ok_with_host_fail_init(self) -> None:
|
||||
def test_do_put_extract_with_host_fail_init(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path",
|
||||
{"X-Token": "secret", "Content-Length": "1", "X-Host": "example.com"},
|
||||
@@ -385,7 +430,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
self.mock_call(self.registry.get_from_host, ["example.com"], Page("path")),
|
||||
self.mock_call_unchecked(self.data_dir.extract_tar_bytes),
|
||||
self.mock_call(self.registry.add, ["path"]),
|
||||
self.mock_call(self.token_manager.set_token, ["secret", "path"]),
|
||||
self.mock_call(self.token_manager.set_token, ["path", "secret"]),
|
||||
self.mock_call(self.cert_manager.create_or_update, ["example.com"], False), # noqa: FBT003
|
||||
self.expects_status_only(
|
||||
handler, http.HTTPStatus.CREATED, "Resource /path/ updated"
|
||||
@@ -394,7 +439,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
):
|
||||
handler.do_PUT()
|
||||
|
||||
def test_do_put_ok_with_host(self) -> None:
|
||||
def test_do_put_extract_with_host(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path",
|
||||
{"X-Token": "secret", "Content-Length": "1", "X-Host": "example.com"},
|
||||
@@ -410,7 +455,88 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
self.mock_call(self.registry.get_from_host, ["example.com"], Page("path")),
|
||||
self.mock_call_unchecked(self.data_dir.extract_tar_bytes),
|
||||
self.mock_call(self.registry.add, ["path"]),
|
||||
self.mock_call(self.token_manager.set_token, ["secret", "path"]),
|
||||
self.mock_call(self.token_manager.set_token, ["path", "secret"]),
|
||||
self.mock_call(self.cert_manager.create_or_update, ["example.com"], True), # noqa: FBT003
|
||||
self.mock_call(self.registry.set_host, ["path", "example.com"]),
|
||||
self.expects_status_only(
|
||||
handler, http.HTTPStatus.CREATED, "Resource /path/ updated"
|
||||
),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
handler.do_PUT()
|
||||
|
||||
def test_do_put_redirect_with_content(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path",
|
||||
{
|
||||
"X-Token": "secret",
|
||||
"X-Redirect": "https://example.com",
|
||||
"Content-Length": "1",
|
||||
},
|
||||
)
|
||||
with (
|
||||
self.mock_call(self.token_manager.is_valid, ["secret"], True), # noqa: FBT003
|
||||
self.mock_call(
|
||||
self.token_manager.is_valid_for_path,
|
||||
["secret", "path"],
|
||||
True, # noqa: FBT003
|
||||
),
|
||||
self.expects_error(
|
||||
handler,
|
||||
http.HTTPStatus.BAD_REQUEST,
|
||||
"No content must be sent with X-Redirect",
|
||||
),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
handler.do_PUT()
|
||||
|
||||
def test_do_put_redirect_ok(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path",
|
||||
{
|
||||
"X-Token": "secret",
|
||||
"X-Redirect": "https://example.com",
|
||||
},
|
||||
)
|
||||
with (
|
||||
self.mock_call(self.token_manager.is_valid, ["secret"], True), # noqa: FBT003
|
||||
self.mock_call(
|
||||
self.token_manager.is_valid_for_path,
|
||||
["secret", "path"],
|
||||
True, # noqa: FBT003
|
||||
),
|
||||
self.mock_call(self.data_dir.empty, ["path"]),
|
||||
self.mock_call(self.registry.add, ["path"]),
|
||||
self.mock_call(self.token_manager.set_token, ["path", "secret"]),
|
||||
self.mock_call(self.registry.set_redirect, ["path", "https://example.com"]),
|
||||
self.expects_status_only(
|
||||
handler, http.HTTPStatus.CREATED, "Resource /path/ updated"
|
||||
),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
handler.do_PUT()
|
||||
|
||||
def test_do_put_redirect_with_host(self) -> None:
|
||||
handler = self._get_handler(
|
||||
"/path",
|
||||
{
|
||||
"X-Token": "secret",
|
||||
"X-Redirect": "https://example.com",
|
||||
"X-Host": "example.com",
|
||||
},
|
||||
)
|
||||
with (
|
||||
self.mock_call(self.token_manager.is_valid, ["secret"], True), # noqa: FBT003
|
||||
self.mock_call(
|
||||
self.token_manager.is_valid_for_path,
|
||||
["secret", "path"],
|
||||
True, # noqa: FBT003
|
||||
),
|
||||
self.mock_call(self.registry.get_from_host, ["example.com"], Page("path")),
|
||||
self.mock_call(self.data_dir.empty, ["path"]),
|
||||
self.mock_call(self.registry.add, ["path"]),
|
||||
self.mock_call(self.token_manager.set_token, ["path", "secret"]),
|
||||
self.mock_call(self.registry.set_redirect, ["path", "https://example.com"]),
|
||||
self.mock_call(self.cert_manager.create_or_update, ["example.com"], True), # noqa: FBT003
|
||||
self.mock_call(self.registry.set_host, ["path", "example.com"]),
|
||||
self.expects_status_only(
|
||||
@@ -577,6 +703,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
def test_translate_path_dotfile(self) -> None:
|
||||
handler = self._get_handler()
|
||||
with (
|
||||
self.mock_call(self.registry.get_from_path, ["path"], Page("path")),
|
||||
self.patch("http.server.SimpleHTTPRequestHandler.translate_path", count=0),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
@@ -603,6 +730,7 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
def test_translate_path_default_host(self) -> None:
|
||||
handler = self._get_handler()
|
||||
with (
|
||||
self.mock_call(self.registry.get_from_path, ["path"], Page("path")),
|
||||
self.patch_call(
|
||||
"http.server.SimpleHTTPRequestHandler.translate_path",
|
||||
["/path/index.html"],
|
||||
@@ -614,6 +742,18 @@ class TestRequestHandler(BaseHandlerTestCase):
|
||||
None,
|
||||
)
|
||||
|
||||
def test_translate_path_default_host_not_found(self) -> None:
|
||||
handler = self._get_handler()
|
||||
with (
|
||||
self.mock_call(self.registry.get_from_path, ["path"]),
|
||||
self.patch("http.server.SimpleHTTPRequestHandler.translate_path", count=0),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
self.assertEqual(
|
||||
handler.translate_path("/path/index.html"),
|
||||
"",
|
||||
)
|
||||
|
||||
|
||||
class TestUpgradeHandler(BaseHandlerTestCase):
|
||||
def _get_handler(
|
||||
|
||||
@@ -15,3 +15,9 @@ class TestPage(BaseTestCase):
|
||||
str(Page("test_1", with_index=True, host="example.com")),
|
||||
"/test_1/ [example.com]",
|
||||
)
|
||||
|
||||
def test_repr_with_redirect(self) -> None:
|
||||
self.assertEqual(
|
||||
str(Page("test_1", redirect="https://example.com")),
|
||||
"/test_1/ (redirect: https://example.com)",
|
||||
)
|
||||
|
||||
@@ -29,14 +29,18 @@ class TestRegistry(BaseTestCase):
|
||||
[
|
||||
["test_1", Registry.HOST_FILE],
|
||||
["test_1", Registry.TOKEN_FILE],
|
||||
["test_1", Registry.REDIRECT_FILE],
|
||||
["test_2", Registry.HOST_FILE],
|
||||
["test_2", Registry.TOKEN_FILE],
|
||||
["test_2", Registry.REDIRECT_FILE],
|
||||
],
|
||||
[
|
||||
"test_1_host",
|
||||
"test_1_token",
|
||||
None,
|
||||
None,
|
||||
"test_2_token",
|
||||
"test_2_redirect",
|
||||
],
|
||||
),
|
||||
self.seal_mocks(),
|
||||
@@ -51,6 +55,7 @@ class TestRegistry(BaseTestCase):
|
||||
True, # noqa: FBT003
|
||||
"test_1_host",
|
||||
"test_1_token",
|
||||
None,
|
||||
),
|
||||
)
|
||||
self.assertEqual(
|
||||
@@ -60,6 +65,7 @@ class TestRegistry(BaseTestCase):
|
||||
False, # noqa: FBT003
|
||||
None,
|
||||
"test_2_token",
|
||||
"test_2_redirect",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -108,6 +114,23 @@ class TestRegistry(BaseTestCase):
|
||||
self.registry.set_token_hash("test_1", "new_value")
|
||||
self.assertEqual(self.registry.pages["test_1"].token_hash, "new_value")
|
||||
|
||||
def test_set_redirect(self) -> None:
|
||||
self.registry.pages["test_1"] = Page(
|
||||
"test_1",
|
||||
redirect="https://example.com",
|
||||
)
|
||||
with (
|
||||
self.mock_call(
|
||||
self.data_dir.set_file,
|
||||
["test_1", Registry.REDIRECT_FILE, "https://new-example.com"],
|
||||
),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
self.registry.set_redirect("test_1", "https://new-example.com")
|
||||
self.assertEqual(
|
||||
self.registry.pages["test_1"].redirect, "https://new-example.com"
|
||||
)
|
||||
|
||||
def test_remove(self) -> None:
|
||||
self.registry.pages["test_1"] = Page(
|
||||
"test_1",
|
||||
|
||||
@@ -117,7 +117,7 @@ class TestTokenManager(BaseTestCase):
|
||||
),
|
||||
self.seal_mocks(),
|
||||
):
|
||||
self.token_manager.set_token("secret", "test_1")
|
||||
self.token_manager.set_token("test_1", "secret")
|
||||
|
||||
@unittest.mock.patch("secrets.token_hex")
|
||||
def test_new_token(self, mock_token_hex: unittest.mock.Mock) -> None:
|
||||
|
||||
Reference in New Issue
Block a user