[Worker support] test for no cors headers (#1374)

* test for no cors headers

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix tests

* suggested changes

* disable directly

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* add error message

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* improve test

* improve error message

* remove py-config tag from cors test

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Madhur Tandon
2023-05-02 18:43:11 +05:30
committed by GitHub
parent 82613d016a
commit cd1aa948f9
5 changed files with 92 additions and 20 deletions

View File

@@ -123,13 +123,17 @@ def browser_type_launch_args(request):
return launch_options
class HTTPServer(SuperHTTPServer):
class DevServer(SuperHTTPServer):
"""
Class for wrapper to run SimpleHTTPServer on Thread.
Ctrl +Only Thread remains dead when terminated with C.
Keyboard Interrupt passes.
"""
def __init__(self, base_url, *args, **kwargs):
self.base_url = base_url
super().__init__(*args, **kwargs)
def run(self):
try:
self.serve_forever()
@@ -140,15 +144,26 @@ class HTTPServer(SuperHTTPServer):
@pytest.fixture(scope="session")
def http_server(logger):
def dev_server(logger):
class MyHTTPRequestHandler(SimpleHTTPRequestHandler):
enable_cors_headers = True
@classmethod
def my_headers(cls):
if cls.enable_cors_headers:
return {
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Opener-Policy": "same-origin",
}
return {}
def end_headers(self):
self.send_my_headers()
SimpleHTTPRequestHandler.end_headers(self)
def send_my_headers(self):
self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
self.send_header("Cross-Origin-Opener-Policy", "same-origin")
for k, v in self.my_headers().items():
self.send_header(k, v)
def log_message(self, fmt, *args):
logger.log("http_server", fmt % args, color="blue")
@@ -157,12 +172,12 @@ def http_server(logger):
base_url = f"http://{host}:{port}"
# serve_Run forever under thread
server = HTTPServer((host, port), MyHTTPRequestHandler)
server = DevServer(base_url, (host, port), MyHTTPRequestHandler)
thread = threading.Thread(None, server.run)
thread.start()
yield base_url # Transition to test here
yield server # Transition to test here
# End thread
server.shutdown()

View File

@@ -158,16 +158,17 @@ class PyScriptTest:
self.tmpdir.chdir()
self.logger = logger
self.execution_thread = execution_thread
self.dev_server = None
if request.config.option.no_fake_server:
# use a real HTTP server. Note that as soon as we request the
# fixture, the server automatically starts in its own thread.
self.http_server = request.getfixturevalue("http_server")
self.dev_server = request.getfixturevalue("dev_server")
self.http_server_addr = self.dev_server.base_url
self.router = None
self.is_fake_server = False
else:
# use the internal playwright routing
self.http_server = "https://fake_server"
self.http_server_addr = "https://fake_server"
self.router = SmartRouter(
"fake_server",
cache=request.config.cache,
@@ -175,7 +176,6 @@ class PyScriptTest:
usepdb=request.config.option.usepdb,
)
self.router.install(page)
self.is_fake_server = True
#
self.init_page(page)
#
@@ -211,6 +211,18 @@ class PyScriptTest:
page.on("console", self._on_console)
page.on("pageerror", self._on_pageerror)
@property
def headers(self):
if self.dev_server is None:
return self.router.headers
return self.dev_server.RequestHandlerClass.my_headers()
def disable_cors_headers(self):
if self.dev_server is None:
self.router.enable_cors_headers = False
else:
self.dev_server.RequestHandlerClass.enable_cors_headers = False
def run_js(self, code):
"""
allows top level await to be present in the `code` parameter
@@ -301,7 +313,7 @@ class PyScriptTest:
def goto(self, path):
self.logger.reset()
self.logger.log("page.goto", path, color="yellow")
url = f"{self.http_server}/{path}"
url = f"{self.http_server_addr}/{path}"
self.page.goto(url, timeout=0)
def wait_for_console(
@@ -433,8 +445,8 @@ class PyScriptTest:
doc = f"""
<html>
<head>
<link rel="stylesheet" href="{self.http_server}/build/pyscript.css" />
<script defer src="{self.http_server}/build/pyscript.js"></script>
<link rel="stylesheet" href="{self.http_server_addr}/build/pyscript.css" />
<script defer src="{self.http_server_addr}/build/pyscript.js"></script>
{extra_head}
</head>
<body>
@@ -851,6 +863,16 @@ class SmartRouter:
self.usepdb = usepdb
self.page = None
self.requests = [] # (status, kind, url)
self.enable_cors_headers = True
@property
def headers(self):
if self.enable_cors_headers:
return {
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Opener-Policy": "same-origin",
}
return {}
def install(self, page):
"""
@@ -903,13 +925,9 @@ class SmartRouter:
assert url.path[0] == "/"
relative_path = url.path[1:]
if os.path.exists(relative_path):
headers = {
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Opener-Policy": "same-origin",
}
route.fulfill(status=200, headers=headers, path=relative_path)
route.fulfill(status=200, headers=self.headers, path=relative_path)
else:
route.fulfill(status=404)
route.fulfill(status=404, headers=self.headers)
return
# network requests might be cached

View File

@@ -113,7 +113,7 @@ class TestSupport(PyScriptTest):
f"""
JS errors found: 1
Error: this is an error
at {self.http_server}/mytest.html:.*
at {self.http_server_addr}/mytest.html:.*
"""
).strip()
assert re.search(expected, msg)

View File

@@ -32,6 +32,30 @@ class TestBasic(PyScriptTest):
expected = f"[pyscript/main] Starting the interpreter in {where}"
assert expected in self.console.info.lines
def test_no_cors_headers(self):
self.disable_cors_headers()
self.pyscript_run(
"""
<!-- we don't really need anything here, we just want to check that
pyscript starts -->
""",
wait_for_pyscript=False,
)
assert self.headers == {}
if self.execution_thread == "worker":
expected_alert_banner_msg = (
'(PY1000): When execution_thread is "worker", the site must be cross origin '
"isolated, but crossOriginIsolated is false. To be cross origin isolated, "
"the server must use https and also serve with the following headers: "
'{"Cross-Origin-Embedder-Policy":"require-corp",'
'"Cross-Origin-Opener-Policy":"same-origin"}. '
"The problem may be that one or both of these are missing."
)
alert_banner = self.page.wait_for_selector(".alert-banner")
assert expected_alert_banner_msg in alert_banner.inner_text()
else:
self.assert_no_banners()
def test_print(self):
self.pyscript_run(
"""