Skip to content

Commit 634c476

Browse files
authored
Support substring exempt user agents (#91)
1 parent 4da7966 commit 634c476

3 files changed

Lines changed: 8 additions & 7 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ services:
9090
--providers.docker=true
9191
--providers.docker.network=default
9292
--experimental.plugins.captcha-protect.modulename=github.com/libops/captcha-protect
93-
--experimental.plugins.captcha-protect.version=v1.12.4
93+
--experimental.plugins.captcha-protect.version=v1.12.5
9494
volumes:
9595
- /var/run/docker.sock:/var/run/docker.sock:z
9696
- /CHANGEME/TO/A/HOST/PATH/FOR/STATE/FILE:/tmp/state.json:rw
@@ -130,7 +130,7 @@ services:
130130
| `protectFileExtensions` | `[]string` | `""` | Comma-separated file extensions to protect. By default, your protected routes only protect html files. This is to prevent files like CSS/JS/img from tripping the rate limit. |
131131
| `protectHttpMethods` | `[]string` | `"GET,HEAD"` | Comma-separated list of HTTP methods to protect against |
132132
| `exemptIps` | `[]string` | `privateIPs` | CIDR-formatted IPs that should never be challenged. Private IP ranges are always exempt. |
133-
| `exemptUserAgents` | `[]string` | `""` | Comma-separated list of case-insensitive user agent **prefixes** to never challenge. e.g. `exemptUserAgents: edge` would never challenge useragents like "Edge/12.4 ..." |
133+
| `exemptUserAgents` | `[]string` | `""` | Comma-separated list of case-insensitive user agent substrings to never challenge. For example, `exemptUserAgents: YandexBot` exempts user agents containing `YandexBot`. |
134134
| `challengeURL` | `string` | `"/challenge"` | URL where challenges are served. This will override existing routes if there is a conflict. Setting to blank will have the challenge presented on the same page that tripped the rate limit. |
135135
| `challengeTmpl` | `string` | `"./challenge.tmpl.html"`| Path to the Go HTML template for the captcha challenge page. |
136136
| `challengeStatusCode` | `int` | `200` | HTTP Response status code to return when serving a challenge |

main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -858,8 +858,8 @@ protected:
858858

859859
func (bc *CaptchaProtect) isGoodUserAgent(ua string) bool {
860860
ua = strings.ToLower(ua)
861-
for _, agentPrefix := range bc.config.ExemptUserAgents {
862-
if strings.HasPrefix(ua, agentPrefix) {
861+
for _, agentSubstring := range bc.config.ExemptUserAgents {
862+
if strings.Contains(ua, agentSubstring) {
863863
return true
864864
}
865865
}

main_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -615,10 +615,11 @@ func TestIsGoodUserAgent(t *testing.T) {
615615
ua string
616616
expected bool
617617
}{
618-
{"Matching first prefix", []string{"Mozilla", "Google"}, "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", true},
619-
{"Matching second prefix", []string{"Bing", "Edge"}, "Edge/12.0", true},
618+
{"Matching first substring", []string{"Mozilla", "Google"}, "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", true},
619+
{"Matching second substring", []string{"Bing", "Edge"}, "Edge/12.0", true},
620+
{"Matching substring within user agent", []string{"YandexBot"}, "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)", true},
620621
{"Case insensitive", []string{"bing", "Edge"}, "BING/12.0", true},
621-
{"No matching prefix", []string{"Mozilla", "Google"}, "Safari/537.36", false},
622+
{"No matching substring", []string{"Mozilla", "Google"}, "Safari/537.36", false},
622623
{"Empty user agent", []string{"Mozilla", "Google"}, "", false},
623624
{"Empty exempt list", []string{}, "Mozilla/5.0", false},
624625
}

0 commit comments

Comments
 (0)