github.com/MetalBlockchain/metalgo@v1.11.9/api/health/handler.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package health 5 6 import ( 7 "encoding/json" 8 "net/http" 9 10 "github.com/gorilla/rpc/v2" 11 12 "github.com/MetalBlockchain/metalgo/utils/logging" 13 14 avajson "github.com/MetalBlockchain/metalgo/utils/json" 15 ) 16 17 // NewGetAndPostHandler returns a health handler that supports GET and jsonrpc 18 // POST requests. 19 func NewGetAndPostHandler(log logging.Logger, reporter Reporter) (http.Handler, error) { 20 newServer := rpc.NewServer() 21 codec := avajson.NewCodec() 22 newServer.RegisterCodec(codec, "application/json") 23 newServer.RegisterCodec(codec, "application/json;charset=UTF-8") 24 25 getHandler := NewGetHandler(reporter.Health) 26 27 // If a GET request is sent, we respond with a 200 if the node is healthy or 28 // a 503 if the node isn't healthy. 29 handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 if r.Method != http.MethodGet { 31 newServer.ServeHTTP(w, r) 32 return 33 } 34 35 getHandler.ServeHTTP(w, r) 36 }) 37 38 err := newServer.RegisterService( 39 &Service{ 40 log: log, 41 health: reporter, 42 }, 43 "health", 44 ) 45 return handler, err 46 } 47 48 // NewGetHandler return a health handler that supports GET requests reporting 49 // the result of the provided [reporter]. 50 func NewGetHandler(reporter func(tags ...string) (map[string]Result, bool)) http.Handler { 51 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 52 // Make sure the content type is set before writing the header. 53 w.Header().Set("Content-Type", "application/json") 54 55 tags := r.URL.Query()["tag"] 56 checks, healthy := reporter(tags...) 57 if !healthy { 58 // If a health check has failed, we should return a 503. 59 w.WriteHeader(http.StatusServiceUnavailable) 60 } 61 // The encoder will call write on the writer, which will write the 62 // header with a 200. 63 _ = json.NewEncoder(w).Encode(APIReply{ 64 Checks: checks, 65 Healthy: healthy, 66 }) 67 }) 68 }