func (c *Ctx) ClearCookie(key ...string) {
	if len(key) > 0 {
		for i := range key {
			c.fasthttp.Response.Header.DelClientCookie(key[i])
		}
		return
	}
	c.fasthttp.Request.Header.VisitAllCookie(func(k, v []byte) {
		c.fasthttp.Response.Header.DelClientCookieBytes(k)
	})
}
ClearCookie expires a specific cookie by key on the client side.
If no key is provided it expires all cookies that came with the request.
package fiber
import (
	"bytes"
	"context"
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"mime/multipart"
	"net"
	"net/http"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"text/template"
	"time"
	"github.com/gofiber/fiber/v2/internal/bytebufferpool"
	"github.com/gofiber/fiber/v2/internal/go-json"
	"github.com/gofiber/fiber/v2/internal/schema"
	"github.com/gofiber/fiber/v2/utils"
	"github.com/valyala/fasthttp"
)
const maxParams = 30
const queryTag = "query"
const userContextKey = "__local_user_context__"
type Ctx struct {
	app                 *App                  
	route               *Route                
	indexRoute          int                   
	indexHandler        int                   
	method              string                
	methodINT           int                   
	baseURI             string                
	path                string                
	pathBuffer          []byte                
	detectionPath       string                
	detectionPathBuffer []byte                
	treePath            string                
	pathOriginal        string                
	values              [maxParams]string     
	fasthttp            *fasthttp.RequestCtx  
	matched             bool                  
}
type Range struct {
	Type   string
	Ranges []struct {
		Start int
		End   int
	}
}
type Cookie struct {
	Name     string    `json:"name"`
	Value    string    `json:"value"`
	Path     string    `json:"path"`
	Domain   string    `json:"domain"`
	MaxAge   int       `json:"max_age"`
	Expires  time.Time `json:"expires"`
	Secure   bool      `json:"secure"`
	HTTPOnly bool      `json:"http_only"`
	SameSite string    `json:"same_site"`
}
type Views interface {
	Load() error
	Render(io.Writer, string, interface{}, ...string) error
}
type ParserType struct {
	Customtype interface{}
	Converter  func(string) reflect.Value
}
type ParserConfig struct {
	IgnoreUnknownKeys bool
	SetAliasTag       string
	ParserType        []ParserType
	ZeroEmpty         bool
}
func (app *App) AcquireCtx(fctx *fasthttp.RequestCtx) *Ctx {
	c := app.pool.Get().(*Ctx)
	c.app = app
	c.indexRoute = -1
	c.indexHandler = 0
	c.matched = false
	c.pathOriginal = app.getString(fctx.URI().PathOriginal())
	c.method = app.getString(fctx.Request.Header.Method())
	c.methodINT = methodInt(c.method)
	c.fasthttp = fctx
	c.baseURI = ""
	c.configDependentPaths()
	return c
}
func (app *App) ReleaseCtx(c *Ctx) {
	c.route = nil
	c.fasthttp = nil
	app.pool.Put(c)
}
func (c *Ctx) Accepts(offers ...string) string {
	if len(offers) == 0 {
		return ""
	}
	header := c.Get(HeaderAccept)
	if header == "" {
		return offers[0]
	}
	spec, commaPos := "", 0
	for len(header) > 0 && commaPos != -1 {
		commaPos = strings.IndexByte(header, ',')
		if commaPos != -1 {
			spec = utils.Trim(header[:commaPos], ' ')
		} else {
			spec = utils.TrimLeft(header, ' ')
		}
		if factorSign := strings.IndexByte(spec, ';'); factorSign != -1 {
			spec = spec[:factorSign]
		}
		var mimetype string
		for _, offer := range offers {
			if len(offer) == 0 {
				continue
			} else if spec == "*/*" {
				return offer
			}
			if strings.IndexByte(offer, '/') != -1 {
				mimetype = offer  
			} else {
				mimetype = utils.GetMIME(offer)  
			}
			if spec == mimetype {
				return offer
			}
			s := strings.IndexByte(mimetype, '/')
			if strings.HasPrefix(spec, mimetype[:s]) && (spec[s:] == "/*" || mimetype[s:] == "/*") {
				return offer
			}
		}
		if commaPos != -1 {
			header = header[commaPos+1:]
		}
	}
	return ""
}
func (c *Ctx) AcceptsCharsets(offers ...string) string {
	return getOffer(c.Get(HeaderAcceptCharset), offers...)
}
func (c *Ctx) AcceptsEncodings(offers ...string) string {
	return getOffer(c.Get(HeaderAcceptEncoding), offers...)
}
func (c *Ctx) AcceptsLanguages(offers ...string) string {
	return getOffer(c.Get(HeaderAcceptLanguage), offers...)
}
func (c *Ctx) App() *App {
	return c.app
}
func (c *Ctx) Append(field string, values ...string) {
	if len(values) == 0 {
		return
	}
	h := c.app.getString(c.fasthttp.Response.Header.Peek(field))
	originalH := h
	for _, value := range values {
		if len(h) == 0 {
			h = value
		} else if h != value && !strings.HasPrefix(h, value+",") && !strings.HasSuffix(h, " "+value) &&
			!strings.Contains(h, " "+value+",") {
			h += ", " + value
		}
	}
	if originalH != h {
		c.Set(field, h)
	}
}
func (c *Ctx) Attachment(filename ...string) {
	if len(filename) > 0 {
		fname := filepath.Base(filename[0])
		c.Type(filepath.Ext(fname))
		c.setCanonical(HeaderContentDisposition, `attachment; filename="`+c.app.quoteString(fname)+`"`)
		return
	}
	c.setCanonical(HeaderContentDisposition, "attachment")
}
func (c *Ctx) BaseURL() string {
	if c.baseURI != "" {
		return c.baseURI
	}
	c.baseURI = c.Protocol() + "://" + c.Hostname()
	return c.baseURI
}
func (c *Ctx) Body() []byte {
	var err error
	var encoding string
	var body []byte
	c.Request().Header.VisitAll(func(key, value []byte) {
		if utils.UnsafeString(key) == HeaderContentEncoding {
			encoding = utils.UnsafeString(value)
		}
	})
	switch encoding {
	case StrGzip:
		body, err = c.fasthttp.Request.BodyGunzip()
	case StrBr, StrBrotli:
		body, err = c.fasthttp.Request.BodyUnbrotli()
	case StrDeflate:
		body, err = c.fasthttp.Request.BodyInflate()
	default:
		body = c.fasthttp.Request.Body()
	}
	if err != nil {
		return []byte(err.Error())
	}
	return body
}
var decoderPool = &sync.Pool{New: func() interface{} {
	return decoderBuilder(ParserConfig{
		IgnoreUnknownKeys: true,
		ZeroEmpty:         true,
	})
}}
func SetParserDecoder(parserConfig ParserConfig) {
	decoderPool = &sync.Pool{New: func() interface{} {
		return decoderBuilder(parserConfig)
	}}
}
func decoderBuilder(parserConfig ParserConfig) interface{} {
	var decoder = schema.NewDecoder()
	decoder.IgnoreUnknownKeys(parserConfig.IgnoreUnknownKeys)
	if parserConfig.SetAliasTag != "" {
		decoder.SetAliasTag(parserConfig.SetAliasTag)
	}
	for _, v := range parserConfig.ParserType {
		decoder.RegisterConverter(reflect.ValueOf(v.Customtype).Interface(), v.Converter)
	}
	decoder.ZeroEmpty(parserConfig.ZeroEmpty)
	return decoder
}
func (c *Ctx) BodyParser(out interface{}) error {
	schemaDecoder := decoderPool.Get().(*schema.Decoder)
	defer decoderPool.Put(schemaDecoder)
	ctype := utils.ToLower(utils.UnsafeString(c.fasthttp.Request.Header.ContentType()))
	ctype = utils.ParseVendorSpecificContentType(ctype)
	if strings.HasPrefix(ctype, MIMEApplicationJSON) {
		schemaDecoder.SetAliasTag("json")
		return c.app.config.JSONDecoder(c.Body(), out)
	}
	if strings.HasPrefix(ctype, MIMEApplicationForm) {
		schemaDecoder.SetAliasTag("form")
		data := make(map[string][]string)
		c.fasthttp.PostArgs().VisitAll(func(key []byte, val []byte) {
			data[utils.UnsafeString(key)] = append(data[utils.UnsafeString(key)], utils.UnsafeString(val))
		})
		return schemaDecoder.Decode(out, data)
	}
	if strings.HasPrefix(ctype, MIMEMultipartForm) {
		schemaDecoder.SetAliasTag("form")
		data, err := c.fasthttp.MultipartForm()
		if err != nil {
			return err
		}
		return schemaDecoder.Decode(out, data.Value)
	}
	if strings.HasPrefix(ctype, MIMETextXML) || strings.HasPrefix(ctype, MIMEApplicationXML) {
		schemaDecoder.SetAliasTag("xml")
		return xml.Unmarshal(c.Body(), out)
	}
	return ErrUnprocessableEntity
}