func keyFromParam(param string) func(c *fiber.Ctx) (string, error) {
	return func(c *fiber.Ctx) (string, error) {
		key := c.Params(param)
		if key == "" {
			return "", errMissingOrMalformedAPIKey
		}
		return key, nil
	}
}
keyFromParam returns a function that extracts api key from the url param string.
package keyauth
import (
	"errors"
	"strings"
	"github.com/gofiber/fiber/v2"
)
var (
	errMissingOrMalformedAPIKey = errors.New("Missing or malformed API Key")
)
type Config struct {
	Filter func(*fiber.Ctx) bool
	SuccessHandler fiber.Handler
	ErrorHandler fiber.ErrorHandler
	KeyLookup string
	AuthScheme string
	Validator func(*fiber.Ctx, string) (bool, error)
	ContextKey string
	keyExtractor func(*fiber.Ctx) (string, error)
}
func New(config ...Config) fiber.Handler {
	var cfg Config
	if len(config) > 0 {
		cfg = config[0]
	}
	if cfg.SuccessHandler == nil {
		cfg.SuccessHandler = func(c *fiber.Ctx) error {
			return c.Next()
		}
	}
	if cfg.ErrorHandler == nil {
		cfg.ErrorHandler = func(c *fiber.Ctx, err error) error {
			if err == errMissingOrMalformedAPIKey {
				return c.Status(fiber.StatusBadRequest).SendString(err.Error())
			}
			return c.Status(fiber.StatusUnauthorized).SendString("Invalid or expired API Key")
		}
	}
	if cfg.KeyLookup == "" {
		cfg.KeyLookup = "header:" + fiber.HeaderAuthorization
		if cfg.AuthScheme == "" {
			cfg.AuthScheme = "Bearer"
		}
	}
	if cfg.Validator == nil {
		cfg.Validator = func(c *fiber.Ctx, t string) (bool, error) {
			return true, nil
		}
	}
	if cfg.ContextKey == "" {
		cfg.ContextKey = "token"
	}
	parts := strings.Split(cfg.KeyLookup, ":")
	extractor := keyFromHeader(parts[1], cfg.AuthScheme)
	switch parts[0] {
	case "query":
		extractor = keyFromQuery(parts[1])
	case "form":
		extractor = keyFromForm(parts[1])
	case "param":
		extractor = keyFromParam(parts[1])
	case "cookie":
		extractor = keyFromCookie(parts[1])
	}
	return func(c *fiber.Ctx) error {
		if cfg.Filter != nil && cfg.Filter(c) {
			return c.Next()
		}
		key, err := extractor(c)
		if err != nil {
			return cfg.ErrorHandler(c, err)
		}
		valid, err := cfg.Validator(c, key)
		if err == nil && valid {
			c.Locals(cfg.ContextKey, key)
			return cfg.SuccessHandler(c)
		}
		return cfg.ErrorHandler(c, err)
	}
}
func keyFromHeader(header string, authScheme string) func(c *fiber.Ctx) (string, error) {
	return func(c *fiber.Ctx) (string, error) {
		auth := c.Get(header)
		l := len(authScheme)
		if l == 0 {
			return auth, nil
		}
		if len(auth) > l+1 && auth[:l] == authScheme {
			return auth[l+1:], nil
		}
		return "", errMissingOrMalformedAPIKey
	}
}
func keyFromQuery(param string) func(c *fiber.Ctx) (string, error) {
	return func(c *fiber.Ctx) (string, error) {
		key := c.Query(param)
		if key == "" {
			return "", errMissingOrMalformedAPIKey
		}
		return key, nil
	}
}
func keyFromForm(param string) func(c *fiber.Ctx) (string, error) {
	return func(c *fiber.Ctx) (string, error) {
		key := c.FormValue(param)
		if key == "" {
			return "", errMissingOrMalformedAPIKey
		}
		return key, nil
	}
}