Compare commits

..
4 Commits
Author SHA1 Message Date
ThePhaseless 1c9093f218 fix(ci): extract first image tag by line, not space
metadata-action emits tags newline-separated, so FIRST_TAG=${TAGS%% *}
kept the entire multi-line value and expanded to 4 args on tag releases,
making `imagetools inspect` fail before the manifest could be signed.
Split on the first line instead.
2026-08-09 19:25:09 +02:00
ThePhaseless 0c44ce1a4d fix: request uncompressed bodies in CSP-strip route
route.fulfill(response=...) re-serves the raw bytes fetched by
route.fetch(), so compressed (gzip/brotli/zstd) documents arrive
at the browser still compressed while the forwarded headers claim
otherwise - page.content() then returns garbled binary, breaking
indexers like uindex.org and 1337x.to (issue #385).

Fetch with accept-encoding: identity so the re-served body is plain
text, and drop content-encoding/content-length alongside the CSP
headers since they are stale after the rewrite.
2026-08-09 19:07:05 +02:00
renovate[bot] 07309c8d8e chore(deps): update dependency httpx2 to ==2.10.* (#386)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-08-09 16:33:10 +00:00
ThePhaseless 25194c3bca fix(ci): sign docker image by digest instead of tag 2026-08-08 02:20:35 +02:00
4 changed files with 54 additions and 21 deletions
+15 -6
View File
@@ -184,6 +184,7 @@ jobs:
# Create manifest lists and push
- name: Create and push manifest lists
id: manifests
run: |
TAGS="${{ steps.meta.outputs.tags }}"
args=""
@@ -213,11 +214,19 @@ jobs:
${image}:${{github.sha}}-arm64
fi
# Sign the manifest
- name: Sign the manifests
# All tags created above alias a single manifest list; capture its digest
# so the signature is bound to the image bytes, not a mutable tag.
# Tags from metadata-action are full references (image:tag), one per line,
# so take the first line rather than splitting on spaces.
FIRST_TAG=$(printf '%s' "$TAGS" | head -n1)
DIGEST=$(docker buildx imagetools inspect --format '{{.Manifest.Digest}}' "$FIRST_TAG")
echo "DIGEST=$DIGEST" >> $GITHUB_OUTPUT
# Sign the manifest list by digest — every consumer tag aliases this digest
- name: Sign the manifest list by digest
env:
TAGS: ${{ steps.meta.outputs.tags }}
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
DIGEST: ${{ steps.manifests.outputs.DIGEST }}
run: |
for TAG in $TAGS; do
cosign sign --yes $TAG
done
image=${IMAGE,,}
cosign sign --yes ${image}@${DIGEST}
+1 -1
View File
@@ -20,7 +20,7 @@ urls = { repository = "https://github.com/ThePhaseless/Byparr" }
[dependency-groups]
test = [
"httpx2==2.9.*",
"httpx2==2.10.*",
"pytest==9.1.*",
"pytest-asyncio==1.4.*",
"pytest-retry==1.7.*",
+18 -4
View File
@@ -26,8 +26,16 @@ router = APIRouter()
BrowserDep = Annotated[BrowserDepClass, Depends(get_browser)]
CSP_HEADERS = frozenset(
{"content-security-policy", "content-security-policy-report-only"}
# Headers to strip from the fulfilled response: CSP is removed for navigation
# freedom, and content-encoding/content-length are stale once we request an
# uncompressed body via accept-encoding: identity below.
DROP_HEADERS = frozenset(
{
"content-security-policy",
"content-security-policy-report-only",
"content-encoding",
"content-length",
}
)
@@ -80,7 +88,13 @@ async def read_item(request: LinkRequest, dep: BrowserDep) -> LinkResponse:
if route.request.resource_type != "document":
await route.continue_()
return
response = await route.fetch()
# Request an uncompressed body via accept-encoding: identity. When
# route.fulfill re-serves the fetched response (by uid), it forwards
# the original compressed bytes; stripping content-encoding below
# would leave the browser reading compressed bytes as plain text.
response = await route.fetch(
headers={**route.request.headers, "accept-encoding": "identity"}
)
if route.request.frame == dep.page.main_frame:
final_url = response.url
await route.fulfill(
@@ -88,7 +102,7 @@ async def read_item(request: LinkRequest, dep: BrowserDep) -> LinkResponse:
headers={
key: value
for key, value in response.headers.items()
if key.lower() not in CSP_HEADERS
if key.lower() not in DROP_HEADERS
},
)
Generated
+20 -10
View File
@@ -109,7 +109,7 @@ dev = [
{ name = "ruff", specifier = "==0.16.*" },
]
test = [
{ name = "httpx2", specifier = "==2.9.*" },
{ name = "httpx2", specifier = "==2.10.*" },
{ name = "pytest", specifier = "==9.1.*" },
{ name = "pytest-asyncio", specifier = "==1.4.*" },
{ name = "pytest-retry", specifier = "==1.7.*" },
@@ -450,15 +450,15 @@ wheels = [
[[package]]
name = "httpcore2"
version = "2.9.1"
version = "2.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "h11" },
{ name = "truststore" },
]
sdist = { url = "https://files.pythonhosted.org/packages/39/a8/20ed1ed79cbc2ecdf5301c0968ab7c85547212e2a7bd126ddd2d986e206e/httpcore2-2.9.1.tar.gz", hash = "sha256:4d8acbf8b306f48c9d6046591fd5ba4037d1b1b1000d140fc2c3eab1e9a0c0e2", size = 67089, upload-time = "2026-07-24T09:21:03.867Z" }
sdist = { url = "https://files.pythonhosted.org/packages/a9/83/a896fc59940fc5a6e2aff3a4be1d92fa890112936803b331cae75a993c34/httpcore2-2.10.0.tar.gz", hash = "sha256:13c0cc3d1919d4f28457f60cd2c2abe04113a8af184ccf1142811beba936f9dc", size = 67427, upload-time = "2026-08-09T09:11:32.123Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9f/fb/46c52b781975c335a2bcf1072c7bbc007cbdc8d674217f5ee1daba2c848b/httpcore2-2.9.1-py3-none-any.whl", hash = "sha256:6182472379e855fe4221246a2bb7ecede403bc61c6798062ae1787d051ccde26", size = 82809, upload-time = "2026-07-24T09:21:01.178Z" },
{ url = "https://files.pythonhosted.org/packages/e5/4f/d149104195a35e2853a2fc203a8e3477747e58c80e17dda686dace174383/httpcore2-2.10.0-py3-none-any.whl", hash = "sha256:7df06cfb34070cae4f7c89be69dc1095eca138e9704ceffb98d25c1912ab6f01", size = 83000, upload-time = "2026-08-09T09:11:29.555Z" },
]
[[package]]
@@ -500,17 +500,27 @@ wheels = [
[[package]]
name = "httpx2"
version = "2.9.1"
version = "2.10.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "httpcore2" },
{ name = "anyio", marker = "sys_platform != 'emscripten'" },
{ name = "httpcore2", marker = "sys_platform != 'emscripten'" },
{ name = "httpx2-jsfetch", marker = "sys_platform == 'emscripten'" },
{ name = "idna" },
{ name = "truststore" },
{ name = "truststore", marker = "sys_platform != 'emscripten'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/21/14/38128fbafd7e0ed41d874df6c9a653d47c2d111cfe59e2b4ac95161b4abd/httpx2-2.9.1.tar.gz", hash = "sha256:1932a768737e3666291582833da748cc4e563c337cf96706fccc04fa6e58764a", size = 95458, upload-time = "2026-07-24T09:21:04.972Z" }
sdist = { url = "https://files.pythonhosted.org/packages/bd/3d/f9a8c07a3884f3e5b26205e8436a18b3af61c5d53192c3bea235574dbbec/httpx2-2.10.0.tar.gz", hash = "sha256:8741d7329fe2c7885fc9ceb61c8217acfb87a85f75723714b89ebf7ad7196338", size = 98749, upload-time = "2026-08-09T09:11:33.24Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/13/b8/cfd91c4ab9134d386d48f0b6ac662ff3d4be6efdee59ee1c67ebc3c0487c/httpx2-2.9.1-py3-none-any.whl", hash = "sha256:1820fe14a9ab1107bfeff39259987429450b070ec0ff38cc87eb0d8c97fdc71a", size = 91191, upload-time = "2026-07-24T09:21:02.6Z" },
{ url = "https://files.pythonhosted.org/packages/b9/6d/a637d52449d98a6892d9a4dc0262587afdb6a66f201871842dce5a97b1c1/httpx2-2.10.0-py3-none-any.whl", hash = "sha256:5e3194a432701e1cc6f69a8b1b2fa199ef907013fede8d9a09a2c5b7b8141a18", size = 94355, upload-time = "2026-08-09T09:11:30.882Z" },
]
[[package]]
name = "httpx2-jsfetch"
version = "1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/0e5636363151a2a1795e0a77617168b9ca438e1748ec05fc9b5687f93d64/httpx2_jsfetch-1.0.tar.gz", hash = "sha256:70a0e3eabfef7cce5ad9c629f7d01ca05e418f586646f4ddf14782e4c1454c60", size = 6872, upload-time = "2026-08-07T00:13:07.492Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/9b/43/832f631d32e4f1211caa2ba368317739fe71f0b8530e4c9d15dc454bac2a/httpx2_jsfetch-1.0-py3-none-any.whl", hash = "sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32", size = 6382, upload-time = "2026-08-07T00:13:06.567Z" },
]
[[package]]