package config import ( "slices" "testing" ) // TestRefererBlocklistParsed loads a referer_blocklist with a host and a // pattern starting with "." and checks both are kept in order. func TestRefererBlocklistParsed(t *testing.T) { t.Parallel() c, err := configFromYAML(t, signingKeyLine+`referer_blocklist: - leech.example - .hotlinker.example `) if err != nil { t.Fatalf("valid referer_blocklist should load, got error: %v", err) } want := []string{"leech.example", ".hotlinker.example"} if !slices.Equal(c.RefererBlocklist, want) { t.Errorf("RefererBlocklist = %v, want %v", c.RefererBlocklist, want) } } // TestRefererBlocklistAcceptsIPAddresses checks that IPv4 and IPv6 addresses, // the IPv6 one written without brackets, are accepted as entries. func TestRefererBlocklistAcceptsIPAddresses(t *testing.T) { t.Parallel() c, err := configFromYAML(t, signingKeyLine+`referer_blocklist: - 192.0.2.7 - "2001:db8::7" `) if err != nil { t.Fatalf("IP address entries should load, got error: %v", err) } want := []string{"192.0.2.7", "2001:db8::7"} if !slices.Equal(c.RefererBlocklist, want) { t.Errorf("RefererBlocklist = %v, want %v", c.RefererBlocklist, want) } } // TestRefererBlocklistAcceptsUnderscore checks that a host name with an // underscore, which a page can be served from, is accepted as an entry. func TestRefererBlocklistAcceptsUnderscore(t *testing.T) { t.Parallel() c, err := configFromYAML(t, signingKeyLine+`referer_blocklist: - my_site.leech.example - .my_site.hotlinker.example `) if err != nil { t.Fatalf("host names with an underscore should load, got error: %v", err) } want := []string{"my_site.leech.example", ".my_site.hotlinker.example"} if !slices.Equal(c.RefererBlocklist, want) { t.Errorf("RefererBlocklist = %v, want %v", c.RefererBlocklist, want) } } // TestRefererBlocklistOmittedIsEmpty checks that an omitted key blocks no // referer. func TestRefererBlocklistOmittedIsEmpty(t *testing.T) { t.Parallel() c, err := configFromYAML(t, signingKeyLine) if err != nil { t.Fatalf("minimal config should be valid, got error: %v", err) } if len(c.RefererBlocklist) != 0 { t.Errorf("RefererBlocklist = %v, want empty", c.RefererBlocklist) } } // TestRefererBlocklistInvalidAbortsStartup checks that an entry that is not a // host, or a value that is not a list of them, aborts startup with an error // naming the key and the entry. func TestRefererBlocklistInvalidAbortsStartup(t *testing.T) { t.Parallel() runAbortCases(t, []abortCase{ { name: "entry with a scheme", yaml: signingKeyLine + "referer_blocklist:\n - https://leech.example\n", wantErrSubstrings: []string{ keyRefererBlocklist, "https://leech.example", }, }, { name: "entry with a path", yaml: signingKeyLine + "referer_blocklist:\n - leech.example/page\n", wantErrSubstrings: []string{ keyRefererBlocklist, "leech.example/page", }, }, { name: "wildcard entry", yaml: signingKeyLine + "referer_blocklist:\n - \"*.leech.example\"\n", wantErrSubstrings: []string{ keyRefererBlocklist, "*.leech.example", }, }, { name: "entry with a port", yaml: signingKeyLine + "referer_blocklist:\n - leech.example:8080\n", wantErrSubstrings: []string{ keyRefererBlocklist, "leech.example:8080", }, }, { name: "two leading dots", yaml: signingKeyLine + "referer_blocklist:\n - ..leech.example\n", wantErrSubstrings: []string{ keyRefererBlocklist, "..leech.example", }, }, { name: "dot only", yaml: signingKeyLine + "referer_blocklist:\n - \".\"\n", wantErrSubstrings: []string{keyRefererBlocklist, `"."`}, }, { name: "empty entry", yaml: signingKeyLine + "referer_blocklist:\n - \"\"\n", wantErrSubstrings: []string{keyRefererBlocklist}, }, { name: "entry not a string", yaml: signingKeyLine + "referer_blocklist:\n - 42\n", wantErrSubstrings: []string{keyRefererBlocklist, "42"}, }, { name: "null value", yaml: signingKeyLine + "referer_blocklist:\n", wantErrSubstrings: []string{keyRefererBlocklist, nullValueText}, }, }) } // TestRefererBlocklistFromEnvironment checks that PIXA_REFERER_BLOCKLIST // takes comma-separated entries, and that an entry in it that is not a host // aborts startup naming the variable and the entry. func TestRefererBlocklistFromEnvironment(t *testing.T) { t.Setenv("PIXA_SIGNING_KEY", validTestSigningKey) t.Setenv("PIXA_REFERER_BLOCKLIST", " leech.example , .hotlinker.example ") c, err := newFromSmartConfig(nil) if err != nil { t.Fatalf("valid PIXA_REFERER_BLOCKLIST should load, got error: %v", err) } want := []string{"leech.example", ".hotlinker.example"} if !slices.Equal(c.RefererBlocklist, want) { t.Errorf("RefererBlocklist = %v, want %v", c.RefererBlocklist, want) } t.Setenv("PIXA_REFERER_BLOCKLIST", "leech.example,https://hotlinker.example") _, err = newFromSmartConfig(nil) wantStartupError(t, err, "PIXA_REFERER_BLOCKLIST", "https://hotlinker.example") }