summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/decky_loader/utilities.py22
1 files changed, 18 insertions, 4 deletions
diff --git a/backend/decky_loader/utilities.py b/backend/decky_loader/utilities.py
index 4962da32..69c69fe6 100644
--- a/backend/decky_loader/utilities.py
+++ b/backend/decky_loader/utilities.py
@@ -9,7 +9,7 @@ from traceback import format_exc
from stat import FILE_ATTRIBUTE_HIDDEN # pyright: ignore [reportAttributeAccessIssue, reportUnknownVariableType]
from asyncio import StreamReader, StreamWriter, start_server, gather, open_connection
-from aiohttp import ClientSession
+from aiohttp import ClientSession, hdrs
from aiohttp.web import Request, StreamResponse, Response, json_response, post
from typing import TYPE_CHECKING, Callable, Coroutine, Dict, Any, List, TypedDict
@@ -153,14 +153,14 @@ class Utilities:
headers["User-Agent"] = helpers.user_agent
for excluded_header in excluded_default_headers:
- self.logger.debug(f"Excluding default header {excluded_header}")
if excluded_header in headers:
+ self.logger.debug(f"Excluding default header {excluded_header}: {headers[excluded_header]}")
del headers[excluded_header]
if "X-Decky-Fetch-Excluded-Headers" in req.headers:
for excluded_header in req.headers["X-Decky-Fetch-Excluded-Headers"].split(", "):
- self.logger.debug(f"Excluding header {excluded_header}")
if excluded_header in headers:
+ self.logger.debug(f"Excluding header {excluded_header}: {headers[excluded_header]}")
del headers[excluded_header]
for header in req.headers:
@@ -187,7 +187,21 @@ class Utilities:
# defeat the point of this proxy.
async with ClientSession(auto_decompress=False) as web:
async with web.request(req.method, url, headers=headers, data=body, ssl=helpers.get_ssl_context()) as web_res:
- res = StreamResponse(headers=web_res.headers, status=web_res.status)
+ # Whenever the aiohttp_cors is used, it expects a near complete control over whatever headers are needed
+ # for `aiohttp_cors.ResourceOptions`. As a server, if you delegate CORS handling to aiohttp_cors,
+ # the headers below must NOT be set. Otherwise they would be overwritten by aiohttp_cors and there would be
+ # logic bugs, so it was probably a smart choice to assert if the headers are present.
+ #
+ # However, this request handler method does not act like our own local server, it always acts like a proxy
+ # where we do not have control over the response headers. For responses that do not allow CORS, we add the support
+ # via aiohttp_cors. For responses that allow CORS, we have to remove the conflicting headers to allow
+ # aiohttp_cors handle it for us as if there was no CORS support.
+ aiohttp_cors_compatible_headers = web_res.headers.copy()
+ aiohttp_cors_compatible_headers.popall(hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, default=None)
+ aiohttp_cors_compatible_headers.popall(hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, default=None)
+ aiohttp_cors_compatible_headers.popall(hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, default=None)
+
+ res = StreamResponse(headers=aiohttp_cors_compatible_headers, status=web_res.status)
if web_res.headers.get('Transfer-Encoding', '').lower() == 'chunked':
res.enable_chunked_encoding()