"""Read-only HTTP checks for the isolated localhost:18080 deployment rehearsal.""" import hashlib import http.cookiejar from html.parser import HTMLParser import json from pathlib import Path import urllib.error import urllib.parse import urllib.request ROOT = Path(__file__).resolve().parents[1] BASE = "http://localhost:18080" class Links(HTMLParser): def __init__(self): super().__init__() self.urls = [] def handle_starttag(self, tag, attrs): values = dict(attrs) if tag in ("script", "img") and values.get("src"): self.urls.append(values["src"]) if tag == "link" and values.get("href"): self.urls.append(values["href"]) class NoRedirect(urllib.request.HTTPRedirectHandler): def redirect_request(self, req, fp, code, msg, headers, newurl): return None def main(): credentials = dict(line.split(": ", 1) for line in (ROOT / "artifacts/preview-access.txt").read_text().splitlines()) opener = urllib.request.build_opener(NoRedirect) cookies = http.cookiejar.CookieJar() signed_in = urllib.request.build_opener(NoRedirect, urllib.request.HTTPCookieProcessor(cookies)) def request(path, status=200, authenticated=False, data=None, headers=None): headers = dict(headers or {}) if data is not None: headers["Content-Type"] = "application/json" req = urllib.request.Request(BASE + path, headers=headers, data=json.dumps(data).encode() if data is not None else None) try: response = (signed_in if authenticated else opener).open(req, timeout=15) except urllib.error.HTTPError as error: response = error with response: body = response.read() assert response.status == status, (path, response.status, status) assert "WWW-Authenticate" not in response.headers, path return body, response.headers portal, _ = request("/") assert b'href="/blackjack/"' in portal and b'href="/wolin/"' in portal game, _ = request("/blackjack/") assert hashlib.sha256(game).digest() == hashlib.sha256( (ROOT / "deploy/site/blackjack/index.html").read_bytes()).digest() for path in ["/blackjack", "/wolin"]: _, headers = request(path, 308) assert headers["Location"].endswith(path + "/") _, headers = request("/wolin/", 303, headers={"Accept": "text/html"}) assert headers["Location"] == "/wolin/login" login_page, _ = request("/wolin/login") assert b'id="login-form"' in login_page for path in ["/wolin/docs", "/wolin/openapi.json", "/wolin/static/app.js", "/wolin/api/studentsManagement/workspace/overview", "/wolin/api/studentsManagement/ai/status"]: request(path, 401) request("/wolin/api/studentsManagement/workspace/query", 401, data={"module": "students"}) for path in ["/api/studentsManagement/workspace/overview", "/docs", "/openapi.json", "/static/app.js", "/.env", "/.env.cloud", "/.git/config"]: request(path, 404) request("/wolin/auth/login", 401, data={"username": credentials["Username"], "password": "incorrect-test-password"}) request("/wolin/auth/login", authenticated=True, data={"username": credentials["Username"], "password": credentials["Password"]}, headers={"Origin": BASE}) assert cookies, "Login did not issue a session cookie" assert all(cookie.path == "/wolin/" and cookie.has_nonstandard_attr("HttpOnly") for cookie in cookies) page, headers = request("/wolin/", authenticated=True) assert headers["Cache-Control"] == "no-store" parser = Links() parser.feed(page.decode()) for url in parser.urls: if urllib.parse.urlsplit(url).scheme: continue path = urllib.parse.urlsplit(urllib.parse.urljoin(BASE + "/wolin/", url)).path assert path.startswith("/wolin/"), path request(path, authenticated=True) request("/wolin/docs", authenticated=True) schema, _ = request("/wolin/openapi.json", authenticated=True) assert any(server["url"] == "/wolin" for server in json.loads(schema)["servers"]) body, _ = request("/wolin/api/studentsManagement/workspace/overview", authenticated=True) overview = json.loads(body) for module in ["students", "classes", "teachers", "advisors", "scores", "employment"]: request("/wolin/api/studentsManagement/workspace/query", authenticated=True, data={"module": module, "page": 1, "page_size": 1}) request("/wolin/auth/logout", authenticated=True, data={}) assert not list(cookies), "Logout did not clear the session" request("/wolin/api/studentsManagement/workspace/overview", 401, authenticated=True) report = {"portal": "ok", "game_bytes_match_online_build": True, "authentication": "form login, signed cookie, logout, private routes protected", "student_assets": "ok", "api_docs_prefix": "ok", "six_modules": "ok", "counts": overview["counts"]} (ROOT / "artifacts/cloud-preview-check.json").write_text( json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8") print(json.dumps(report, ensure_ascii=True)) if __name__ == "__main__": main()