Skip to content

Commit

Permalink
simpler http handler tests
Browse files Browse the repository at this point in the history
  • Loading branch information
metachris committed Sep 25, 2024
1 parent f76a268 commit 588712d
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 42 deletions.
24 changes: 12 additions & 12 deletions httpserver/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/flashbots/go-template/metrics"
)

func (s *Server) handleAPI(w http.ResponseWriter, r *http.Request) {
m := s.metricsSrv.Float64Histogram(
func (srv *Server) handleAPI(w http.ResponseWriter, r *http.Request) {
m := srv.metricsSrv.Float64Histogram(
"request_duration_api",
"API request handling duration",
metrics.UomMicroseconds,
Expand All @@ -23,32 +23,32 @@ func (s *Server) handleAPI(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}

func (s *Server) handleLivenessCheck(w http.ResponseWriter, r *http.Request) {
func (srv *Server) handleLivenessCheck(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}

func (s *Server) handleReadinessCheck(w http.ResponseWriter, r *http.Request) {
if !s.isReady.Load() {
func (srv *Server) handleReadinessCheck(w http.ResponseWriter, r *http.Request) {
if !srv.isReady.Load() {
w.WriteHeader(http.StatusServiceUnavailable)
return
}

w.WriteHeader(http.StatusOK)
}

func (s *Server) handleDrain(w http.ResponseWriter, r *http.Request) {
if wasReady := s.isReady.Swap(false); !wasReady {
func (srv *Server) handleDrain(w http.ResponseWriter, r *http.Request) {
if wasReady := srv.isReady.Swap(false); !wasReady {
return
}
// l := logutils.ZapFromRequest(r)
s.log.Info("Server marked as not ready")
time.Sleep(s.cfg.DrainDuration) // Give LB enough time to detect us not ready
srv.log.Info("Server marked as not ready")
time.Sleep(srv.cfg.DrainDuration) // Give LB enough time to detect us not ready
}

func (s *Server) handleUndrain(w http.ResponseWriter, r *http.Request) {
if wasReady := s.isReady.Swap(true); wasReady {
func (srv *Server) handleUndrain(w http.ResponseWriter, r *http.Request) {
if wasReady := srv.isReady.Swap(true); wasReady {
return
}
// l := logutils.ZapFromRequest(r)
s.log.Info("Server marked as ready")
srv.log.Info("Server marked as ready")
}
18 changes: 18 additions & 0 deletions httpserver/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,21 @@ func Test_Handlers_Healthcheck_Drain_Undrain(t *testing.T) {
require.Equal(t, http.StatusOK, resp.StatusCode, "Healthcheck must return `Ok` after undraining")
}
}

func Test_Handlers_Simple(t *testing.T) {
// This test doesn't need the server to actually start and serve. Instead it just tests the handlers.
//nolint: exhaustruct
srv, err := New(&HTTPServerConfig{
Log: getTestLogger(),
})
require.NoError(t, err)

{ // Check health
req, err := http.NewRequest(http.MethodGet, "/readyz", nil) //nolint:goconst,nolintlint
require.NoError(t, err)

rr := httptest.NewRecorder()
srv.getRouter().ServeHTTP(rr, req)
require.Equal(t, http.StatusOK, rr.Code)
}
}
63 changes: 33 additions & 30 deletions httpserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,72 +50,75 @@ func New(cfg *HTTPServerConfig) (srv *Server, err error) {
}
srv.isReady.Swap(true)

srv.srv = &http.Server{
Addr: cfg.ListenAddr,
Handler: srv.getRouter(),
ReadTimeout: cfg.ReadTimeout,
WriteTimeout: cfg.WriteTimeout,
}

return srv, nil
}

func (srv *Server) getRouter() http.Handler {
mux := chi.NewRouter()
mux.With(srv.httpLogger).Get("/api", srv.handleAPI) // Never serve at `/` (root) path
mux.With(srv.httpLogger).Get("/livez", srv.handleLivenessCheck)
mux.With(srv.httpLogger).Get("/readyz", srv.handleReadinessCheck)
mux.With(srv.httpLogger).Get("/drain", srv.handleDrain)
mux.With(srv.httpLogger).Get("/undrain", srv.handleUndrain)

if cfg.EnablePprof {
if srv.cfg.EnablePprof {
srv.log.Info("pprof API enabled")
mux.Mount("/debug", middleware.Profiler())
}

srv.srv = &http.Server{
Addr: cfg.ListenAddr,
Handler: mux,
ReadTimeout: cfg.ReadTimeout,
WriteTimeout: cfg.WriteTimeout,
}

return srv, nil
return mux
}

func (s *Server) httpLogger(next http.Handler) http.Handler {
return httplogger.LoggingMiddlewareSlog(s.log, next)
func (srv *Server) httpLogger(next http.Handler) http.Handler {
return httplogger.LoggingMiddlewareSlog(srv.log, next)
}

func (s *Server) RunInBackground() {
func (srv *Server) RunInBackground() {
// metrics
if s.cfg.MetricsAddr != "" {
if srv.cfg.MetricsAddr != "" {
go func() {
s.log.With("metricsAddress", s.cfg.MetricsAddr).Info("Starting metrics server")
err := s.metricsSrv.ListenAndServe()
srv.log.With("metricsAddress", srv.cfg.MetricsAddr).Info("Starting metrics server")
err := srv.metricsSrv.ListenAndServe()
if err != nil && !errors.Is(err, http.ErrServerClosed) {
s.log.Error("HTTP server failed", "err", err)
srv.log.Error("HTTP server failed", "err", err)
}
}()
}

// api
go func() {
s.log.Info("Starting HTTP server", "listenAddress", s.cfg.ListenAddr)
if err := s.srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
s.log.Error("HTTP server failed", "err", err)
srv.log.Info("Starting HTTP server", "listenAddress", srv.cfg.ListenAddr)
if err := srv.srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
srv.log.Error("HTTP server failed", "err", err)
}
}()
}

func (s *Server) Shutdown() {
func (srv *Server) Shutdown() {
// api
ctx, cancel := context.WithTimeout(context.Background(), s.cfg.GracefulShutdownDuration)
ctx, cancel := context.WithTimeout(context.Background(), srv.cfg.GracefulShutdownDuration)
defer cancel()
if err := s.srv.Shutdown(ctx); err != nil {
s.log.Error("Graceful HTTP server shutdown failed", "err", err)
if err := srv.srv.Shutdown(ctx); err != nil {
srv.log.Error("Graceful HTTP server shutdown failed", "err", err)
} else {
s.log.Info("HTTP server gracefully stopped")
srv.log.Info("HTTP server gracefully stopped")
}

// metrics
if len(s.cfg.MetricsAddr) != 0 {
ctx, cancel := context.WithTimeout(context.Background(), s.cfg.GracefulShutdownDuration)
if len(srv.cfg.MetricsAddr) != 0 {
ctx, cancel := context.WithTimeout(context.Background(), srv.cfg.GracefulShutdownDuration)
defer cancel()

if err := s.metricsSrv.Shutdown(ctx); err != nil {
s.log.Error("Graceful metrics server shutdown failed", "err", err)
if err := srv.metricsSrv.Shutdown(ctx); err != nil {
srv.log.Error("Graceful metrics server shutdown failed", "err", err)
} else {
s.log.Info("Metrics server gracefully stopped")
srv.log.Info("Metrics server gracefully stopped")
}
}
}

0 comments on commit 588712d

Please sign in to comment.