github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/plugin/cb/middleware.go (about)

     1  package cb
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net/http"
     7  
     8  	"github.com/Knetic/govaluate"
     9  	"github.com/afex/hystrix-go/hystrix"
    10  	"github.com/felixge/httpsnoop"
    11  	log "github.com/sirupsen/logrus"
    12  
    13  	janusErr "github.com/hellofresh/janus/pkg/errors"
    14  )
    15  
    16  const (
    17  	defaultPredicate = "statusCode == 0 || statusCode >= 500"
    18  )
    19  
    20  // NewCBMiddleware creates a new cb middleware
    21  func NewCBMiddleware(cfg Config) func(http.Handler) http.Handler {
    22  	return func(handler http.Handler) http.Handler {
    23  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    24  			logger := log.WithFields(log.Fields{
    25  				"name":                    cfg.Name,
    26  				"timeout":                 cfg.Timeout,
    27  				"max_concurrent_requests": cfg.MaxConcurrentRequests,
    28  				"error_percent_threshold": cfg.ErrorPercentThreshold,
    29  			})
    30  
    31  			logger.Debug("Starting cb middleware")
    32  			if cfg.Predicate == "" {
    33  				cfg.Predicate = defaultPredicate
    34  			}
    35  
    36  			expression, err := govaluate.NewEvaluableExpression(cfg.Predicate)
    37  			if err != nil {
    38  				log.WithError(err).Error("could not create an expression with this predicate")
    39  				handler.ServeHTTP(w, r)
    40  				return
    41  			}
    42  
    43  			err = hystrix.Do(cfg.Name, func() error {
    44  				m := httpsnoop.CaptureMetrics(handler, w, r)
    45  				params := make(map[string]interface{}, 8)
    46  				params["statusCode"] = m.Code
    47  				params["request"] = r
    48  
    49  				result, err := expression.Evaluate(params)
    50  				if err != nil {
    51  					return errors.New("cannot evaluate the expression")
    52  				}
    53  
    54  				if result.(bool) {
    55  					return fmt.Errorf("%s %s request failed", r.Method, r.URL)
    56  				}
    57  
    58  				return nil
    59  			}, nil)
    60  
    61  			if err != nil {
    62  				logger.WithError(err).Error("Request failed on the cb middleware")
    63  				janusErr.Handler(w, r, fmt.Errorf("request failed: %w", err))
    64  			}
    65  		})
    66  	}
    67  }