diff --git a/checks_test.go b/checks_test.go index debe4ee..3607693 100644 --- a/checks_test.go +++ b/checks_test.go @@ -28,9 +28,9 @@ func TestTCPDialCheck(t *testing.T) { } func TestHTTPGetCheck(t *testing.T) { - assert.NoError(t, HTTPGetCheck("https://heptio.com", 5*time.Second)()) - assert.Error(t, HTTPGetCheck("http://heptio.com", 5*time.Second)(), "redirect should fail") - assert.Error(t, HTTPGetCheck("https://heptio.com/nonexistent", 5*time.Second)(), "404 should fail") + assert.NoError(t, HTTPGetCheck("https://heptio.cloud.vmware.com", 5*time.Second)()) + assert.Error(t, HTTPGetCheck("http://heptio.cloud.vmware.com", 5*time.Second)(), "redirect should fail") + assert.Error(t, HTTPGetCheck("https://heptio.cloud.vmware.com/nonexistent", 5*time.Second)(), "404 should fail") } func TestDatabasePingCheck(t *testing.T) { diff --git a/handler.go b/handler.go index 6ea9740..e8cd67a 100644 --- a/handler.go +++ b/handler.go @@ -73,7 +73,8 @@ func (s *basicHandler) collectChecks(checks map[string]Check, resultsOut map[str } func (s *basicHandler) handle(w http.ResponseWriter, r *http.Request, checks ...map[string]Check) { - if r.Method != http.MethodGet { + + if r.Method != http.MethodGet && r.Method != http.MethodHead { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } @@ -88,6 +89,10 @@ func (s *basicHandler) handle(w http.ResponseWriter, r *http.Request, checks ... w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(status) + if r.Method == http.MethodHead { + return + } + // unless ?full=1, return an empty body. Kubernetes only cares about the // HTTP status code, so we won't waste bytes on the full body. if r.URL.Query().Get("full") != "1" { diff --git a/handler_test.go b/handler_test.go index 2e894b4..2e158d2 100644 --- a/handler_test.go +++ b/handler_test.go @@ -120,6 +120,42 @@ func TestNewHandler(t *testing.T) { expect: http.StatusServiceUnavailable, expectBody: "{}\n", }, + { + name: "HEAD with no checks, /live should succeed", + method: "HEAD", + path: "/live", + live: true, + ready: true, + expect: http.StatusOK, + expectBody: "", + }, + { + name: "HEAD with no checks, /ready should succeed", + method: "HEAD", + path: "/ready", + live: true, + ready: true, + expect: http.StatusOK, + expectBody: "", + }, + { + name: "HEAD with a failing liveness check, /live should fail", + method: "HEAD", + path: "/live", + live: false, + ready: true, + expect: http.StatusServiceUnavailable, + expectBody: "", + }, + { + name: "HEAD with a failing liveness check, /ready should fail", + method: "HEAD", + path: "/ready", + live: false, + ready: true, + expect: http.StatusServiceUnavailable, + expectBody: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {