The generator page gives one upstream image several cache keys for host case and an empty path #293

Closed
opened 2026-10-16 03:31:19 +02:00 by clawbot · 2 comments
Collaborator

Where: internal/handlers/auth.go, HandleGenerateURL, on next after #289. Found by the review of #289.

What is wrong: the generator page passes the source host and path into the encrypted URL as entered. https://cdn.example.com and https://cdn.example.com/ make two cache keys for the same upstream request of /, and hosts that differ only in letter case (CDN.Example.com and cdn.example.com) make separate cache keys too, because the generator does not lower-case the host the way /v1/image/ does since #246.

How it fails: a logged-in user who makes image URLs for the same image spelled two ways gets the image fetched and stored twice. Only logged-in users reach the page.

Severity: low

Definition of done:

  1. The generator page lower-cases the source host and writes an empty source path as /, so each of those spellings makes one image URL with one cache key and one upstream request.
  2. Router tests first, against a test upstream that records each request; make check green.

Package: internal/handlers.

Model: opus-5-5

Where: `internal/handlers/auth.go`, `HandleGenerateURL`, on `next` after https://git.eeqj.de/sneak/pixa/pulls/289. Found by the review of https://git.eeqj.de/sneak/pixa/pulls/289. What is wrong: the generator page passes the source host and path into the encrypted URL as entered. `https://cdn.example.com` and `https://cdn.example.com/` make two cache keys for the same upstream request of `/`, and hosts that differ only in letter case (`CDN.Example.com` and `cdn.example.com`) make separate cache keys too, because the generator does not lower-case the host the way `/v1/image/` does since https://git.eeqj.de/sneak/pixa/issues/246. How it fails: a logged-in user who makes image URLs for the same image spelled two ways gets the image fetched and stored twice. Only logged-in users reach the page. Severity: low Definition of done: 1. The generator page lower-cases the source host and writes an empty source path as `/`, so each of those spellings makes one image URL with one cache key and one upstream request. 2. Router tests first, against a test upstream that records each request; `make check` green. Package: `internal/handlers`. Model: opus-5-5
clawbot self-assigned this 2026-10-16 03:31:25 +02:00
Author
Collaborator

Plan: in HandleGenerateURL, before the encrypted URL is built, the generator page lower-cases the source host, as /v1/image/ has done since #246, and writes an empty source path as /, as /v1/image/ does. The check from #289 then compares the fetched URL with the source URL after these two changes, so https://cdn.example.com?x=1 still makes an image URL.

Tests come first, in the existing router test file internal/server/source_url_internal_test.go, against its test upstream that records each request. Each pair of spellings is entered on the generator page, both image URLs are requested, and the upstream must receive one request:

  • https://192.0.2.10 and https://192.0.2.10/
  • for host case, an IPv6 address written in upper and in lower case, such as [2001:DB8::10] and [2001:db8::10]. A host name such as CDN.Example.com would need a DNS lookup, which the fetcher makes before it connects, so the test cannot use one.

No existing test changes.

Model: opus-5-5

Plan: in `HandleGenerateURL`, before the encrypted URL is built, the generator page lower-cases the source host, as `/v1/image/` has done since https://git.eeqj.de/sneak/pixa/issues/246, and writes an empty source path as `/`, as `/v1/image/` does. The check from https://git.eeqj.de/sneak/pixa/pulls/289 then compares the fetched URL with the source URL after these two changes, so `https://cdn.example.com?x=1` still makes an image URL. Tests come first, in the existing router test file `internal/server/source_url_internal_test.go`, against its test upstream that records each request. Each pair of spellings is entered on the generator page, both image URLs are requested, and the upstream must receive one request: - `https://192.0.2.10` and `https://192.0.2.10/` - for host case, an IPv6 address written in upper and in lower case, such as `[2001:DB8::10]` and `[2001:db8::10]`. A host name such as `CDN.Example.com` would need a DNS lookup, which the fetcher makes before it connects, so the test cannot use one. No existing test changes. Model: opus-5-5
Author
Collaborator

Built as planned in #294. Two differences from the plan: the two changes sit in a small function that parses the source URL, because HandleGenerateURL was already at the linter's length limit; and the IPv6 address in the test has a port, because the fetcher refuses an IPv6 address written without one. That refusal is outside this issue and is not fixed in the PR.

Model: opus-5-5

Built as planned in https://git.eeqj.de/sneak/pixa/pulls/294. Two differences from the plan: the two changes sit in a small function that parses the source URL, because `HandleGenerateURL` was already at the linter's length limit; and the IPv6 address in the test has a port, because the fetcher refuses an IPv6 address written without one. That refusal is outside this issue and is not fixed in the PR. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/pixa#293