func (app *App) Get(path string, handlers ...Handler) Router {
	return app.Add(MethodHead, path, handlers...).Add(MethodGet, path, handlers...)
}
Get registers a route for GET methods that requests a representation
of the specified resource. Requests using GET should only retrieve data.
package fiber
import (
	"bufio"
	"crypto/tls"
	"errors"
	"fmt"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"github.com/gofiber/fiber/v2/internal/colorable"
	"github.com/gofiber/fiber/v2/internal/go-json"
	"github.com/gofiber/fiber/v2/internal/isatty"
	"github.com/gofiber/fiber/v2/utils"
	"github.com/valyala/fasthttp"
)
const Version = "2.20.2"
type Handler = func(*Ctx) error
type Map map[string]interface{}
type Storage interface {
	Get(key string) ([]byte, error)
	Set(key string, val []byte, ttl time.Duration) error
	Delete(key string) error
	Reset() error
	Close() error
}
type ErrorHandler = func(*Ctx, error) error
type Error struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}
type App struct {
	mutex sync.Mutex
	stack [][]*Route
	treeStack []map[string][]*Route
	routesRefreshed bool
	routesCount uint32
	handlerCount uint32
	pool sync.Pool
	server *fasthttp.Server
	config Config
	getBytes func(s string) (b []byte)
	getString func(b []byte) string
	errorHandlers map[string]ErrorHandler
}
type Config struct {
	Prefork bool `json:"prefork"`
	ServerHeader string `json:"server_header"`
	StrictRouting bool `json:"strict_routing"`
	CaseSensitive bool `json:"case_sensitive"`
	Immutable bool `json:"immutable"`
	UnescapePath bool `json:"unescape_path"`
	ETag bool `json:"etag"`
	BodyLimit int `json:"body_limit"`
	Concurrency int `json:"concurrency"`
	Views Views `json:"-"`
	ViewsLayout string `json:"views_layout"`
	ReadTimeout time.Duration `json:"read_timeout"`
	WriteTimeout time.Duration `json:"write_timeout"`
	IdleTimeout time.Duration `json:"idle_timeout"`
	ReadBufferSize int `json:"read_buffer_size"`
	WriteBufferSize int `json:"write_buffer_size"`
	CompressedFileSuffix string `json:"compressed_file_suffix"`
	ProxyHeader string `json:"proxy_header"`
	GETOnly bool `json:"get_only"`
	ErrorHandler ErrorHandler `json:"-"`
	DisableKeepalive bool `json:"disable_keepalive"`
	DisableDefaultDate bool `json:"disable_default_date"`
	DisableDefaultContentType bool `json:"disable_default_content_type"`
	DisableHeaderNormalizing bool `json:"disable_header_normalizing"`
	DisableStartupMessage bool `json:"disable_startup_message"`
	AppName string `json:"app_name"`
	StreamRequestBody bool
	DisablePreParseMultipartForm bool
	ReduceMemoryUsage bool `json:"reduce_memory_usage"`
	JSONEncoder utils.JSONMarshal `json:"-"`
	JSONDecoder utils.JSONUnmarshal `json:"-"`
	Network string
	EnableTrustedProxyCheck bool `json:"enable_trusted_proxy_check"`
	TrustedProxies    []string `json:"trusted_proxies"`
	trustedProxiesMap map[string]struct{}
}
type Static struct {
	Compress bool `json:"compress"`
	ByteRange bool `json:"byte_range"`
	Browse bool `json:"browse"`
	Index string `json:"index"`
	CacheDuration time.Duration `json:"cache_duration"`
	MaxAge int `json:"max_age"`
	Next func(c *Ctx) bool
}
const (
	DefaultBodyLimit            = 4 * 1024 * 1024
	DefaultConcurrency          = 256 * 1024
	DefaultReadBufferSize       = 4096
	DefaultWriteBufferSize      = 4096
	DefaultCompressedFileSuffix = ".fiber.gz"
)
var DefaultErrorHandler = func(c *Ctx, err error) error {
	code := StatusInternalServerError
	if e, ok := err.(*Error); ok {
		code = e.Code
	}
	c.Set(HeaderContentType, MIMETextPlainCharsetUTF8)
	return c.Status(code).SendString(err.Error())
}
func New(config ...Config) *App {
	app := &App{
		stack:     make([][]*Route, len(intMethod)),
		treeStack: make([]map[string][]*Route, len(intMethod)),
		pool: sync.Pool{
			New: func() interface{} {
				return new(Ctx)
			},
		},
		config:        Config{},
		getBytes:      utils.UnsafeBytes,
		getString:     utils.UnsafeString,
		errorHandlers: make(map[string]ErrorHandler),
	}
	if len(config) > 0 {
		app.config = config[0]
	}
	if app.config.ETag {
		if !IsChild() {
			fmt.Println("[Warning] Config.ETag is deprecated since v2.0.6, please use 'middleware/etag'.")
		}
	}
	if app.config.BodyLimit == 0 {
		app.config.BodyLimit = DefaultBodyLimit
	}
	if app.config.Concurrency <= 0 {
		app.config.Concurrency = DefaultConcurrency
	}
	if app.config.ReadBufferSize <= 0 {
		app.config.ReadBufferSize = DefaultReadBufferSize
	}
	if app.config.WriteBufferSize <= 0 {
		app.config.WriteBufferSize = DefaultWriteBufferSize
	}
	if app.config.CompressedFileSuffix == "" {
		app.config.CompressedFileSuffix = DefaultCompressedFileSuffix
	}
	if app.config.Immutable {
		app.getBytes, app.getString = getBytesImmutable, getStringImmutable
	}
	if app.config.ErrorHandler == nil {
		app.config.ErrorHandler = DefaultErrorHandler
	}
	if app.config.JSONEncoder == nil {
		app.config.JSONEncoder = json.Marshal
	}
	if app.config.JSONDecoder == nil {
		app.config.JSONDecoder = json.Unmarshal
	}
	if app.config.Network == "" {
		app.config.Network = NetworkTCP4
	}
	app.config.trustedProxiesMap = make(map[string]struct{}, len(app.config.TrustedProxies))
	for _, ip := range app.config.TrustedProxies {
		app.config.trustedProxiesMap[ip] = struct{}{}
	}
	app.init()
	return app
}
func (app *App) Mount(prefix string, fiber *App) Router {
	stack := fiber.Stack()
	for m := range stack {
		for r := range stack[m] {
			route := app.copyRoute(stack[m][r])
			app.addRoute(route.Method, app.addPrefixToRoute(prefix, route))
		}
	}
	prefix = strings.TrimRight(prefix, "/")
	if fiber.config.ErrorHandler != nil {
		app.errorHandlers[prefix] = fiber.config.ErrorHandler
	}
	for mountedPrefixes, errHandler := range fiber.errorHandlers {
		app.errorHandlers[prefix+mountedPrefixes] = errHandler
	}
	atomic.AddUint32(&app.handlerCount, fiber.handlerCount)
	return app
}
func (app *App) Use(args ...interface{}) Router {
	var prefix string
	var handlers []Handler
	for i := 0; i < len(args); i++ {
		switch arg := args[i].(type) {
		case string:
			prefix = arg
		case Handler:
			handlers = append(handlers, arg)
		default:
			panic(fmt.Sprintf("use: invalid handler %v\n", reflect.TypeOf(arg)))
		}
	}
	app.register(methodUse, prefix, handlers...)
	return app
}