github.com/cornelk/go-cloud@v0.17.1/server/health/health.go (about)

     1  // Copyright 2018 The Go Cloud Development Kit Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package health provides health check handlers.
    16  package health // import "github.com/cornelk/go-cloud/server/health"
    17  
    18  import (
    19  	"io"
    20  	"net/http"
    21  )
    22  
    23  // Handler is an HTTP handler that reports on the success of an
    24  // aggregate of Checkers.  The zero value is always healthy.
    25  type Handler struct {
    26  	checkers []Checker
    27  }
    28  
    29  // Add adds a new check to the handler.
    30  func (h *Handler) Add(c Checker) {
    31  	h.checkers = append(h.checkers, c)
    32  }
    33  
    34  // ServeHTTP returns 200 if it is healthy, 500 otherwise.
    35  func (h *Handler) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
    36  	for _, c := range h.checkers {
    37  		if err := c.CheckHealth(); err != nil {
    38  			writeUnhealthy(w)
    39  			return
    40  		}
    41  	}
    42  	writeHealthy(w)
    43  }
    44  
    45  func writeHeaders(statusLen string, w http.ResponseWriter) {
    46  	w.Header().Set("Content-Length", statusLen)
    47  	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
    48  	w.Header().Set("X-Content-Type-Options", "nosniff")
    49  }
    50  
    51  func writeUnhealthy(w http.ResponseWriter) {
    52  	const (
    53  		status    = "unhealthy"
    54  		statusLen = "9"
    55  	)
    56  
    57  	writeHeaders(statusLen, w)
    58  	w.WriteHeader(http.StatusInternalServerError)
    59  	io.WriteString(w, status)
    60  }
    61  
    62  // HandleLive is an http.HandlerFunc that handles liveness checks by
    63  // immediately responding with an HTTP 200 status.
    64  func HandleLive(w http.ResponseWriter, _ *http.Request) {
    65  	writeHealthy(w)
    66  }
    67  
    68  func writeHealthy(w http.ResponseWriter) {
    69  	const (
    70  		status    = "ok"
    71  		statusLen = "2"
    72  	)
    73  
    74  	writeHeaders(statusLen, w)
    75  	w.WriteHeader(http.StatusOK)
    76  	io.WriteString(w, status)
    77  }
    78  
    79  // Checker wraps the CheckHealth method.
    80  //
    81  // CheckHealth returns nil if the resource is healthy, or a non-nil
    82  // error if the resource is not healthy.  CheckHealth must be safe to
    83  // call from multiple goroutines.
    84  type Checker interface {
    85  	CheckHealth() error
    86  }
    87  
    88  // CheckerFunc is an adapter type to allow the use of ordinary functions as
    89  // health checks. If f is a function with the appropriate signature,
    90  // CheckerFunc(f) is a Checker that calls f.
    91  type CheckerFunc func() error
    92  
    93  // CheckHealth calls f().
    94  func (f CheckerFunc) CheckHealth() error {
    95  	return f()
    96  }