Skip to content
This repository has been archived by the owner on Mar 15, 2022. It is now read-only.

Commit

Permalink
Handler now accepts customizable routes for liveness and readiness
Browse files Browse the repository at this point in the history
Signed-off-by: Win Hung <win_hung86@hotmail.com>
  • Loading branch information
Win Hung Chan authored and winhung committed Oct 20, 2018
1 parent da5fdee commit f261fe5
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 13 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ See the [GoDoc examples](https://godoc.org/github.com/heptiolabs/healthcheck) fo
```go
health := healthcheck.NewHandler()
```
or
```go
liveURL := "/liveness"
readyURL := "/readiness"
health := healthcheck.NewHandlerCustomURL(liveURL, readyURL)
```

- Configure some application-specific liveness checks (whether the app itself is unhealthy):
```go
Expand Down
4 changes: 2 additions & 2 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,10 @@ func Example_metrics() {
adminMux.Handle("/metrics", promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))

// Expose a liveness check on /live
adminMux.HandleFunc("/live", health.LiveEndpoint)
adminMux.HandleFunc(oriLiveEndpoint, health.LiveEndpoint)

// Expose a readiness check on /ready
adminMux.HandleFunc("/ready", health.ReadyEndpoint)
adminMux.HandleFunc(oriReadyEndpoint, health.ReadyEndpoint)

// Make a request to the metrics endpoint and print the response.
fmt.Println(dumpRequest(adminMux, "GET", "/metrics"))
Expand Down
30 changes: 28 additions & 2 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ import (
"sync"
)

const (
oriLiveEndpoint = "/live"
oriReadyEndpoint = "/ready"
)

// basicHandler is a basic Handler implementation.
type basicHandler struct {
http.ServeMux
Expand All @@ -34,8 +39,29 @@ func NewHandler() Handler {
livenessChecks: make(map[string]Check),
readinessChecks: make(map[string]Check),
}
h.Handle("/live", http.HandlerFunc(h.LiveEndpoint))
h.Handle("/ready", http.HandlerFunc(h.ReadyEndpoint))

h.Handle(oriLiveEndpoint, http.HandlerFunc(h.LiveEndpoint))
h.Handle(oriReadyEndpoint, http.HandlerFunc(h.ReadyEndpoint))
return h
}

// NewHandlerCustomURL creates a new basic Handler with custom URL for liveness and readiness
func NewHandlerCustomURL(customLiveEndpoint, customReadyEndpoint string) Handler {
if customLiveEndpoint == "" {
customLiveEndpoint = oriLiveEndpoint
}

if customReadyEndpoint == "" {
customReadyEndpoint = oriReadyEndpoint
}

h := &basicHandler{
livenessChecks: make(map[string]Check),
readinessChecks: make(map[string]Check),
}

h.Handle(customLiveEndpoint, http.HandlerFunc(h.LiveEndpoint))
h.Handle(customReadyEndpoint, http.HandlerFunc(h.ReadyEndpoint))
return h
}

Expand Down
78 changes: 69 additions & 9 deletions handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ import (
"github.com/stretchr/testify/assert"
)

func checkEnpoint(t *testing.T, handler Handler, httpMethod, testPath, expectedBody string, expectedHTTPCode int) {
req, err := http.NewRequest(httpMethod, testPath, nil)
assert.NoError(t, err)

reqStr := httpMethod + " " + testPath
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
assert.Equal(t, expectedHTTPCode, rr.Code, "wrong code for %q", reqStr)

if expectedBody != "" {
assert.Equal(t, expectedBody, rr.Body.String(), "wrong body for %q", reqStr)
}
}

func TestNewHandler(t *testing.T) {
tests := []struct {
name string
Expand Down Expand Up @@ -137,17 +151,63 @@ func TestNewHandler(t *testing.T) {
})
}

req, err := http.NewRequest(tt.method, tt.path, nil)
assert.NoError(t, err)
checkEnpoint(t, h, tt.method, tt.path, tt.expectBody, tt.expect)
})
}
}

reqStr := tt.method + " " + tt.path
rr := httptest.NewRecorder()
h.ServeHTTP(rr, req)
assert.Equal(t, tt.expect, rr.Code, "wrong code for %q", reqStr)
func TestNewHandlerCustomURL(t *testing.T) {
liveEndpoint := "/liveness"
readyEndpoint := "/readiness"
emptyEndpoint := ""

if tt.expectBody != "" {
assert.Equal(t, tt.expectBody, rr.Body.String(), "wrong body for %q", reqStr)
}
tests := []struct {
name string
method string
customLiveEndpoint string
custoReadyEndpoint string
expectedLivenessPath string
expectedReadinessPath string
expect int
expectBody string
}{
{
name: "using only custom liveness endpoint, call to custom liveness endpoint and original readiness endpoint should succeed",
method: http.MethodGet,
customLiveEndpoint: liveEndpoint,
custoReadyEndpoint: emptyEndpoint,
expectedLivenessPath: liveEndpoint,
expectedReadinessPath: "/ready",
expect: http.StatusOK,
expectBody: "{}\n",
},
{
name: "using only custom readiness endpoint, call to custom readiness endpoint and original liveness endpoint should succeed",
method: http.MethodGet,
customLiveEndpoint: emptyEndpoint,
custoReadyEndpoint: readyEndpoint,
expectedLivenessPath: "/live",
expectedReadinessPath: readyEndpoint,
expect: http.StatusOK,
expectBody: "{}\n",
},
{
name: "with no custom liveness endpoints, the default hanlder should be called and hence original liveness and readiness endpoint should succeed",
method: http.MethodGet,
customLiveEndpoint: emptyEndpoint,
custoReadyEndpoint: emptyEndpoint,
expectedLivenessPath: "/live",
expectedReadinessPath: "/ready",
expect: http.StatusOK,
expectBody: "{}\n",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := NewHandlerCustomURL(tt.customLiveEndpoint, tt.custoReadyEndpoint)
checkEnpoint(t, h, tt.method, tt.expectedLivenessPath, tt.expectBody, tt.expect)
checkEnpoint(t, h, tt.method, tt.expectedReadinessPath, tt.expectBody, tt.expect)
})
}
}

0 comments on commit f261fe5

Please sign in to comment.