Skip to content

Commit 68d4a33

Browse files
committed
[Fix] proxy: CLI port passing, cookie loosening
1 parent d7016fe commit 68d4a33

File tree

1 file changed

+18
-21
lines changed

1 file changed

+18
-21
lines changed

src/py/extra/services/proxy.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22
from ..model import Service
33
from ..http.model import HTTPRequest, HTTPResponse
4+
from ..http.parser import iparseCookie, formatCookie
45
from ..decorators import on
56
from ..server import run
67
from ..client import HTTPClient
@@ -54,11 +55,12 @@ class ProxyTarget(NamedTuple):
5455
timeout: float = 2.0 # Default backend response timeout
5556

5657

58+
# TODO: Abstract headers pre-processing and post-processing
5759
class ProxyService(Service):
5860
def __init__(self, target: ProxyTarget, *, prefix: str | None = None):
5961
super().__init__(prefix=prefix)
6062
self.target: ProxyTarget = target
61-
info(f"Proxy service {self.prefix or ""} to {target.uri}")
63+
info(f"Proxy service {self.prefix or "/"} to {target.uri}")
6264

6365
@on(
6466
GET="{path:any}",
@@ -97,7 +99,7 @@ async def proxy(self, request: HTTPRequest, path: str) -> HTTPResponse:
9799
# Now we do the request
98100
res: HTTPResponse | None = None
99101
req_path: str = f"{uri.path or ""}{path}" if self.prefix else path
100-
info(f"Proxying {path} to {self.target.uri}")
102+
info(f"Proxying {path} to {uri.host}{req_path}")
101103
async for atom in HTTPClient.Request(
102104
host=uri.host or "localhost",
103105
path=req_path,
@@ -121,16 +123,17 @@ async def proxy(self, request: HTTPRequest, path: str) -> HTTPResponse:
121123
del res.headers.headers[name]
122124
updated_headers: dict[str, str] = {}
123125
# SEE: https://stackoverflow.com/questions/46288437/set-cookies-for-cross-origin-requests
124-
# for name, value in res.headers.headers.items():
125-
# match name:
126-
# # We loosen the cookies
127-
# case "Set-Cookie":
128-
# # FIXME: This is super brittle
129-
# updated_headers[name] = (
130-
# value.replace("Secure; ", "")
131-
# .replace("SameSite=Strict; ", "SameSite=Lax; ")
132-
# .replace("HTTPOnly", "")
133-
# ).strip(";")
126+
for name, value in res.headers.headers.items():
127+
match name:
128+
# We loosen the cookies so that they flow
129+
case "Set-Cookie":
130+
cookies = []
131+
for cookie in iparseCookie(value):
132+
if cookie.key in ("Secure", "HTTPOnly"):
133+
continue
134+
elif cookie.value == "Secure":
135+
cookies.append(cookie._replace(value="Lax"))
136+
updated_headers[name] = formatCookie(cookies)
134137
res.headers.headers.update(updated_headers)
135138
return (
136139
setCORSHeaders(res, origin=request.getHeader("Origin"))
@@ -192,19 +195,11 @@ def main(args: list[str]) -> None:
192195
# If args is None, it defaults to sys.argv[1:]
193196
options = parser.parse_args(args=args)
194197

195-
# The positional arguments are now in options.url
196-
# No need for len(args) == 0 check as nargs='+' handles it by raising an error
197-
# if no URL is provided.
198-
# If you want to handle it gracefully without exiting, you might need a try-except
199-
# around parse_args or check options.url after parsing.
200-
# For now, we assume argparse's default error handling is sufficient.
201-
202198
components: list[Service] = []
203199
for url in options.url:
204200
lc = url.split("=", 1)
205201
prefix, target = (None, url) if len(lc) == 1 else lc
206202
uri = URI.Parse(target)
207-
print(uri.asDict())
208203
if not uri.host:
209204
raise RuntimeError(f"URI has no host: {url}")
210205
components.append(
@@ -217,9 +212,11 @@ def main(args: list[str]) -> None:
217212
)
218213
)
219214

215+
# TODO: If proxy services start with /, this is pointless.
220216
if options.files:
221217
components.append(FileService(options.files))
222-
return run(*components)
218+
219+
return run(*components, port=options.port)
223220

224221

225222
if __name__ == "__main__":

0 commit comments

Comments
 (0)