Require ArchiveBox health in setup probes

This commit is contained in:
Nick Sweeting 2026-08-15 03:50:13 -07:00
parent b1dd33a541
commit 5ec6478b12
3 changed files with 31 additions and 9 deletions

View File

@ -1801,7 +1801,11 @@ class HealthCheckView(View):
"""
Handle a GET request
"""
return HttpResponse("OK", content_type="text/plain", status=200)
response = HttpResponse("OK", content_type="text/plain", status=200)
response["Access-Control-Allow-Origin"] = "*"
response["Access-Control-Expose-Headers"] = "X-ArchiveBox-Health"
response["X-ArchiveBox-Health"] = "OK"
return response
@render_with_table_view

View File

@ -262,21 +262,23 @@
document.getElementById('archivebox-setup-wildcard-help').hidden = dnsMode === 'localhost';
}
function probeUrl(url, generation) {
function probeUrl(url, generation, requireArchiveBoxHealth) {
var controller = new AbortController();
var timeout = window.setTimeout(function() { controller.abort(); }, 5000);
var target = new URL(url);
target.searchParams.set('archivebox_setup_probe', String(generation));
return fetch(target.toString(), {
method: 'GET',
mode: 'no-cors',
mode: requireArchiveBoxHealth ? 'cors' : 'no-cors',
credentials: 'omit',
cache: 'no-store',
redirect: 'follow',
signal: controller.signal,
}).then(function() {
}).then(function(response) {
window.clearTimeout(timeout);
return true;
return requireArchiveBoxHealth
? response.ok && response.headers.get('X-ArchiveBox-Health') === 'OK'
: true;
}).catch(function() {
window.clearTimeout(timeout);
return false;
@ -378,9 +380,9 @@
admin: probeUrl(preview.adminUrl, generation),
api: probeUrl(preview.apiUrl, generation),
index: probeUrl(preview.indexUrl, generation),
web: probeUrl(preview.webHealthUrl, generation),
snapshot: probeUrl(preview.snapshotHealthUrl, generation),
original: probeUrl(preview.originalHealthUrl, generation),
web: probeUrl(preview.webHealthUrl, generation, true),
snapshot: probeUrl(preview.snapshotHealthUrl, generation, true),
original: probeUrl(preview.originalHealthUrl, generation, true),
};
Promise.all(Object.keys(checks).map(function(key) { return checks[key].then(function(ok) { return [key, ok]; }); })).then(function(entries) {
if (generation !== probeGeneration || preview !== currentPreview) return;

View File

@ -12,6 +12,7 @@ from archivebox.config.common import get_config
from archivebox.core.middleware import AdminCookieIsolationMiddleware
from archivebox.core.setup_wizard import get_base_url_mismatch_context, get_setup_wizard_context
from archivebox.core.templatetags.core_tags import system_warnings_banner
from archivebox.core.views import HealthCheckView
STATIC_DIR = Path(__file__).parents[1] / "templates" / "static"
SETUP_WIZARD_CSS = (STATIC_DIR / "setup_wizard.css").read_text()
@ -213,13 +214,28 @@ def test_setup_wizard_assets_enforce_selection_and_access_requirements():
assert "Waiting for a matching browser URL and valid setup options" in SETUP_WIZARD_JS
assert "Finish the selected DNS, ingress, and TLS setup" in SETUP_WIZARD_JS
for target in ("adminUrl", "apiUrl", "indexUrl", "webHealthUrl", "snapshotHealthUrl", "originalHealthUrl"):
for target in ("adminUrl", "apiUrl", "indexUrl"):
assert f"probeUrl(preview.{target}" in SETUP_WIZARD_JS
assert "wildcardHealthUrl" not in SETUP_WIZARD_JS
assert "results.wildcard" not in SETUP_WIZARD_JS
assert "var coreReachable = results.admin && results.api && results.index && results.web && results.snapshot;" in SETUP_WIZARD_JS
assert "probeUrl(webOrigin + '/web/https://example.com'" not in SETUP_WIZARD_JS
assert "credentials: 'omit'" in SETUP_WIZARD_JS
assert "function probeUrl(url, generation, requireArchiveBoxHealth)" in SETUP_WIZARD_JS
assert "mode: requireArchiveBoxHealth ? 'cors' : 'no-cors'" in SETUP_WIZARD_JS
assert "response.ok && response.headers.get('X-ArchiveBox-Health') === 'OK'" in SETUP_WIZARD_JS
for target in ("webHealthUrl", "snapshotHealthUrl", "originalHealthUrl"):
assert f"probeUrl(preview.{target}, generation, true)" in SETUP_WIZARD_JS
def test_health_check_is_identifiable_across_ingress_origins():
response = HealthCheckView.as_view()(RequestFactory().get("/health/"))
assert response.status_code == 200
assert response.content == b"OK"
assert response["Access-Control-Allow-Origin"] == "*"
assert response["Access-Control-Expose-Headers"] == "X-ArchiveBox-Health"
assert response["X-ArchiveBox-Health"] == "OK"
@pytest.mark.parametrize(