repos
/ orchard main

orchard

mirror

Every 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

2.4 KB · 69 lines · Go Raw History
 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}