func New(config ...Config) fiber.Handler {
	cfg := configDefault(config...)
	manager := newManager(cfg.Storage)
	dummyValue := []byte{'+'}
	return func(c *fiber.Ctx) (err error) {
		if cfg.Next != nil && cfg.Next(c) {
			return c.Next()
		}
		var token string
		switch c.Method() {
		case fiber.MethodGet, fiber.MethodHead, fiber.MethodOptions, fiber.MethodTrace:
			token = c.Cookies(cfg.CookieName)
		default:
			token, err = cfg.extractor(c)
			if err != nil {
				return cfg.ErrorHandler(c, err)
			}
			if manager.getRaw(token) == nil {
				c.Cookie(&fiber.Cookie{
					Name:     cfg.CookieName,
					Domain:   cfg.CookieDomain,
					Path:     cfg.CookiePath,
					Expires:  time.Now().Add(-1 * time.Minute),
					Secure:   cfg.CookieSecure,
					HTTPOnly: cfg.CookieHTTPOnly,
					SameSite: cfg.CookieSameSite,
				})
				return cfg.ErrorHandler(c, err)
			}
		}
		if token == "" {
			token = cfg.KeyGenerator()
		}
		manager.setRaw(token, dummyValue, cfg.Expiration)
		cookie := &fiber.Cookie{
			Name:     cfg.CookieName,
			Value:    token,
			Domain:   cfg.CookieDomain,
			Path:     cfg.CookiePath,
			Expires:  time.Now().Add(cfg.Expiration),
			Secure:   cfg.CookieSecure,
			HTTPOnly: cfg.CookieHTTPOnly,
			SameSite: cfg.CookieSameSite,
		}
		c.Cookie(cookie)
		c.Vary(fiber.HeaderCookie)
		if cfg.ContextKey != "" {
			c.Locals(cfg.ContextKey, token)
		}
		return c.Next()
	}
}
New creates a new middleware handler
package csrf
import (
	"time"
	"github.com/gofiber/fiber/v2"
)