...

Source file src/github.com/emissary-ingress/emissary/v3/cmd/kat-server/services/health_check_server.go

Documentation: github.com/emissary-ingress/emissary/v3/cmd/kat-server/services

     1  package services
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"time"
     9  
    10  	"github.com/datawire/dlib/dgroup"
    11  	"github.com/datawire/dlib/dhttp"
    12  	"github.com/datawire/dlib/dlog"
    13  )
    14  
    15  // HTTP server object (all fields are required).
    16  type HealthCheckServer struct {
    17  	Port                int16
    18  	Backend             string
    19  	SecurePort          int16
    20  	SecureBackend       string
    21  	Cert                string
    22  	Key                 string
    23  	TLSVersion          string
    24  	Healthy             bool
    25  	HealthyStatusCode   int
    26  	UnhealthyStatusCode int
    27  }
    28  
    29  // Start initializes the Health Check HTTP server.
    30  func (h *HealthCheckServer) Start(ctx context.Context) <-chan bool {
    31  	dlog.Printf(ctx, "HTTP: %s listening on %d/%d", h.Backend, h.Port, h.SecurePort)
    32  
    33  	h.Healthy = true
    34  	mux := http.NewServeMux()
    35  	mux.HandleFunc("/", h.handler)
    36  
    37  	sc := &dhttp.ServerConfig{
    38  		Handler: mux,
    39  	}
    40  
    41  	g := dgroup.NewGroup(ctx, dgroup.GroupConfig{})
    42  	g.Go("cleartext", func(ctx context.Context) error {
    43  		return sc.ListenAndServe(ctx, fmt.Sprintf(":%v", h.Port))
    44  	})
    45  	g.Go("tls", func(ctx context.Context) error {
    46  		return sc.ListenAndServeTLS(ctx, fmt.Sprintf(":%v", h.SecurePort), h.Cert, h.Key)
    47  	})
    48  
    49  	exited := make(chan bool)
    50  	go func() {
    51  		if err := g.Wait(); err != nil {
    52  			dlog.Error(ctx, err)
    53  			panic(err) // TODO: do something better
    54  		}
    55  		close(exited)
    56  	}()
    57  	return exited
    58  }
    59  
    60  func (h *HealthCheckServer) handler(w http.ResponseWriter, r *http.Request) {
    61  	ctx := r.Context()
    62  	// Assume we're the clear side of the world.
    63  	backend := h.Backend
    64  	conntype := "CLR"
    65  
    66  	var request = make(map[string]interface{})
    67  	var url = make(map[string]interface{})
    68  	request["url"] = url
    69  	url["fragment"] = r.URL.Fragment
    70  	url["host"] = r.URL.Host
    71  	url["opaque"] = r.URL.Opaque
    72  	url["path"] = r.URL.Path
    73  	url["query"] = r.URL.Query()
    74  	url["rawQuery"] = r.URL.RawQuery
    75  	url["scheme"] = r.URL.Scheme
    76  	if r.URL.User != nil {
    77  		url["username"] = r.URL.User.Username()
    78  		pw, ok := r.URL.User.Password()
    79  		if ok {
    80  			url["password"] = pw
    81  		}
    82  	}
    83  	request["method"] = r.Method
    84  	request["headers"] = lower(r.Header)
    85  	request["host"] = r.Host
    86  
    87  	var tlsrequest = make(map[string]interface{})
    88  	request["tls"] = tlsrequest
    89  
    90  	tlsrequest["enabled"] = r.TLS != nil
    91  
    92  	if r.TLS != nil {
    93  		// We're the secure side of the world, I guess.
    94  		backend = h.SecureBackend
    95  		conntype = "TLS"
    96  
    97  		tlsrequest["negotiated-protocol"] = r.TLS.NegotiatedProtocol
    98  		tlsrequest["server-name"] = r.TLS.ServerName
    99  		tlsrequest["negotiated-protocol-version"] = getTLSVersion(r.TLS)
   100  	}
   101  
   102  	// Set date response header.
   103  	w.Header().Set("Date", time.Now().Format(time.RFC1123))
   104  
   105  	statusCode := h.HealthyStatusCode
   106  	if !h.Healthy {
   107  		statusCode = h.UnhealthyStatusCode
   108  	}
   109  
   110  	fmt.Println(r.URL.Path)
   111  	// A request to this path will make the health check server respond with
   112  	// only the UnhealthyStatusCode to all subsequent requests
   113  	if r.URL.Path == "/makeUnhealthy/" {
   114  		h.Healthy = false
   115  	}
   116  
   117  	w.WriteHeader(statusCode)
   118  
   119  	// Write out all request/response information
   120  	var response = make(map[string]interface{})
   121  	response["headers"] = lower(w.Header())
   122  
   123  	var body = make(map[string]interface{})
   124  	body["backend"] = backend
   125  	body["request"] = request
   126  	body["response"] = response
   127  
   128  	b, err := json.MarshalIndent(body, "", "  ")
   129  	if err != nil {
   130  		b = []byte(fmt.Sprintf("Error: %v", err))
   131  	}
   132  
   133  	dlog.Printf(ctx, "%s (%s): \"%s %s\" -> HTTP %v", r.Method, r.URL.Path, backend, conntype, statusCode)
   134  	_, _ = w.Write(b)
   135  }
   136  

View as plain text