orchard
mirrorEvery site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.
blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics
1package main
2
3import (
4 "testing"
5 "testing/fstest"
6)
7
8func testDist() fstest.MapFS {
9 f := &fstest.MapFile{Data: []byte("x")}
10 return fstest.MapFS{
11 "images/art/acrylic-pours/000-480.avif": f,
12 "images/art/acrylic-pours/000-960.avif": f,
13 "images/art/acrylic-pours/000-1600.avif": f,
14 "images/art/acrylic-pours/006-480.avif": f,
15 "images/avatar.avif": f,
16 "images/favicon.png": f,
17 }
18}
19
20// The old optimiser asked for a .webp and a width in the query string. Both
21// moved into the filename, so the mapping has to put them back together.
22func TestNextImageResolves(t *testing.T) {
23 idx := newNextImageIndex(testDist())
24
25 for _, tc := range []struct {
26 url string
27 want int
28 out string
29 }{
30 // Smallest width at or above the request, so nothing is upscaled.
31 {"/static/images/art/acrylic-pours/000.webp", 960, "/static/images/art/acrylic-pours/000-960.avif"},
32 {"/static/images/art/acrylic-pours/000.webp", 500, "/static/images/art/acrylic-pours/000-960.avif"},
33 {"/static/images/art/acrylic-pours/000.webp", 480, "/static/images/art/acrylic-pours/000-480.avif"},
34 // More than anything here has, so the largest available.
35 {"/static/images/art/acrylic-pours/000.webp", 3840, "/static/images/art/acrylic-pours/000-1600.avif"},
36 // No width given at all still has to answer with something.
37 {"/static/images/art/acrylic-pours/000.webp", 0, "/static/images/art/acrylic-pours/000-480.avif"},
38 {"/static/images/art/acrylic-pours/006.webp", 1600, "/static/images/art/acrylic-pours/006-480.avif"},
39 // Never had size variants.
40 {"/static/images/avatar.webp", 640, "/static/images/avatar.avif"},
41 {"/static/images/favicon.png", 64, "/static/images/favicon.png"},
42 } {
43 got, ok := idx.resolve(tc.url, tc.want)
44 if !ok || got != tc.out {
45 t.Errorf("resolve(%q, %d) = %q,%v want %q", tc.url, tc.want, got, ok, tc.out)
46 }
47 }
48}
49
50// An open redirect here would turn a dead endpoint into a way to bounce someone
51// off this domain, and the url parameter is entirely attacker controlled.
52func TestNextImageRefusesAnythingOffSite(t *testing.T) {
53 idx := newNextImageIndex(testDist())
54
55 for _, url := range []string{
56 "https://evil.example/x.webp",
57 "//evil.example/x.webp",
58 "/etc/passwd",
59 "/static/../../etc/passwd",
60 "/images/art/acrylic-pours/000.webp",
61 "/static/images/does-not-exist.webp",
62 "",
63 } {
64 if got, ok := idx.resolve(url, 640); ok {
65 t.Errorf("resolve(%q) = %q, want refused", url, got)
66 }
67 }
68}