func (f *Flagr) Cleanup() error {
	return nil
}
Cleanup cleans up the resources made by rl during provisioning.
package flagr
import (
	"context"
	"fmt"
	"net/http"
	"regexp"
	"strings"
	"time"
	"github.com/caddyserver/caddy/v2"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
	"github.com/checkr/flagr/swagger_gen/models"
	"go.uber.org/zap"
	"github.com/RussellLuo/caddy-ext/flagr/evaluator"
)
var (
	regexpFullVar  = regexp.MustCompile(`^\{http\.request\..+\}$`)
	regexpShortVar = regexp.MustCompile(`^\{(\w+)\.(.+)\}$`)
)
func init() {
	caddy.RegisterModule(Flagr{})
}
type Evaluator interface {
	PostEvaluationBatch(ctx context.Context, req *models.EvaluationBatchRequest) (*models.EvaluationBatchResponse, error)
}
type ContextValue struct {
	Value      interface{}
	IsCaddyVar bool
	Converters []Converter `json:"-"`
}
type Flagr struct {
	URL string `json:"url,omitempty"`
	Evaluator string `json:"evaluator,omitempty"`
	RefreshInterval string `json:"refresh_interval,omitempty"`
	EntityID string `json:"entity_id,omitempty"`
	EntityContext map[string]interface{} `json:"entity_context,omitempty"`
	FlagKeys []string `json:"flag_keys,omitempty"`
	BindVariantKeysTo string `json:"bind_variant_keys_to,omitempty"`
	logger         *zap.Logger
	evaluator      Evaluator
	entityIDVar    string
	entityContext  map[string]ContextValue
	bindToLocation string
	bindToName     string
}
func (Flagr) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "http.handlers.flagr",
		New: func() caddy.Module { return new(Flagr) },  
	}
}
func (f *Flagr) Provision(ctx caddy.Context) (err error) {
	f.logger = ctx.Logger(f)
	return f.provision()
}
func (f *Flagr) provision() (err error) {
	if f.URL == "" {
		return fmt.Errorf("empty url")
	}
	refreshInterval := 10 * time.Second
	if f.RefreshInterval != "" {
		d, err := time.ParseDuration(f.RefreshInterval)
		if err != nil {
			return err
		}
		refreshInterval = d
	}
	if f.Evaluator == "" {
		f.Evaluator = "local"
	}
	switch f.Evaluator {
	case "local":
		f.evaluator, err = evaluator.NewLocal(refreshInterval, f.URL)
		if err != nil {
			return err
		}
	case "remote":
		f.evaluator = evaluator.NewRemote(f.URL)
	default:
		return fmt.Errorf("unsupported evaluator %q", f.Evaluator)
	}
	if f.EntityID != "" {
		f.entityIDVar, err = parseVar(f.EntityID)
		if err != nil {
			return err
		}
	}
	f.entityContext = make(map[string]ContextValue)
	for k, v := range f.EntityContext {
		cv := ContextValue{Value: v}
		if s, ok := v.(string); ok {
			parts := strings.Split(s, "|")
			val := parts[0]
			if p, err := parseVar(val); err == nil {
				cv.Value = p
				cv.IsCaddyVar = true
			} else {
				cv.Value = val
			}
			for _, name := range parts[1:] {
				c, err := GetConverter(name)
				if err != nil {
					return err
				}
				cv.Converters = append(cv.Converters, c)
			}
		}
		f.entityContext[k] = cv
	}
	if f.BindVariantKeysTo == "" {
		f.BindVariantKeysTo = "header.X-Flagr-Variant"
	}
	parts := strings.SplitN(f.BindVariantKeysTo, ".", 2)
	if len(parts) != 2 {
		return fmt.Errorf("invalid bind_variant_key_to")
	}
	f.bindToLocation, f.bindToName = parts[0], parts[1]
	return nil
}