diff --git a/caddyhttp/basicauth/basicauth.go b/caddyhttp/basicauth/basicauth.go index 0496c3e16..59c65418c 100644 --- a/caddyhttp/basicauth/basicauth.go +++ b/caddyhttp/basicauth/basicauth.go @@ -52,6 +52,12 @@ func (a BasicAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error var protected, isAuthenticated bool var realm string + // do not check for basic auth on OPTIONS call + if r.Method == http.MethodOptions { + // Pass-through when no paths match + return a.Next.ServeHTTP(w, r) + } + for _, rule := range a.Rules { for _, res := range rule.Resources { if !httpserver.Path(r.URL.Path).Matches(res) { diff --git a/caddyhttp/basicauth/basicauth_test.go b/caddyhttp/basicauth/basicauth_test.go index 71255f763..1182b5226 100644 --- a/caddyhttp/basicauth/basicauth_test.go +++ b/caddyhttp/basicauth/basicauth_test.go @@ -194,3 +194,30 @@ md5:$apr1$l42y8rex$pOA2VJ0x/0TwaFeAF9nX61` } } } + +func TestOptionsMethod(t *testing.T) { + rw := BasicAuth{ + Next: httpserver.HandlerFunc(contentHandler), + Rules: []Rule{ + {Username: "username", Password: PlainMatcher("password"), Resources: []string{"/testing"}}, + }, + } + + req, err := http.NewRequest(http.MethodOptions, "/testing", nil) + if err != nil { + t.Fatalf("Could not create HTTP request: %v", err) + } + + // add basic auth with invalid username + // and password to make sure basic auth is ignored + req.SetBasicAuth("invaliduser", "invalidpassword") + + rec := httptest.NewRecorder() + result, err := rw.ServeHTTP(rec, req) + if err != nil { + t.Fatalf("Could not ServeHTTP: %v", err) + } + if result != http.StatusOK { + t.Errorf("Expected status code %d but was %d", http.StatusOK, result) + } +}