Просмотр исходного кода

SVI Документация, код

SVI 2 лет назад
Родитель
Сommit
a072d78e63
35 измененных файлов с 151 добавлено и 5805 удалено
  1. 2 1
      Makefile
  2. 38 0
      README.md
  3. 1 0
      dev.sh
  4. 1 6
      go.mod
  5. 0 22
      go.sum
  6. 90 2
      internal/serv_http/serv_http.go
  7. 12 2
      internal/service/service.go
  8. 7 0
      pkg/types/iserv_http.go
  9. 0 26
      vendor/github.com/gofiber/fiber/.gitignore
  10. 0 21
      vendor/github.com/gofiber/fiber/LICENSE
  11. 0 713
      vendor/github.com/gofiber/fiber/app.go
  12. 0 1045
      vendor/github.com/gofiber/fiber/ctx.go
  13. 0 126
      vendor/github.com/gofiber/fiber/group.go
  14. 0 370
      vendor/github.com/gofiber/fiber/path.go
  15. 0 152
      vendor/github.com/gofiber/fiber/prefork.go
  16. 0 390
      vendor/github.com/gofiber/fiber/router.go
  17. 0 642
      vendor/github.com/gofiber/fiber/utils.go
  18. 0 21
      vendor/github.com/gofiber/utils/LICENSE
  19. 0 87
      vendor/github.com/gofiber/utils/README.md
  20. 0 62
      vendor/github.com/gofiber/utils/assertions.go
  21. 0 78
      vendor/github.com/gofiber/utils/bytes.go
  22. 0 83
      vendor/github.com/gofiber/utils/common.go
  23. 0 104
      vendor/github.com/gofiber/utils/convert.go
  24. 0 110
      vendor/github.com/gofiber/utils/file.go
  25. 0 212
      vendor/github.com/gofiber/utils/http.go
  26. 0 13
      vendor/github.com/gofiber/utils/integer.go
  27. 0 70
      vendor/github.com/gofiber/utils/strings.go
  28. 0 27
      vendor/github.com/gorilla/schema/LICENSE
  29. 0 90
      vendor/github.com/gorilla/schema/README.md
  30. 0 305
      vendor/github.com/gorilla/schema/cache.go
  31. 0 145
      vendor/github.com/gorilla/schema/converter.go
  32. 0 521
      vendor/github.com/gorilla/schema/decoder.go
  33. 0 148
      vendor/github.com/gorilla/schema/doc.go
  34. 0 202
      vendor/github.com/gorilla/schema/encoder.go
  35. 0 9
      vendor/modules.txt

+ 2 - 1
Makefile

@@ -13,4 +13,5 @@ mod:
 	clear
 	go get -u ./...
 	go mod tidy -compat=1.21.1
-	go mod vendor
+	go mod vendor
+	go fmt ./...

+ 38 - 0
README.md

@@ -1,3 +1,41 @@
 # gostore
 
 Простейшее сетевое хранилще на `golang`.
+
+## Описание
+
+Хранилище `ключ-значение` работает поверх HTTP1.1/ip4.
+
+Выполняет следующие POST-запросы:
+
+* [ ] `/put/:login/:pass/:key` (поместить в хранилище);
+* [ ] `/get/:login/:pass/:key` (извлечь из хранилища);
+* [ ] `/del/:login/:pass/:key` (удалить из хранилища).
+* [ ] `/time` (возвращает текущее время на сервере; для поддержания `KeepAlive`).
+
+Запросы сделанными классическими специально, чтобы гарантировать праильную работу через прокси.
+
+Поддерживается `KeepAlive` с ожиданием следующего запроса 10 сек. Клиент должен
+присылать запросы не реже, чтобы поддерживать открытым соединение.
+
+Если необходима работа через внешние сети, то следует использовать `nginx proxy manager`
+со включенными сертификатами `LetsEncript` перед сервисом `gostore`.
+
+Максимальный размер значения ключа не может быть более 10 МБ (но можно настроить в коде).
+
+## Переменные окружения
+
+```bash
+export STORE_USER="dev"
+export STORE_USER_PASS="dev"
+export STORE_HTTP_PORT="25000"
+```
+
+## Команды сборки
+
+```make
+make         # Сборка сервиса для прода
+make build   # -//-
+make dev.run # Сборка с и запуск  детектором гонок для отладки
+make mod     # Обновление зависимостей
+```

+ 1 - 0
dev.sh

@@ -1,4 +1,5 @@
 export STORE_USER="dev"
 export STORE_USER_PASS="dev"
+export STORE_HTTP_PORT="25000"
 cd ./bin_dev && \
 ./gostore_dev

+ 1 - 6
go.mod

@@ -2,16 +2,11 @@ module git.p78su.freemyip.com/svi/gostore
 
 go 1.21.1
 
-require (
-	github.com/gofiber/fiber v1.14.6
-	github.com/gofiber/fiber/v2 v2.50.0
-)
+require github.com/gofiber/fiber/v2 v2.50.0
 
 require (
 	github.com/andybalholm/brotli v1.0.6 // indirect
-	github.com/gofiber/utils v1.1.0 // indirect
 	github.com/google/uuid v1.4.0 // indirect
-	github.com/gorilla/schema v1.2.0 // indirect
 	github.com/klauspost/compress v1.17.2 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
 	github.com/mattn/go-isatty v0.0.20 // indirect

+ 0 - 22
go.sum

@@ -1,25 +1,13 @@
-github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
 github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
 github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
-github.com/gofiber/fiber v1.14.6 h1:QRUPvPmr8ijQuGo1MgupHBn8E+wW0IKqiOvIZPtV70o=
-github.com/gofiber/fiber v1.14.6/go.mod h1:Yw2ekF1YDPreO9V6TMYjynu94xRxZBdaa8X5HhHsjCM=
 github.com/gofiber/fiber/v2 v2.50.0 h1:ia0JaB+uw3GpNSCR5nvC5dsaxXjRU5OEu36aytx+zGw=
 github.com/gofiber/fiber/v2 v2.50.0/go.mod h1:21eytvay9Is7S6z+OgPi7c7n4++tnClWmhpimVHMimw=
-github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo=
-github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
-github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
 github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
 github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
-github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
-github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
-github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
 github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
 github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
@@ -30,21 +18,11 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
 github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
 github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
 github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
-github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
 github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
 github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

+ 90 - 2
internal/serv_http/serv_http.go

@@ -2,11 +2,99 @@
 package serv_http
 
 import (
-	"github.com/gofiber/fiber"
+	"fmt"
+	"os"
+	"time"
+
 	"github.com/gofiber/fiber/v2"
+
+	"git.p78su.freemyip.com/svi/gostore/pkg/types"
 )
 
 // ServHttp -- встроенный HTTP-сервер
 type ServHttp struct {
-	fib fiber.App
+	serv     types.IServHttp
+	fiberApp *fiber.App
+	port     string
+}
+
+// NewServHttp -- возвращает новый HTTP-сервер
+func NewServHttp(serv types.IService) (types.IServHttp, error) {
+	if serv == nil {
+		return nil, fmt.Errorf("NewServHttp(): IService==nil")
+	}
+	port := os.Getenv("STORE_HTTP_PORT")
+	if port == "" {
+		return nil, fmt.Errorf("NewServHttp(): env STORE_HTTP_PORT not set")
+	}
+	config := fiber.Config{
+		Prefork:              false,
+		ServerHeader:         "GoStore",
+		StrictRouting:        false,
+		CaseSensitive:        false,
+		Immutable:            false,
+		UnescapePath:         false,
+		ETag:                 false,
+		BodyLimit:            10_000_000,
+		Concurrency:          0,
+		Views:                nil,
+		ViewsLayout:          "",
+		PassLocalsToViews:    false,
+		ReadTimeout:          time.Second * 60,
+		WriteTimeout:         time.Second * 60,
+		IdleTimeout:          time.Second * 10,
+		ReadBufferSize:       0,
+		WriteBufferSize:      0,
+		CompressedFileSuffix: "",
+		ProxyHeader:          "",
+		GETOnly:              false,
+		// ErrorHandler:                 func(*fiber.Ctx, error) error { panic("not implemented") },
+		DisableKeepalive:             false,
+		DisableDefaultDate:           false,
+		DisableDefaultContentType:    false,
+		DisableHeaderNormalizing:     false,
+		DisableStartupMessage:        false,
+		AppName:                      "GoStore",
+		StreamRequestBody:            false,
+		DisablePreParseMultipartForm: false,
+		ReduceMemoryUsage:            false,
+		// JSONEncoder:                  func(interface{}) ([]byte, error) { panic("not implemented") },
+		// JSONDecoder:                  func([]byte, interface{}) error { panic("not implemented") },
+		// XMLEncoder:                   func(interface{}) ([]byte, error) { panic("not implemented") },
+		Network:                 "tcp4",
+		EnableTrustedProxyCheck: false,
+		TrustedProxies:          []string{},
+		EnableIPValidation:      false,
+		EnablePrintRoutes:       false,
+		// ColorScheme: fiber.Colors{
+		// 	Black:   "",
+		// 	Red:     "",
+		// 	Green:   "",
+		// 	Yellow:  "",
+		// 	Blue:    "",
+		// 	Magenta: "",
+		// 	Cyan:    "",
+		// 	White:   "",
+		// 	Reset:   "",
+		// },
+		// RequestMethods:           []string{},
+		EnableSplittingOnParsers: false,
+	}
+
+	app := fiber.New(config)
+	sf := &ServHttp{
+		serv:     serv,
+		fiberApp: app,
+		port:     port,
+	}
+	return sf, nil
+}
+
+// Run -- запускает веб-сервер в работу
+func (sf *ServHttp) Run() error {
+	err := sf.fiberApp.Listen(":" + sf.port)
+	if err != nil {
+		return fmt.Errorf("ServHttp.Run(): in listen port(%q), err=\n\t%w", sf.port, err)
+	}
+	return nil
 }

+ 12 - 2
internal/service/service.go

@@ -4,13 +4,15 @@ package service
 import (
 	"fmt"
 
+	"git.p78su.freemyip.com/svi/gostore/internal/serv_http"
 	"git.p78su.freemyip.com/svi/gostore/internal/store_user"
 	"git.p78su.freemyip.com/svi/gostore/pkg/types"
 )
 
 // Service -- главный объект сервиса
 type Service struct {
-	user types.IStoreUser
+	user     types.IStoreUser
+	servHttp types.IServHttp
 }
 
 // NewService -- возвращает новый объект сервиса
@@ -22,10 +24,18 @@ func NewService() (types.IService, error) {
 	sf := &Service{
 		user: user,
 	}
+	sf.servHttp, err = serv_http.NewServHttp(sf)
+	if err != nil {
+		return nil, fmt.Errorf("NewService(): in create IServHttp, err=\n\t%w", err)
+	}
 	return sf, nil
 }
 
 // Run -- запускает сервис в работу
 func (sf *Service) Run() error {
-	return fmt.Errorf("Service.Run(): доделать")
+	err := sf.servHttp.Run()
+	if err != nil {
+		return fmt.Errorf("Service.Run(): in run IServHttp, err=\n\t%w", err)
+	}
+	return nil
 }

+ 7 - 0
pkg/types/iserv_http.go

@@ -0,0 +1,7 @@
+package types
+
+// IServHttp -- встроенный веб-сервер
+type IServHttp interface {
+	// Run -- запускает веб-сервер в работу
+	Run() error
+}

+ 0 - 26
vendor/github.com/gofiber/fiber/.gitignore

@@ -1,26 +0,0 @@
-# Binaries for programs and plugins
-*.exe
-*.exe~
-*.dll
-*.so
-*.dylib
-
-# Test binary, built with `go test -c`
-*.test
-
-# Output of the go coverage tool, specifically when used with LiteIDE
-*.out
-
-# IDE files
-.vscode
-.DS_Store
-.idea
-
-# Misc
-*.fiber.gz
-*.fasthttp.gz
-*.pprof
-*.workspace
-
-# Dependencies
-vendor

+ 0 - 21
vendor/github.com/gofiber/fiber/LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019-2020 Fenny and Contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 0 - 713
vendor/github.com/gofiber/fiber/app.go

@@ -1,713 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-// Package fiber
-// Fiber is an Express inspired web framework built on top of Fasthttp,
-// the fastest HTTP engine for Go. Designed to ease things up for fast
-// development with zero memory allocation and performance in mind.
-
-package fiber
-
-import (
-	"bufio"
-	"crypto/tls"
-	"fmt"
-	"io"
-	"net"
-	"net/http"
-	"net/http/httputil"
-	"os"
-	"reflect"
-	"runtime"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-
-	utils "github.com/gofiber/utils"
-	colorable "github.com/mattn/go-colorable"
-	isatty "github.com/mattn/go-isatty"
-	fasthttp "github.com/valyala/fasthttp"
-)
-
-// Version of current package
-const Version = "1.14.6"
-
-// Map is a shortcut for map[string]interface{}, useful for JSON returns
-type Map map[string]interface{}
-
-// Handler defines a function to serve HTTP requests.
-type Handler = func(*Ctx)
-
-// Error represents an error that occurred while handling a request.
-type Error struct {
-	Code    int    `json:"code"`
-	Message string `json:"message"`
-}
-
-// App denotes the Fiber application.
-type App struct {
-	out   io.Writer
-	mutex sync.Mutex
-	// Route stack divided by HTTP methods
-	stack [][]*Route
-	// Route stack divided by HTTP methods and route prefixes
-	treeStack []map[string][]*Route
-	// Amount of registered routes
-	routesCount int
-	// Amount of registered handlers
-	handlerCount int
-	// Ctx pool
-	pool sync.Pool
-	// Fasthttp server
-	server *fasthttp.Server
-	// App settings
-	Settings *Settings `json:"settings"`
-}
-
-// Settings is a struct holding the server settings.
-type Settings struct {
-	// ErrorHandler is executed when you pass an error in the Next(err) method.
-	// This function is also executed when middleware.Recover() catches a panic
-	// Default: func(ctx *Ctx, err error) {
-	// 	code := StatusInternalServerError
-	// 	if e, ok := err.(*Error); ok {
-	// 		code = e.Code
-	// 	}
-	// 	ctx.Set(HeaderContentType, MIMETextPlainCharsetUTF8)
-	// 	ctx.Status(code).SendString(err.Error())
-	// }
-	ErrorHandler func(*Ctx, error) `json:"-"`
-
-	// Enables the "Server: value" HTTP header.
-	// Default: ""
-	ServerHeader string `json:"server_header"`
-
-	// When set to true, the router treats "/foo" and "/foo/" as different.
-	// By default this is disabled and both "/foo" and "/foo/" will execute the same handler.
-	StrictRouting bool `json:"strict_routing"`
-
-	// When set to true, enables case sensitive routing.
-	// E.g. "/FoO" and "/foo" are treated as different routes.
-	// By default this is disabled and both "/FoO" and "/foo" will execute the same handler.
-	CaseSensitive bool `json:"case_sensitive"`
-
-	// When set to true, this relinquishes the 0-allocation promise in certain
-	// cases in order to access the handler values (e.g. request bodies) in an
-	// immutable fashion so that these values are available even if you return
-	// from handler.
-	// Default: false
-	Immutable bool `json:"immutable"`
-
-	// When set to true, converts all encoded characters in the route back
-	// before setting the path for the context, so that the routing can also
-	// work with urlencoded special characters.
-	// Default: false
-	UnescapePath bool `json:"unescape_path"`
-
-	// Enable or disable ETag header generation, since both weak and strong etags are generated
-	// using the same hashing method (CRC-32). Weak ETags are the default when enabled.
-	// Default: false
-	ETag bool `json:"etag"`
-
-	// When set to true, this will spawn multiple Go processes listening on the same port.
-	// Default: false
-	Prefork bool `json:"prefork"`
-
-	// Max body size that the server accepts.
-	// Default: 4 * 1024 * 1024
-	BodyLimit int `json:"body_limit"`
-
-	// Maximum number of concurrent connections.
-	// Default: 256 * 1024
-	Concurrency int `json:"concurrency"`
-
-	// When set to true, disables keep-alive connections.
-	// The server will close incoming connections after sending the first response to client.
-	// Default: false
-	DisableKeepalive bool `json:"disable_keep_alive"`
-
-	// When set to true, causes the default date header to be excluded from the response.
-	// Default: false
-	DisableDefaultDate bool `json:"disable_default_date"`
-
-	// When set to true, causes the default Content-Type header to be excluded from the response.
-	// Default: false
-	DisableDefaultContentType bool `json:"disable_default_content_type"`
-
-	// When set to true, disables header normalization.
-	// By default all header names are normalized: conteNT-tYPE -> Content-Type.
-	// Default: false
-	DisableHeaderNormalizing bool `json:"disable_header_normalizing"`
-
-	// When set to true, it will not print out the «Fiber» ASCII art and listening address.
-	// Default: false
-	DisableStartupMessage bool `json:"disable_startup_message"`
-
-	// Views is the interface that wraps the Render function.
-	// Default: nil
-	Views Views `json:"-"`
-
-	// The amount of time allowed to read the full request including body.
-	// It is reset after the request handler has returned.
-	// The connection's read deadline is reset when the connection opens.
-	// Default: unlimited
-	ReadTimeout time.Duration `json:"read_timeout"`
-
-	// The maximum duration before timing out writes of the response.
-	// It is reset after the request handler has returned.
-	// Default: unlimited
-	WriteTimeout time.Duration `json:"write_timeout"`
-
-	// The maximum amount of time to wait for the next request when keep-alive is enabled.
-	// If IdleTimeout is zero, the value of ReadTimeout is used.
-	// Default: unlimited
-	IdleTimeout time.Duration `json:"idle_timeout"`
-
-	// Per-connection buffer size for requests' reading.
-	// This also limits the maximum header size.
-	// Increase this buffer if your clients send multi-KB RequestURIs
-	// and/or multi-KB headers (for example, BIG cookies).
-	// Default: 4096
-	ReadBufferSize int `json:"read_buffer_size"`
-
-	// Per-connection buffer size for responses' writing.
-	// Default: 4096
-	WriteBufferSize int `json:"write_buffer_size"`
-
-	// CompressedFileSuffix adds suffix to the original file name and
-	// tries saving the resulting compressed file under the new file name.
-	// Default: ".fiber.gz"
-	CompressedFileSuffix string `json:"compressed_file_suffix"`
-
-	// FEATURE: v1.13
-	// The router executes the same handler by default if StrictRouting or CaseSensitive is disabled.
-	// Enabling RedirectFixedPath will change this behaviour into a client redirect to the original route path.
-	// Using the status code 301 for GET requests and 308 for all other request methods.
-	// RedirectFixedPath bool
-}
-
-// Static defines configuration options when defining static assets.
-type Static struct {
-	// When set to true, the server tries minimizing CPU usage by caching compressed files.
-	// This works differently than the github.com/gofiber/compression middleware.
-	// Optional. Default value false
-	Compress bool
-
-	// When set to true, enables byte range requests.
-	// Optional. Default value false
-	ByteRange bool
-
-	// When set to true, enables directory browsing.
-	// Optional. Default value false.
-	Browse bool
-
-	// The name of the index file for serving a directory.
-	// Optional. Default value "index.html".
-	Index string
-}
-
-// default settings
-const (
-	defaultBodyLimit            = 4 * 1024 * 1024
-	defaultConcurrency          = 256 * 1024
-	defaultReadBufferSize       = 4096
-	defaultWriteBufferSize      = 4096
-	defaultCompressedFileSuffix = ".fiber.gz"
-)
-
-var defaultErrorHandler = func(ctx *Ctx, err error) {
-	code := StatusInternalServerError
-	if e, ok := err.(*Error); ok {
-		code = e.Code
-	}
-	ctx.Set(HeaderContentType, MIMETextPlainCharsetUTF8)
-	ctx.Status(code).SendString(err.Error())
-}
-
-// New creates a new Fiber named instance.
-//  myApp := app.New()
-// You can pass an optional settings by passing a *Settings struct:
-//  myApp := app.New(&fiber.Settings{
-//      Prefork: true,
-//      ServerHeader: "Fiber",
-//  })
-func New(settings ...*Settings) *App {
-	// Create a new app
-	app := &App{
-		// Create router stack
-		stack:     make([][]*Route, len(intMethod)),
-		treeStack: make([]map[string][]*Route, len(intMethod)),
-		// Create Ctx pool
-		pool: sync.Pool{
-			New: func() interface{} {
-				return new(Ctx)
-			},
-		},
-		// Set settings
-		Settings: &Settings{},
-	}
-
-	// Overwrite settings if provided
-	if len(settings) > 0 {
-		app.Settings = settings[0]
-	}
-
-	if app.Settings.BodyLimit <= 0 {
-		app.Settings.BodyLimit = defaultBodyLimit
-	}
-	if app.Settings.Concurrency <= 0 {
-		app.Settings.Concurrency = defaultConcurrency
-	}
-	if app.Settings.ReadBufferSize <= 0 {
-		app.Settings.ReadBufferSize = defaultReadBufferSize
-	}
-	if app.Settings.WriteBufferSize <= 0 {
-		app.Settings.WriteBufferSize = defaultWriteBufferSize
-	}
-	if app.Settings.CompressedFileSuffix == "" {
-		app.Settings.CompressedFileSuffix = defaultCompressedFileSuffix
-	}
-	if app.Settings.ErrorHandler == nil {
-		app.Settings.ErrorHandler = defaultErrorHandler
-	}
-	if app.Settings.Immutable {
-		getBytes, getString = getBytesImmutable, getStringImmutable
-	}
-
-	// Return app
-	return app
-}
-
-// Use registers a middleware route.
-// Middleware matches requests beginning with the provided prefix.
-// Providing a prefix is optional, it defaults to "/".
-//
-//  app.Use(handler)
-//  app.Use("/api", handler)
-//  app.Use("/api", handler, handler)
-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
-}
-
-// Get registers a route for GET methods that requests a representation
-// of the specified resource. Requests using GET should only retrieve data.
-func (app *App) Get(path string, handlers ...Handler) Router {
-	route := app.register(MethodGet, path, handlers...)
-	// Add HEAD route
-	headRoute := route
-	app.addRoute(MethodHead, &headRoute)
-
-	return app
-}
-
-// Head registers a route for HEAD methods that asks for a response identical
-// to that of a GET request, but without the response body.
-func (app *App) Head(path string, handlers ...Handler) Router {
-	return app.Add(MethodHead, path, handlers...)
-}
-
-// Post registers a route for POST methods that is used to submit an entity to the
-// specified resource, often causing a change in state or side effects on the server.
-func (app *App) Post(path string, handlers ...Handler) Router {
-	return app.Add(MethodPost, path, handlers...)
-}
-
-// Put registers a route for PUT methods that replaces all current representations
-// of the target resource with the request payload.
-func (app *App) Put(path string, handlers ...Handler) Router {
-	return app.Add(MethodPut, path, handlers...)
-}
-
-// Delete registers a route for DELETE methods that deletes the specified resource.
-func (app *App) Delete(path string, handlers ...Handler) Router {
-	return app.Add(MethodDelete, path, handlers...)
-}
-
-// Connect registers a route for CONNECT methods that establishes a tunnel to the
-// server identified by the target resource.
-func (app *App) Connect(path string, handlers ...Handler) Router {
-	return app.Add(MethodConnect, path, handlers...)
-}
-
-// Options registers a route for OPTIONS methods that is used to describe the
-// communication options for the target resource.
-func (app *App) Options(path string, handlers ...Handler) Router {
-	return app.Add(MethodOptions, path, handlers...)
-}
-
-// Trace registers a route for TRACE methods that performs a message loop-back
-// test along the path to the target resource.
-func (app *App) Trace(path string, handlers ...Handler) Router {
-	return app.Add(MethodTrace, path, handlers...)
-}
-
-// Patch registers a route for PATCH methods that is used to apply partial
-// modifications to a resource.
-func (app *App) Patch(path string, handlers ...Handler) Router {
-	return app.Add(MethodPatch, path, handlers...)
-}
-
-// Add ...
-func (app *App) Add(method, path string, handlers ...Handler) Router {
-	app.register(method, path, handlers...)
-	return app
-}
-
-// Static ...
-func (app *App) Static(prefix, root string, config ...Static) Router {
-	app.registerStatic(prefix, root, config...)
-	return app
-}
-
-// All ...
-func (app *App) All(path string, handlers ...Handler) Router {
-	for _, method := range intMethod {
-		app.Add(method, path, handlers...)
-	}
-	return app
-}
-
-// Group is used for Routes with common prefix to define a new sub-router with optional middleware.
-func (app *App) Group(prefix string, handlers ...Handler) Router {
-	if len(handlers) > 0 {
-		app.register(methodUse, prefix, handlers...)
-	}
-	return &Group{prefix: prefix, app: app}
-}
-
-// Error makes it compatible with `error` interface.
-func (e *Error) Error() string {
-	return e.Message
-}
-
-// NewError creates a new HTTPError instance.
-func NewError(code int, message ...string) *Error {
-	e := &Error{code, utils.StatusMessage(code)}
-	if len(message) > 0 {
-		e.Message = message[0]
-	}
-	return e
-}
-
-// Routes returns all registered routes
-//  for _, r := range app.Routes() {
-//  	fmt.Printf("%s\t%s\n", r.Method, r.Path)
-//  }
-func (app *App) Routes() []*Route {
-	fmt.Println("routes is deprecated since v1.13.2, please use `app.Stack()` to access the raw router stack")
-	routes := make([]*Route, 0)
-	for m := range app.stack {
-	stackLoop:
-		for r := range app.stack[m] {
-			// Don't duplicate USE routesCount
-			if app.stack[m][r].use {
-				for i := range routes {
-					if routes[i].use && routes[i].Path == app.stack[m][r].Path {
-						continue stackLoop
-					}
-				}
-			}
-			routes = append(routes, app.stack[m][r])
-		}
-	}
-	return routes
-}
-
-// Listener can be used to pass a custom listener.
-// You can pass an optional *tls.Config to enable TLS.
-// This method does not support the Prefork feature
-// To use Prefork, please use app.Listen()
-func (app *App) Listener(ln net.Listener, tlsconfig ...*tls.Config) error {
-	// Update server settings
-	app.init()
-	// TLS config
-	if len(tlsconfig) > 0 {
-		ln = tls.NewListener(ln, tlsconfig[0])
-	}
-	// Print startup message
-	if !app.Settings.DisableStartupMessage {
-		app.startupMessage(ln.Addr().String(), len(tlsconfig) > 0, "")
-	}
-	return app.server.Serve(ln)
-}
-
-// Listen serves HTTP requests from the given addr or port.
-// You can pass an optional *tls.Config to enable TLS.
-//
-//  app.Listen(8080)
-//  app.Listen("8080")
-//  app.Listen(":8080")
-//  app.Listen("127.0.0.1:8080")
-func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error {
-	// Convert address to string
-	addr, ok := address.(string)
-	if !ok {
-		port, ok := address.(int)
-		if !ok {
-			return fmt.Errorf("listen: host must be an `int` port or `string` address")
-		}
-		addr = strconv.Itoa(port)
-	}
-	if !strings.Contains(addr, ":") {
-		addr = ":" + addr
-	}
-	// Update server settings
-	app.init()
-	// Start prefork
-	if app.Settings.Prefork {
-		return app.prefork(addr, tlsconfig...)
-	}
-	// Set correct network protocol
-	network := "tcp4"
-	if isIPv6(addr) {
-		network = "tcp6"
-	}
-	// Setup listener
-	ln, err := net.Listen(network, addr)
-	if err != nil {
-		return err
-	}
-	// Add TLS config if provided
-	if len(tlsconfig) > 0 {
-		ln = tls.NewListener(ln, tlsconfig[0])
-	}
-	// Print startup message
-	if !app.Settings.DisableStartupMessage {
-		app.startupMessage(ln.Addr().String(), len(tlsconfig) > 0, "")
-	}
-	// Start listening
-	return app.server.Serve(ln)
-}
-
-// Handler returns the server handler.
-func (app *App) Handler() fasthttp.RequestHandler {
-	app.init()
-	return app.handler
-}
-
-// Handler returns the server handler.
-func (app *App) Stack() [][]*Route {
-	return app.stack
-}
-
-// Shutdown gracefully
-// shuts down the server without interrupting any active connections.
-// Shutdown works by first closing all open listeners and then waiting indefinitely for all connections to return to idle and then shut down.
-//
-// When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return nil.
-// Make sure the program doesn't exit and waits instead for Shutdown to return.
-//
-// Shutdown does not close keepalive connections so its recommended to set ReadTimeout to something else than 0.
-func (app *App) Shutdown() error {
-	app.mutex.Lock()
-	defer app.mutex.Unlock()
-	if app.server == nil {
-		return fmt.Errorf("shutdown: server is not running")
-	}
-	return app.server.Shutdown()
-}
-
-// Test is used for internal debugging by passing a *http.Request.
-// Timeout is optional and defaults to 1s, -1 will disable it completely.
-func (app *App) Test(request *http.Request, msTimeout ...int) (*http.Response, error) {
-	timeout := 1000 // 1 second default
-	if len(msTimeout) > 0 {
-		timeout = msTimeout[0]
-	}
-	// Add Content-Length if not provided with body
-	if request.Body != http.NoBody && request.Header.Get("Content-Length") == "" {
-		request.Header.Add("Content-Length", strconv.FormatInt(request.ContentLength, 10))
-	}
-	// Dump raw http request
-	dump, err := httputil.DumpRequest(request, true)
-	if err != nil {
-		return nil, err
-	}
-	// Update server settings
-	app.init()
-	// Create test connection
-	conn := new(testConn)
-	// Write raw http request
-	if _, err = conn.r.Write(dump); err != nil {
-		return nil, err
-	}
-	// Serve conn to server
-	channel := make(chan error)
-	go func() {
-		channel <- app.server.ServeConn(conn)
-	}()
-	// Wait for callback
-	if timeout >= 0 {
-		// With timeout
-		select {
-		case err = <-channel:
-		case <-time.After(time.Duration(timeout) * time.Millisecond):
-			return nil, fmt.Errorf("test: timeout error %vms", timeout)
-		}
-	} else {
-		// Without timeout
-		err = <-channel
-	}
-	// Check for errors
-	if err != nil {
-		return nil, err
-	}
-	// Read response
-	buffer := bufio.NewReader(&conn.w)
-	// Convert raw http response to *http.Response
-	resp, err := http.ReadResponse(buffer, request)
-	if err != nil {
-		return nil, err
-	}
-	// Return *http.Response
-	return resp, nil
-}
-
-type disableLogger struct{}
-
-func (dl *disableLogger) Printf(format string, args ...interface{}) {
-	// fmt.Println(fmt.Sprintf(format, args...))
-}
-
-func (app *App) init() *App {
-	// Lock application
-	app.mutex.Lock()
-	defer app.mutex.Unlock()
-
-	// Load view engine if provided
-	if app.Settings != nil {
-		// Only load templates if an view engine is specified
-		if app.Settings.Views != nil {
-			if err := app.Settings.Views.Load(); err != nil {
-				fmt.Printf("views: %v\n", err)
-			}
-		}
-	}
-	if app.server == nil {
-		app.server = &fasthttp.Server{
-			Logger:       &disableLogger{},
-			LogAllErrors: false,
-			ErrorHandler: func(fctx *fasthttp.RequestCtx, err error) {
-				ctx := app.AcquireCtx(fctx)
-				if _, ok := err.(*fasthttp.ErrSmallBuffer); ok {
-					ctx.err = ErrRequestHeaderFieldsTooLarge
-				} else if netErr, ok := err.(*net.OpError); ok && netErr.Timeout() {
-					ctx.err = ErrRequestTimeout
-				} else if len(err.Error()) == 33 && err.Error() == "body size exceeds the given limit" {
-					ctx.err = ErrRequestEntityTooLarge
-				} else {
-					ctx.err = ErrBadRequest
-				}
-				app.Settings.ErrorHandler(ctx, ctx.err)
-				app.ReleaseCtx(ctx)
-			},
-		}
-	}
-	if app.server.Handler == nil {
-		app.server.Handler = app.handler
-	}
-	app.server.Name = app.Settings.ServerHeader
-	app.server.Concurrency = app.Settings.Concurrency
-	app.server.NoDefaultDate = app.Settings.DisableDefaultDate
-	app.server.NoDefaultContentType = app.Settings.DisableDefaultContentType
-	app.server.DisableHeaderNamesNormalizing = app.Settings.DisableHeaderNormalizing
-	app.server.DisableKeepalive = app.Settings.DisableKeepalive
-	app.server.MaxRequestBodySize = app.Settings.BodyLimit
-	app.server.NoDefaultServerHeader = app.Settings.ServerHeader == ""
-	app.server.ReadTimeout = app.Settings.ReadTimeout
-	app.server.WriteTimeout = app.Settings.WriteTimeout
-	app.server.IdleTimeout = app.Settings.IdleTimeout
-	app.server.ReadBufferSize = app.Settings.ReadBufferSize
-	app.server.WriteBufferSize = app.Settings.WriteBufferSize
-	app.buildTree()
-	return app
-}
-
-const (
-	cBlack = "\u001b[90m"
-	cRed   = "\u001b[91m"
-	// cGreen  = "\u001b[92m"
-	// cYellow = "\u001b[93m"
-	// cBlue    = "\u001b[94m"
-	// cMagenta = "\u001b[95m"
-	cCyan = "\u001b[96m"
-	// cWhite   = "\u001b[97m"
-	cReset = "\u001b[0m"
-)
-
-func (app *App) startupMessage(addr string, tls bool, pids string) {
-	// ignore child processes
-	if app.IsChild() {
-		return
-	}
-	// ascii logo
-	var logo string
-	logo += `%s        _______ __                 %s` + "\n"
-	logo += `%s  ____%s / ____(_) /_  ___  _____  %s` + "\n"
-	logo += `%s_____%s / /_  / / __ \/ _ \/ ___/  %s` + "\n"
-	logo += `%s  __%s / __/ / / /_/ /  __/ /      %s` + "\n"
-	logo += `%s    /_/   /_/_.___/\___/_/%s %s` + ""
-	logo += cRed + "v2 will be released on 15 September 2020!\nPlease visit https://gofiber.io/v2 for more information.\n" + cReset
-	host, port := parseAddr(addr)
-	padding := strconv.Itoa(len(host))
-	if len(host) <= 4 {
-		padding = "5"
-	}
-	var (
-		tlsStr       = "FALSE"
-		preforkStr   = "FALSE"
-		handlerCount = strconv.Itoa(app.handlerCount)
-		osName       = utils.ToUpper(runtime.GOOS)
-		cpuThreads   = runtime.NumCPU()
-		pid          = os.Getpid()
-	)
-	if host == "" {
-		host = "0.0.0.0"
-	}
-	if tls {
-		tlsStr = "TRUE"
-	}
-	if app.Settings.Prefork {
-		preforkStr = "TRUE"
-	}
-	// tabwriter makes sure the spacing are consistent across different values
-	// colorable handles the escape sequence for stdout using ascii color codes
-	host = fmt.Sprintf("%-"+padding+"s", host)
-	port = fmt.Sprintf("%-"+padding+"s", port)
-	tlsStr = fmt.Sprintf("%-"+padding+"s", tlsStr)
-	handlerCount = fmt.Sprintf("%-"+padding+"s", handlerCount)
-
-	app.out = colorable.NewColorableStdout()
-	// Check if colors are supported
-	if os.Getenv("TERM") == "dumb" ||
-		(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) {
-		app.out = colorable.NewNonColorable(os.Stdout)
-	}
-	// simple Sprintf function that defaults back to black
-	cyan := func(v interface{}) string {
-		return fmt.Sprintf("%s%v%s", cCyan, v, cBlack)
-	}
-	// Build startup banner
-	fmt.Fprintf(app.out, logo, cBlack, cBlack,
-		cCyan, cBlack, fmt.Sprintf(" HOST     %s  OS      %s", cyan(host), cyan(osName)),
-		cCyan, cBlack, fmt.Sprintf(" PORT     %s  THREADS %s", cyan(port), cyan(cpuThreads)),
-		cCyan, cBlack, fmt.Sprintf(" TLS      %s  PREFORK %s", cyan(tlsStr), cyan(preforkStr)),
-		cBlack, cyan(Version), fmt.Sprintf(" HANDLERS %s  PID     %s%s%s\n", cyan(handlerCount), cyan(pid), pids, cReset),
-	)
-}

+ 0 - 1045
vendor/github.com/gofiber/fiber/ctx.go

@@ -1,1045 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package fiber
-
-import (
-	"bytes"
-	"context"
-	"encoding/json"
-	"encoding/xml"
-	"errors"
-	"fmt"
-	"io"
-	"log"
-	"mime/multipart"
-	"net/http"
-	"path/filepath"
-	"strconv"
-	"strings"
-	"sync"
-	"text/template"
-	"time"
-
-	utils "github.com/gofiber/utils"
-	schema "github.com/gorilla/schema"
-	bytebufferpool "github.com/valyala/bytebufferpool"
-	fasthttp "github.com/valyala/fasthttp"
-)
-
-// Ctx represents the Context which hold the HTTP request and response.
-// It has methods for the request query string, parameters, body, HTTP headers and so on.
-type Ctx struct {
-	app          *App                 // Reference to *App
-	route        *Route               // Reference to *Route
-	indexRoute   int                  // Index of the current route
-	indexHandler int                  // Index of the current handler
-	method       string               // HTTP method
-	methodINT    int                  // HTTP method INT equivalent
-	path         string               // Prettified HTTP path
-	treePath     string               // Path for the search in the tree
-	pathOriginal string               // Original HTTP path
-	values       []string             // Route parameter values
-	err          error                // Contains error if passed to Next
-	Fasthttp     *fasthttp.RequestCtx // Reference to *fasthttp.RequestCtx
-	matched      bool                 // Non use route matched
-}
-
-// Range data for ctx.Range
-type Range struct {
-	Type   string
-	Ranges []struct {
-		Start int
-		End   int
-	}
-}
-
-// Cookie data for ctx.Cookie
-type Cookie struct {
-	Name     string    `json:"name"`
-	Value    string    `json:"value"`
-	Path     string    `json:"path"`
-	Domain   string    `json:"domain"`
-	Expires  time.Time `json:"expires"`
-	Secure   bool      `json:"secure"`
-	HTTPOnly bool      `json:"http_only"`
-	SameSite string    `json:"same_site"`
-}
-
-// Views is the interface that wraps the Render function.
-type Views interface {
-	Load() error
-	Render(io.Writer, string, interface{}, ...string) error
-}
-
-// AcquireCtx retrieves a new Ctx from the pool.
-func (app *App) AcquireCtx(fctx *fasthttp.RequestCtx) *Ctx {
-	ctx := app.pool.Get().(*Ctx)
-	// Set app reference
-	ctx.app = app
-	// Reset route and handler index
-	ctx.indexRoute = -1
-	ctx.indexHandler = 0
-	// Reset matched flag
-	ctx.matched = false
-	// Set paths
-	ctx.path = getString(fctx.URI().PathOriginal())
-	ctx.pathOriginal = ctx.path
-	// Set method
-	ctx.method = getString(fctx.Request.Header.Method())
-	ctx.methodINT = methodInt(ctx.method)
-	// Attach *fasthttp.RequestCtx to ctx
-	ctx.Fasthttp = fctx
-	// Prettify path
-	ctx.prettifyPath()
-	return ctx
-}
-
-// ReleaseCtx releases the ctx back into the pool.
-func (app *App) ReleaseCtx(ctx *Ctx) {
-	// Reset values
-	ctx.route = nil
-	ctx.values = nil
-	ctx.Fasthttp = nil
-	ctx.err = nil
-	app.pool.Put(ctx)
-}
-
-// Accepts checks if the specified extensions or content types are acceptable.
-func (ctx *Ctx) Accepts(offers ...string) string {
-	if len(offers) == 0 {
-		return ""
-	}
-	header := ctx.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 = header
-		}
-		if factorSign := strings.IndexByte(spec, ';'); factorSign != -1 {
-			spec = spec[:factorSign]
-		}
-
-		for _, offer := range offers {
-			mimetype := utils.GetMIME(offer)
-			if len(spec) > 2 && spec[len(spec)-2:] == "/*" {
-				if strings.HasPrefix(spec[:len(spec)-2], strings.Split(mimetype, "/")[0]) {
-					return offer
-				} else if spec == "*/*" {
-					return offer
-				}
-			} else if strings.HasPrefix(spec, mimetype) {
-				return offer
-			}
-		}
-		if commaPos != -1 {
-			header = header[commaPos+1:]
-		}
-	}
-
-	return ""
-}
-
-// AcceptsCharsets checks if the specified charset is acceptable.
-func (ctx *Ctx) AcceptsCharsets(offers ...string) string {
-	return getOffer(ctx.Get(HeaderAcceptCharset), offers...)
-}
-
-// AcceptsEncodings checks if the specified encoding is acceptable.
-func (ctx *Ctx) AcceptsEncodings(offers ...string) string {
-	return getOffer(ctx.Get(HeaderAcceptEncoding), offers...)
-}
-
-// AcceptsLanguages checks if the specified language is acceptable.
-func (ctx *Ctx) AcceptsLanguages(offers ...string) string {
-	return getOffer(ctx.Get(HeaderAcceptLanguage), offers...)
-}
-
-// App returns the *App reference to access Settings or ErrorHandler
-func (ctx *Ctx) App() *App {
-	return ctx.app
-}
-
-// Append the specified value to the HTTP response header field.
-// If the header is not already set, it creates the header with the specified value.
-func (ctx *Ctx) Append(field string, values ...string) {
-	if len(values) == 0 {
-		return
-	}
-	h := getString(ctx.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 {
-		ctx.Set(field, h)
-	}
-}
-
-// Attachment sets the HTTP response Content-Disposition header field to attachment.
-func (ctx *Ctx) Attachment(filename ...string) {
-	if len(filename) > 0 {
-		fname := filepath.Base(filename[0])
-		ctx.Type(filepath.Ext(fname))
-
-		ctx.Set(HeaderContentDisposition, `attachment; filename="`+quoteString(fname)+`"`)
-		return
-	}
-	ctx.Set(HeaderContentDisposition, "attachment")
-}
-
-// BaseURL returns (protocol + host + base path).
-func (ctx *Ctx) BaseURL() string {
-	// TODO: Could be improved: 53.8 ns/op  32 B/op  1 allocs/op
-	// Should work like https://codeigniter.com/user_guide/helpers/url_helper.html
-	return ctx.Protocol() + "://" + ctx.Hostname()
-}
-
-// Body contains the raw body submitted in a POST request.
-// Returned value is only valid within the handler. Do not store any references.
-// Make copies or use the Immutable setting instead.
-func (ctx *Ctx) Body() string {
-	return getString(ctx.Fasthttp.Request.Body())
-}
-
-// decoderPool helps to improve BodyParser's and QueryParser's performance
-var decoderPool = &sync.Pool{New: func() interface{} {
-	var decoder = schema.NewDecoder()
-	decoder.IgnoreUnknownKeys(true)
-	return decoder
-}}
-
-// BodyParser binds the request body to a struct.
-// It supports decoding the following content types based on the Content-Type header:
-// application/json, application/xml, application/x-www-form-urlencoded, multipart/form-data
-func (ctx *Ctx) BodyParser(out interface{}) error {
-	// Get decoder from pool
-	schemaDecoder := decoderPool.Get().(*schema.Decoder)
-	defer decoderPool.Put(schemaDecoder)
-
-	// Get content-type
-	ctype := getString(ctx.Fasthttp.Request.Header.ContentType())
-
-	// Parse body accordingly
-	if strings.HasPrefix(ctype, MIMEApplicationJSON) {
-		schemaDecoder.SetAliasTag("json")
-		return json.Unmarshal(ctx.Fasthttp.Request.Body(), out)
-	} else if strings.HasPrefix(ctype, MIMEApplicationForm) {
-		schemaDecoder.SetAliasTag("form")
-		data := make(map[string][]string)
-		ctx.Fasthttp.PostArgs().VisitAll(func(key []byte, val []byte) {
-			data[getString(key)] = append(data[getString(key)], getString(val))
-		})
-		return schemaDecoder.Decode(out, data)
-	} else if strings.HasPrefix(ctype, MIMEMultipartForm) {
-		schemaDecoder.SetAliasTag("form")
-		data, err := ctx.Fasthttp.MultipartForm()
-		if err != nil {
-			return err
-		}
-		return schemaDecoder.Decode(out, data.Value)
-	} else if strings.HasPrefix(ctype, MIMETextXML) || strings.HasPrefix(ctype, MIMEApplicationXML) {
-		schemaDecoder.SetAliasTag("xml")
-		return xml.Unmarshal(ctx.Fasthttp.Request.Body(), out)
-	}
-
-	// Query params in BodyParser is deprecated
-	if ctx.Fasthttp.QueryArgs().Len() > 0 {
-		fmt.Println("bodyparser: parsing query strings is deprecated since v1.12.7, please use `ctx.QueryParser` instead")
-		return ctx.QueryParser(out)
-	}
-
-	// No suitable content type found
-	return fmt.Errorf("bodyparser: cannot parse content-type: %v", ctype)
-}
-
-// QueryParser binds the query string to a struct.
-func (ctx *Ctx) QueryParser(out interface{}) error {
-	if ctx.Fasthttp.QueryArgs().Len() < 1 {
-		return nil
-	}
-	// Get decoder from pool
-	var decoder = decoderPool.Get().(*schema.Decoder)
-	defer decoderPool.Put(decoder)
-
-	// Set correct alias tag
-	decoder.SetAliasTag("query")
-
-	data := make(map[string][]string)
-	ctx.Fasthttp.QueryArgs().VisitAll(func(key []byte, val []byte) {
-		data[getString(key)] = append(data[getString(key)], getString(val))
-	})
-
-	return decoder.Decode(out, data)
-}
-
-// 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.
-func (ctx *Ctx) ClearCookie(key ...string) {
-	if len(key) > 0 {
-		for i := range key {
-			ctx.Fasthttp.Response.Header.DelClientCookie(key[i])
-		}
-		return
-	}
-	ctx.Fasthttp.Request.Header.VisitAllCookie(func(k, v []byte) {
-		ctx.Fasthttp.Response.Header.DelClientCookieBytes(k)
-	})
-}
-
-// Context returns context.Context that carries a deadline, a cancellation signal,
-// and other values across API boundaries.
-func (ctx *Ctx) Context() context.Context {
-	return ctx.Fasthttp
-}
-
-// Cookie sets a cookie by passing a cookie struct.
-func (ctx *Ctx) Cookie(cookie *Cookie) {
-	fcookie := fasthttp.AcquireCookie()
-	fcookie.SetKey(cookie.Name)
-	fcookie.SetValue(cookie.Value)
-	fcookie.SetPath(cookie.Path)
-	fcookie.SetDomain(cookie.Domain)
-	fcookie.SetExpire(cookie.Expires)
-	fcookie.SetSecure(cookie.Secure)
-	fcookie.SetHTTPOnly(cookie.HTTPOnly)
-
-	switch utils.ToLower(cookie.SameSite) {
-	case "strict":
-		fcookie.SetSameSite(fasthttp.CookieSameSiteStrictMode)
-	case "none":
-		fcookie.SetSameSite(fasthttp.CookieSameSiteNoneMode)
-	default:
-		fcookie.SetSameSite(fasthttp.CookieSameSiteLaxMode)
-	}
-
-	ctx.Fasthttp.Response.Header.SetCookie(fcookie)
-	fasthttp.ReleaseCookie(fcookie)
-}
-
-// Cookies is used for getting a cookie value by key.
-// Defaults to the empty string "" if the cookie doesn't exist.
-// If a default value is given, it will return that value if the cookie doesn't exist.
-// The returned value is only valid within the handler. Do not store any references.
-// Make copies or use the Immutable setting to use the value outside the Handler.
-func (ctx *Ctx) Cookies(key string, defaultValue ...string) string {
-	return defaultString(getString(ctx.Fasthttp.Request.Header.Cookie(key)), defaultValue)
-}
-
-// Download transfers the file from path as an attachment.
-// Typically, browsers will prompt the user for download.
-// By default, the Content-Disposition header filename= parameter is the filepath (this typically appears in the browser dialog).
-// Override this default with the filename parameter.
-func (ctx *Ctx) Download(file string, filename ...string) error {
-	fname := filepath.Base(file)
-	if len(filename) > 0 {
-		fname = filename[0]
-	}
-	ctx.Set(HeaderContentDisposition, `attachment; filename="`+quoteString(fname)+`"`)
-	return ctx.SendFile(file)
-}
-
-// Error contains the error information passed via the Next(err) method.
-func (ctx *Ctx) Error() error {
-	return ctx.err
-}
-
-// Format performs content-negotiation on the Accept HTTP header.
-// It uses Accepts to select a proper format.
-// If the header is not specified or there is no proper format, text/plain is used.
-func (ctx *Ctx) Format(body interface{}) {
-	// Get accepted content type
-	accept := ctx.Accepts("html", "json", "txt", "xml")
-	// Set accepted content type
-	ctx.Type(accept)
-
-	// Type convert provided body
-	var b string
-	switch val := body.(type) {
-	case string:
-		b = val
-	case []byte:
-		b = getString(val)
-	default:
-		b = fmt.Sprintf("%v", val)
-	}
-
-	// Format based on the accept content type
-	switch accept {
-	case "html":
-		ctx.SendString("<p>" + b + "</p>")
-	case "json":
-		if err := ctx.JSON(body); err != nil {
-			ctx.Send(body) // Fallback
-			log.Println("Format: error serializing json ", err)
-		}
-	case "txt":
-		ctx.SendString(b)
-	case "xml":
-		raw, err := xml.Marshal(body)
-		if err != nil {
-			ctx.Send(body) // Fallback
-			log.Println("Format: error serializing xml ", err)
-		} else {
-			ctx.Fasthttp.Response.SetBodyRaw(raw)
-		}
-	default:
-		ctx.SendString(b)
-	}
-}
-
-// FormFile returns the first file by key from a MultipartForm.
-func (ctx *Ctx) FormFile(key string) (*multipart.FileHeader, error) {
-	return ctx.Fasthttp.FormFile(key)
-}
-
-// FormValue returns the first value by key from a MultipartForm.
-// Returned value is only valid within the handler. Do not store any references.
-// Make copies or use the Immutable setting instead.
-func (ctx *Ctx) FormValue(key string) (value string) {
-	return getString(ctx.Fasthttp.FormValue(key))
-}
-
-// Fresh returns true when the response is still “fresh” in the client's cache,
-// otherwise false is returned to indicate that the client cache is now stale
-// and the full response should be sent.
-// When a client sends the Cache-Control: no-cache request header to indicate an end-to-end
-// reload request, this module will return false to make handling these requests transparent.
-// https://github.com/jshttp/fresh/blob/10e0471669dbbfbfd8de65bc6efac2ddd0bfa057/index.js#L33
-func (ctx *Ctx) Fresh() bool {
-	// fields
-	var modifiedSince = ctx.Get(HeaderIfModifiedSince)
-	var noneMatch = ctx.Get(HeaderIfNoneMatch)
-
-	// unconditional request
-	if modifiedSince == "" && noneMatch == "" {
-		return false
-	}
-
-	// Always return stale when Cache-Control: no-cache
-	// to support end-to-end reload requests
-	// https://tools.ietf.org/html/rfc2616#section-14.9.4
-	cacheControl := ctx.Get(HeaderCacheControl)
-	if cacheControl != "" && isNoCache(cacheControl) {
-		return false
-	}
-
-	// if-none-match
-	if noneMatch != "" && noneMatch != "*" {
-		var etag = getString(ctx.Fasthttp.Response.Header.Peek(HeaderETag))
-		if etag == "" {
-			return false
-		}
-		if isEtagStale(etag, getBytes(noneMatch)) {
-			return false
-		}
-
-		if modifiedSince != "" {
-			var lastModified = getString(ctx.Fasthttp.Response.Header.Peek(HeaderLastModified))
-			if lastModified != "" {
-				lastModifiedTime, err := http.ParseTime(lastModified)
-				if err != nil {
-					return false
-				}
-				modifiedSinceTime, err := http.ParseTime(modifiedSince)
-				if err != nil {
-					return false
-				}
-				return lastModifiedTime.Before(modifiedSinceTime)
-			}
-		}
-	}
-	return true
-}
-
-// Get returns the HTTP request header specified by field.
-// Field names are case-insensitive
-// Returned value is only valid within the handler. Do not store any references.
-// Make copies or use the Immutable setting instead.
-func (ctx *Ctx) Get(key string, defaultValue ...string) string {
-	return defaultString(getString(ctx.Fasthttp.Request.Header.Peek(key)), defaultValue)
-}
-
-// Hostname contains the hostname derived from the Host HTTP header.
-// Returned value is only valid within the handler. Do not store any references.
-// Make copies or use the Immutable setting instead.
-func (ctx *Ctx) Hostname() string {
-	return getString(ctx.Fasthttp.URI().Host())
-}
-
-// IP returns the remote IP address of the request.
-func (ctx *Ctx) IP() string {
-	return ctx.Fasthttp.RemoteIP().String()
-}
-
-// IPs returns an string slice of IP addresses specified in the X-Forwarded-For request header.
-func (ctx *Ctx) IPs() (ips []string) {
-	header := ctx.Fasthttp.Request.Header.Peek(HeaderXForwardedFor)
-	if len(header) == 0 {
-		return
-	}
-	ips = make([]string, bytes.Count(header, []byte(","))+1)
-	var commaPos, i int
-	for {
-		commaPos = bytes.IndexByte(header, ',')
-		if commaPos != -1 {
-			ips[i] = getString(header[:commaPos])
-			header, i = header[commaPos+2:], i+1
-		} else {
-			ips[i] = getString(header)
-			return
-		}
-	}
-}
-
-// Is returns the matching content type,
-// if the incoming request's Content-Type HTTP header field matches the MIME type specified by the type parameter
-func (ctx *Ctx) Is(extension string) bool {
-	extensionHeader := utils.GetMIME(extension)
-	if extensionHeader == "" {
-		return false
-	}
-
-	return strings.HasPrefix(
-		utils.TrimLeft(utils.GetString(ctx.Fasthttp.Request.Header.ContentType()), ' '),
-		extensionHeader,
-	)
-}
-
-// JSON converts any interface or string to JSON.
-// This method also sets the content header to application/json.
-func (ctx *Ctx) JSON(data interface{}) error {
-	raw, err := json.Marshal(data)
-	// Check for errors
-	if err != nil {
-		return err
-	}
-	// Set http headers
-	ctx.Fasthttp.Response.Header.SetContentType(MIMEApplicationJSON)
-	ctx.Fasthttp.Response.SetBodyRaw(raw)
-
-	return nil
-}
-
-// JSONP sends a JSON response with JSONP support.
-// This method is identical to JSON, except that it opts-in to JSONP callback support.
-// By default, the callback name is simply callback.
-func (ctx *Ctx) JSONP(data interface{}, callback ...string) error {
-	raw, err := json.Marshal(data)
-
-	if err != nil {
-		return err
-	}
-
-	var result, cb string
-
-	if len(callback) > 0 {
-		cb = callback[0]
-	} else {
-		cb = "callback"
-	}
-
-	result = cb + "(" + getString(raw) + ");"
-
-	ctx.Set(HeaderXContentTypeOptions, "nosniff")
-	ctx.Fasthttp.Response.Header.SetContentType(MIMEApplicationJavaScriptCharsetUTF8)
-	ctx.SendString(result)
-
-	return nil
-}
-
-// Links joins the links followed by the property to populate the response's Link HTTP header field.
-func (ctx *Ctx) Links(link ...string) {
-	if len(link) == 0 {
-		return
-	}
-	bb := bytebufferpool.Get()
-	for i := range link {
-		if i%2 == 0 {
-			_ = bb.WriteByte('<')
-			_, _ = bb.WriteString(link[i])
-			_ = bb.WriteByte('>')
-		} else {
-			_, _ = bb.WriteString(`; rel="` + link[i] + `",`)
-		}
-	}
-	ctx.Set(HeaderLink, utils.TrimRight(getString(bb.Bytes()), ','))
-	bytebufferpool.Put(bb)
-}
-
-// Locals makes it possible to pass interface{} values under string keys scoped to the request
-// and therefore available to all following routes that match the request.
-func (ctx *Ctx) Locals(key string, value ...interface{}) (val interface{}) {
-	if len(value) == 0 {
-		return ctx.Fasthttp.UserValue(key)
-	}
-	ctx.Fasthttp.SetUserValue(key, value[0])
-	return value[0]
-}
-
-// Location sets the response Location HTTP header to the specified path parameter.
-func (ctx *Ctx) Location(path string) {
-	ctx.Set(HeaderLocation, path)
-}
-
-// Method contains a string corresponding to the HTTP method of the request: GET, POST, PUT and so on.
-func (ctx *Ctx) Method(override ...string) string {
-	if len(override) > 0 {
-		method := utils.ToUpper(override[0])
-		mINT := methodInt(method)
-		if mINT == -1 {
-			return ctx.method
-		}
-		ctx.method = method
-		ctx.methodINT = mINT
-	}
-	return ctx.method
-}
-
-// MultipartForm parse form entries from binary.
-// This returns a map[string][]string, so given a key the value will be a string slice.
-func (ctx *Ctx) MultipartForm() (*multipart.Form, error) {
-	return ctx.Fasthttp.MultipartForm()
-}
-
-// Next executes the next method in the stack that matches the current route.
-// You can pass an optional error for custom error handling.
-func (ctx *Ctx) Next(err ...error) {
-	if len(err) > 0 {
-		ctx.err = err[0]
-		ctx.app.Settings.ErrorHandler(ctx, ctx.err)
-		return
-	}
-
-	// Increment handler index
-	ctx.indexHandler++
-	// Did we executed all route handlers?
-	if ctx.indexHandler < len(ctx.route.Handlers) {
-		// Continue route stack
-		ctx.route.Handlers[ctx.indexHandler](ctx)
-	} else {
-		// Continue handler stack
-		ctx.app.next(ctx)
-	}
-}
-
-// OriginalURL contains the original request URL.
-// Returned value is only valid within the handler. Do not store any references.
-// Make copies or use the Immutable setting to use the value outside the Handler.
-func (ctx *Ctx) OriginalURL() string {
-	return getString(ctx.Fasthttp.Request.Header.RequestURI())
-}
-
-// Params is used to get the route parameters.
-// Defaults to empty string "" if the param doesn't exist.
-// If a default value is given, it will return that value if the param doesn't exist.
-// Returned value is only valid within the handler. Do not store any references.
-// Make copies or use the Immutable setting to use the value outside the Handler.
-func (ctx *Ctx) Params(key string, defaultValue ...string) string {
-	if key == "*" || key == "+" {
-		key += "1"
-	}
-	for i := range ctx.route.Params {
-		if len(key) != len(ctx.route.Params[i]) {
-			continue
-		}
-		if ctx.route.Params[i] == key {
-			// in case values are not here
-			if len(ctx.values) <= i || len(ctx.values[i]) == 0 {
-				break
-			}
-			return ctx.values[i]
-		}
-	}
-	return defaultString("", defaultValue)
-}
-
-// Path returns the path part of the request URL.
-// Optionally, you could override the path.
-func (ctx *Ctx) Path(override ...string) string {
-	if len(override) != 0 && ctx.path != override[0] {
-		// Set new path to context
-		ctx.path = override[0]
-		ctx.pathOriginal = ctx.path
-		// Set new path to request context
-		ctx.Fasthttp.Request.URI().SetPath(ctx.pathOriginal)
-		// Prettify path
-		ctx.prettifyPath()
-	}
-	return ctx.pathOriginal
-}
-
-// Protocol contains the request protocol string: http or https for TLS requests.
-func (ctx *Ctx) Protocol() string {
-	if ctx.Fasthttp.IsTLS() {
-		return "https"
-	}
-	scheme := "http"
-	ctx.Fasthttp.Request.Header.VisitAll(func(key, val []byte) {
-		if len(key) < 12 {
-			return // X-Forwarded-
-		} else if bytes.HasPrefix(key, []byte("X-Forwarded-")) {
-			if bytes.Equal(key, []byte(HeaderXForwardedProto)) {
-				scheme = getString(val)
-			} else if bytes.Equal(key, []byte(HeaderXForwardedProtocol)) {
-				scheme = getString(val)
-			} else if bytes.Equal(key, []byte(HeaderXForwardedSsl)) && bytes.Equal(val, []byte("on")) {
-				scheme = "https"
-			}
-		} else if bytes.Equal(key, []byte(HeaderXUrlScheme)) {
-			scheme = getString(val)
-		}
-	})
-	return scheme
-}
-
-// Query returns the query string parameter in the url.
-// Defaults to empty string "" if the query doesn't exist.
-// If a default value is given, it will return that value if the query doesn't exist.
-// Returned value is only valid within the handler. Do not store any references.
-// Make copies or use the Immutable setting to use the value outside the Handler.
-func (ctx *Ctx) Query(key string, defaultValue ...string) string {
-	return defaultString(getString(ctx.Fasthttp.QueryArgs().Peek(key)), defaultValue)
-}
-
-var (
-	ErrRangeMalformed     = errors.New("range: malformed range header string")
-	ErrRangeUnsatisfiable = errors.New("range: unsatisfiable range")
-)
-
-// Range returns a struct containing the type and a slice of ranges.
-func (ctx *Ctx) Range(size int) (rangeData Range, err error) {
-	rangeStr := ctx.Get(HeaderRange)
-	if rangeStr == "" || !strings.Contains(rangeStr, "=") {
-		err = ErrRangeMalformed
-		return
-	}
-	data := strings.Split(rangeStr, "=")
-	if len(data) != 2 {
-		err = ErrRangeMalformed
-		return
-	}
-	rangeData.Type = data[0]
-	arr := strings.Split(data[1], ",")
-	for i := 0; i < len(arr); i++ {
-		item := strings.Split(arr[i], "-")
-		if len(item) == 1 {
-			err = ErrRangeMalformed
-			return
-		}
-		start, startErr := strconv.Atoi(item[0])
-		end, endErr := strconv.Atoi(item[1])
-		if startErr != nil { // -nnn
-			start = size - end
-			end = size - 1
-		} else if endErr != nil { // nnn-
-			end = size - 1
-		}
-		if end > size-1 { // limit last-byte-pos to current length
-			end = size - 1
-		}
-		if start > end || start < 0 {
-			continue
-		}
-		rangeData.Ranges = append(rangeData.Ranges, struct {
-			Start int
-			End   int
-		}{
-			start,
-			end,
-		})
-	}
-	if len(rangeData.Ranges) < 1 {
-		err = ErrRangeUnsatisfiable
-		return
-	}
-
-	return
-}
-
-// Redirect to the URL derived from the specified path, with specified status.
-// If status is not specified, status defaults to 302 Found.
-func (ctx *Ctx) Redirect(location string, status ...int) {
-	ctx.Set(HeaderLocation, location)
-	if len(status) > 0 {
-		ctx.Status(status[0])
-	} else {
-		ctx.Status(StatusFound)
-	}
-}
-
-// Render a template with data and sends a text/html response.
-// We support the following engines: html, amber, handlebars, mustache, pug
-func (ctx *Ctx) Render(name string, bind interface{}, layouts ...string) (err error) {
-	// Get new buffer from pool
-	buf := bytebufferpool.Get()
-	defer bytebufferpool.Put(buf)
-
-	if ctx.app.Settings.Views != nil {
-		// Render template from Views
-		if err := ctx.app.Settings.Views.Render(buf, name, bind, layouts...); err != nil {
-			return err
-		}
-	} else {
-		// Render raw template using 'name' as filepath if no engine is set
-		var tmpl *template.Template
-		if _, err = readContent(buf, name); err != nil {
-			return err
-		}
-		// Parse template
-		if tmpl, err = template.New("").Parse(getString(buf.Bytes())); err != nil {
-			return err
-		}
-		buf.Reset()
-		// Render template
-		if err = tmpl.Execute(buf, bind); err != nil {
-			return err
-		}
-	}
-	// Set Content-Type to text/html
-	ctx.Fasthttp.Response.Header.SetContentType(MIMETextHTMLCharsetUTF8)
-	// Set rendered template to body
-	ctx.Fasthttp.Response.SetBody(buf.Bytes())
-	// Return err if exist
-	return
-}
-
-// Route returns the matched Route struct.
-func (ctx *Ctx) Route() *Route {
-	if ctx.route == nil {
-		// Fallback for fasthttp error handler
-		return &Route{
-			path:     ctx.pathOriginal,
-			Path:     ctx.pathOriginal,
-			Method:   ctx.method,
-			Handlers: make([]Handler, 0),
-		}
-	}
-	return ctx.route
-}
-
-// SaveFile saves any multipart file to disk.
-func (ctx *Ctx) SaveFile(fileheader *multipart.FileHeader, path string) error {
-	return fasthttp.SaveMultipartFile(fileheader, path)
-}
-
-// Secure returns a boolean property, that is true, if a TLS connection is established.
-func (ctx *Ctx) Secure() bool {
-	return ctx.Fasthttp.IsTLS()
-}
-
-// Send sets the HTTP response body. The input can be of any type, io.Reader is also supported.
-func (ctx *Ctx) Send(bodies ...interface{}) {
-	// Reset response body
-	ctx.SendString("")
-	// Write response body
-	ctx.Write(bodies...)
-}
-
-// SendBytes sets the HTTP response body for []byte types without copying it.
-// From this point onward the body argument must not be changed.
-func (ctx *Ctx) SendBytes(body []byte) {
-	ctx.Fasthttp.Response.SetBodyRaw(body)
-}
-
-var fsOnce sync.Once
-var sendFileFS *fasthttp.FS
-var sendFileHandler fasthttp.RequestHandler
-
-// SendFile transfers the file from the given path.
-// The file is not compressed by default, enable this by passing a 'true' argument
-// Sets the Content-Type response HTTP header field based on the filenames extension.
-func (ctx *Ctx) SendFile(file string, compress ...bool) error {
-	// https://github.com/valyala/fasthttp/blob/master/fs.go#L81
-	fsOnce.Do(func() {
-		sendFileFS = &fasthttp.FS{
-			Root:                 "/",
-			GenerateIndexPages:   false,
-			AcceptByteRange:      true,
-			Compress:             true,
-			CompressedFileSuffix: ctx.app.Settings.CompressedFileSuffix,
-			CacheDuration:        10 * time.Second,
-			IndexNames:           []string{"index.html"},
-			PathNotFound: func(ctx *fasthttp.RequestCtx) {
-				ctx.Response.SetStatusCode(StatusNotFound)
-			},
-		}
-		sendFileHandler = sendFileFS.NewRequestHandler()
-	})
-
-	// Keep original path for mutable params
-	ctx.pathOriginal = utils.ImmutableString(ctx.pathOriginal)
-	// Disable compression
-	if len(compress) <= 0 || !compress[0] {
-		// https://github.com/valyala/fasthttp/blob/master/fs.go#L46
-		ctx.Fasthttp.Request.Header.Del(HeaderAcceptEncoding)
-	}
-	// https://github.com/valyala/fasthttp/blob/master/fs.go#L85
-	if len(file) == 0 || file[0] != '/' {
-		hasTrailingSlash := len(file) > 0 && file[len(file)-1] == '/'
-		var err error
-		if file, err = filepath.Abs(file); err != nil {
-			return err
-		}
-		if hasTrailingSlash {
-			file += "/"
-		}
-	}
-	// Set new URI for fileHandler
-	ctx.Fasthttp.Request.SetRequestURI(file)
-	// Save status code
-	status := ctx.Fasthttp.Response.StatusCode()
-	// Serve file
-	sendFileHandler(ctx.Fasthttp)
-	// Get the status code which is set by fasthttp
-	fsStatus := ctx.Fasthttp.Response.StatusCode()
-	// Set the status code set by the user if it is different from the fasthttp status code and 200
-	if status != fsStatus && status != StatusOK {
-		ctx.Status(status)
-	}
-	// Check for error
-	if status != StatusNotFound && fsStatus == StatusNotFound {
-		return fmt.Errorf("sendfile: file %s not found", file)
-	}
-	return nil
-}
-
-// SendStatus sets the HTTP status code and if the response body is empty,
-// it sets the correct status message in the body.
-func (ctx *Ctx) SendStatus(status int) {
-	ctx.Status(status)
-	// Only set status body when there is no response body
-	if len(ctx.Fasthttp.Response.Body()) == 0 {
-		ctx.SendString(utils.StatusMessage(status))
-	}
-}
-
-// SendString sets the HTTP response body for string types.
-// This means no type assertion, recommended for faster performance
-func (ctx *Ctx) SendString(body string) {
-	ctx.Fasthttp.Response.SetBodyString(body)
-}
-
-// SendStream sets response body stream and optional body size.
-func (ctx *Ctx) SendStream(stream io.Reader, size ...int) {
-	if len(size) > 0 && size[0] >= 0 {
-		ctx.Fasthttp.Response.SetBodyStream(stream, size[0])
-	} else {
-		ctx.Fasthttp.Response.SetBodyStream(stream, -1)
-		ctx.Set(HeaderContentLength, strconv.Itoa(len(ctx.Fasthttp.Response.Body())))
-	}
-}
-
-// Set sets the response's HTTP header field to the specified key, value.
-func (ctx *Ctx) Set(key string, val string) {
-	ctx.Fasthttp.Response.Header.Set(key, val)
-}
-
-// Subdomains returns a string slice of subdomains in the domain name of the request.
-// The subdomain offset, which defaults to 2, is used for determining the beginning of the subdomain segments.
-func (ctx *Ctx) Subdomains(offset ...int) []string {
-	o := 2
-	if len(offset) > 0 {
-		o = offset[0]
-	}
-	subdomains := strings.Split(ctx.Hostname(), ".")
-	l := len(subdomains) - o
-	// Check index to avoid slice bounds out of range panic
-	if l < 0 {
-		l = len(subdomains)
-	}
-	subdomains = subdomains[:l]
-	return subdomains
-}
-
-// Stale is not implemented yet, pull requests are welcome!
-func (ctx *Ctx) Stale() bool {
-	return !ctx.Fresh()
-}
-
-// Status sets the HTTP status for the response.
-// This method is chainable.
-func (ctx *Ctx) Status(status int) *Ctx {
-	ctx.Fasthttp.Response.SetStatusCode(status)
-	return ctx
-}
-
-// Type sets the Content-Type HTTP header to the MIME type specified by the file extension.
-func (ctx *Ctx) Type(extension string, charset ...string) *Ctx {
-	if len(charset) > 0 {
-		ctx.Fasthttp.Response.Header.SetContentType(utils.GetMIME(extension) + "; charset=" + charset[0])
-	} else {
-		ctx.Fasthttp.Response.Header.SetContentType(utils.GetMIME(extension))
-	}
-	return ctx
-}
-
-// Vary adds the given header field to the Vary response header.
-// This will append the header, if not already listed, otherwise leaves it listed in the current location.
-func (ctx *Ctx) Vary(fields ...string) {
-	ctx.Append(HeaderVary, fields...)
-}
-
-// Write appends any input to the HTTP body response, io.Reader is also supported as input.
-func (ctx *Ctx) Write(bodies ...interface{}) {
-	for i := range bodies {
-		switch body := bodies[i].(type) {
-		case string:
-			ctx.Fasthttp.Response.AppendBodyString(body)
-		case []byte:
-			ctx.Fasthttp.Response.AppendBodyString(getString(body))
-		case int:
-			ctx.Fasthttp.Response.AppendBodyString(strconv.Itoa(body))
-		case bool:
-			ctx.Fasthttp.Response.AppendBodyString(strconv.FormatBool(body))
-		case io.Reader:
-			ctx.Fasthttp.Response.SetBodyStream(body, -1)
-			ctx.Set(HeaderContentLength, strconv.Itoa(len(ctx.Fasthttp.Response.Body())))
-		default:
-			ctx.Fasthttp.Response.AppendBodyString(fmt.Sprintf("%v", body))
-		}
-	}
-}
-
-// XHR returns a Boolean property, that is true, if the request's X-Requested-With header field is XMLHttpRequest,
-// indicating that the request was issued by a client library (such as jQuery).
-func (ctx *Ctx) XHR() bool {
-	return strings.EqualFold(ctx.Get(HeaderXRequestedWith), "xmlhttprequest")
-}
-
-// prettifyPath ...
-func (ctx *Ctx) prettifyPath() {
-	// If UnescapePath enabled, we decode the path
-	if ctx.app.Settings.UnescapePath {
-		pathBytes := getBytes(ctx.path)
-		pathBytes = fasthttp.AppendUnquotedArg(pathBytes[:0], pathBytes)
-		ctx.path = getString(pathBytes)
-	}
-	// If CaseSensitive is disabled, we lowercase the original path
-	if !ctx.app.Settings.CaseSensitive {
-		// We are making a copy here to keep access to the original path
-		ctx.path = utils.ToLower(ctx.path)
-	}
-	// If StrictRouting is disabled, we strip all trailing slashes
-	if !ctx.app.Settings.StrictRouting && len(ctx.path) > 1 && ctx.path[len(ctx.path)-1] == '/' {
-		ctx.path = utils.TrimRight(ctx.path, '/')
-	}
-
-	ctx.treePath = ctx.treePath[0:0]
-	if len(ctx.path) >= 3 {
-		ctx.treePath = ctx.path[:3]
-	}
-}

+ 0 - 126
vendor/github.com/gofiber/fiber/group.go

@@ -1,126 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package fiber
-
-import (
-	"fmt"
-	"reflect"
-)
-
-// Group struct
-type Group struct {
-	app    *App
-	prefix string
-}
-
-// Use registers a middleware route.
-// Middleware matches requests beginning with the provided prefix.
-// Providing a prefix is optional, it defaults to "/".
-//
-// - group.Use(handler)
-// - group.Use("/api", handler)
-// - group.Use("/api", handler, handler)
-func (grp *Group) Use(args ...interface{}) Router {
-	var path = ""
-	var handlers []Handler
-	for i := 0; i < len(args); i++ {
-		switch arg := args[i].(type) {
-		case string:
-			path = arg
-		case Handler:
-			handlers = append(handlers, arg)
-		default:
-			panic(fmt.Sprintf("use: invalid handler %v\n", reflect.TypeOf(arg)))
-		}
-	}
-	grp.app.register(methodUse, getGroupPath(grp.prefix, path), handlers...)
-	return grp
-}
-
-// Get registers a route for GET methods that requests a representation
-// of the specified resource. Requests using GET should only retrieve data.
-func (grp *Group) Get(path string, handlers ...Handler) Router {
-	route := grp.app.register(MethodGet, getGroupPath(grp.prefix, path), handlers...)
-	// Add head route
-	headRoute := route
-	grp.app.addRoute(MethodHead, &headRoute)
-	return grp
-}
-
-// Head registers a route for HEAD methods that asks for a response identical
-// to that of a GET request, but without the response body.
-func (grp *Group) Head(path string, handlers ...Handler) Router {
-	return grp.Add(MethodHead, path, handlers...)
-}
-
-// Post registers a route for POST methods that is used to submit an entity to the
-// specified resource, often causing a change in state or side effects on the server.
-func (grp *Group) Post(path string, handlers ...Handler) Router {
-	return grp.Add(MethodPost, path, handlers...)
-}
-
-// Put registers a route for PUT methods that replaces all current representations
-// of the target resource with the request payload.
-func (grp *Group) Put(path string, handlers ...Handler) Router {
-	return grp.Add(MethodPut, path, handlers...)
-}
-
-// Delete registers a route for DELETE methods that deletes the specified resource.
-func (grp *Group) Delete(path string, handlers ...Handler) Router {
-	return grp.Add(MethodDelete, path, handlers...)
-}
-
-// Connect registers a route for CONNECT methods that establishes a tunnel to the
-// server identified by the target resource.
-func (grp *Group) Connect(path string, handlers ...Handler) Router {
-	return grp.Add(MethodConnect, path, handlers...)
-}
-
-// Options registers a route for OPTIONS methods that is used to describe the
-// communication options for the target resource.
-func (grp *Group) Options(path string, handlers ...Handler) Router {
-	return grp.Add(MethodOptions, path, handlers...)
-}
-
-// Trace registers a route for TRACE methods that performs a message loop-back
-// test along the path to the target resource.
-func (grp *Group) Trace(path string, handlers ...Handler) Router {
-	return grp.Add(MethodTrace, path, handlers...)
-}
-
-// Patch registers a route for PATCH methods that is used to apply partial
-// modifications to a resource.
-func (grp *Group) Patch(path string, handlers ...Handler) Router {
-	return grp.Add(MethodPatch, path, handlers...)
-}
-
-// Add ...
-func (grp *Group) Add(method, path string, handlers ...Handler) Router {
-	grp.app.register(method, getGroupPath(grp.prefix, path), handlers...)
-	return grp
-}
-
-// Static ...
-func (grp *Group) Static(prefix, root string, config ...Static) Router {
-	grp.app.registerStatic(getGroupPath(grp.prefix, prefix), root, config...)
-	return grp
-}
-
-// All ...
-func (grp *Group) All(path string, handlers ...Handler) Router {
-	for _, method := range intMethod {
-		grp.Add(method, path, handlers...)
-	}
-	return grp
-}
-
-// Group is used for Routes with common prefix to define a new sub-router with optional middleware.
-func (grp *Group) Group(prefix string, handlers ...Handler) Router {
-	prefix = getGroupPath(grp.prefix, prefix)
-	if len(handlers) > 0 {
-		grp.app.register(methodUse, prefix, handlers...)
-	}
-	return grp.app.Group(prefix)
-}

+ 0 - 370
vendor/github.com/gofiber/fiber/path.go

@@ -1,370 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-// ⚠️ This path parser was inspired by ucarion/urlpath (MIT License).
-// 💖 Maintained and modified for Fiber by @renewerner87
-
-package fiber
-
-import (
-	"strconv"
-	"strings"
-	"sync/atomic"
-
-	utils "github.com/gofiber/utils"
-)
-
-// routeParser holds the path segments and param names
-type routeParser struct {
-	segs          []routeSegment // the parsed segments of the route
-	params        []string       // that parameter names the parsed route
-	wildCardCount int            // number of wildcard parameters, used internally to give the wildcard parameter its number
-	plusCount     int            // number of plus parameters, used internally to give the plus parameter its number
-}
-
-// paramsSeg holds the segment metadata
-type routeSegment struct {
-	// const information
-	Const string // constant part of the route
-	// parameter information
-	IsParam     bool   // Truth value that indicates whether it is a parameter or a constant part
-	ParamName   string // name of the parameter for access to it, for wildcards and plus parameters access iterators starting with 1 are added
-	ComparePart string // search part to find the end of the parameter
-	PartCount   int    // how often is the search part contained in the non-param segments? -> necessary for greedy search
-	IsGreedy    bool   // indicates whether the parameter is greedy or not, is used with wildcard and plus
-	IsOptional  bool   // indicates whether the parameter is optional or not
-	// common information
-	IsLast bool // shows if the segment is the last one for the route
-	// future TODO: add support for optional groups "/abc(/def)?"
-}
-
-// different special routing signs
-const (
-	wildcardParam    byte = '*' // indicates a optional greedy parameter
-	plusParam        byte = '+' // indicates a required greedy parameter
-	optionalParam    byte = '?' // concludes a parameter by name and makes it optional
-	paramStarterChar byte = ':' // start character for a parameter with name
-	slashDelimiter   byte = '/' // separator for the route, unlike the other delimiters this character at the end can be optional
-)
-
-// list of possible parameter and segment delimiter
-var (
-	// slash has a special role, unlike the other parameters it must not be interpreted as a parameter
-	routeDelimiter = []byte{slashDelimiter, '-', '.'}
-	// list of chars for the parameter recognising
-	parameterStartChars = []byte{wildcardParam, plusParam, paramStarterChar}
-	// list of chars of delimiters and the starting parameter name char
-	parameterDelimiterChars = append([]byte{paramStarterChar}, routeDelimiter...)
-	// list of chars to find the end of a parameter
-	parameterEndChars = append([]byte{optionalParam}, parameterDelimiterChars...)
-)
-
-// parseRoute analyzes the route and divides it into segments for constant areas and parameters,
-// this information is needed later when assigning the requests to the declared routes
-func parseRoute(pattern string) routeParser {
-	parser := routeParser{}
-
-	part := ""
-	for len(pattern) > 0 {
-		nextParamPosition := findNextParamPosition(pattern)
-		// handle the parameter part
-		if nextParamPosition == 0 {
-			processedPart, seg := parser.analyseParameterPart(pattern)
-			parser.params, parser.segs, part = append(parser.params, seg.ParamName), append(parser.segs, seg), processedPart
-		} else {
-			processedPart, seg := parser.analyseConstantPart(pattern, nextParamPosition)
-			parser.segs, part = append(parser.segs, seg), processedPart
-		}
-
-		// reduce the pattern by the processed parts
-		if len(part) == len(pattern) {
-			break
-		}
-		pattern = pattern[len(part):]
-	}
-	// mark last segment
-	if len(parser.segs) > 0 {
-		parser.segs[len(parser.segs)-1].IsLast = true
-	}
-	parser.segs = addParameterMetaInfo(parser.segs)
-
-	return parser
-}
-
-// addParameterMetaInfo add important meta information to the parameter segments
-// to simplify the search for the end of the parameter
-func addParameterMetaInfo(segs []routeSegment) []routeSegment {
-	comparePart := ""
-	// loop from end to begin
-	for i := len(segs) - 1; i >= 0; i-- {
-		// set the compare part for the parameter
-		if segs[i].IsParam {
-			// important for finding the end of the parameter
-			segs[i].ComparePart = comparePart
-		} else {
-			comparePart = segs[i].Const
-			if len(comparePart) > 1 {
-				comparePart = utils.TrimRight(comparePart, slashDelimiter)
-			}
-		}
-	}
-
-	// loop from begin to end
-	for i := 0; i < len(segs); i++ {
-		// check how often the compare part is in the following const parts
-		if segs[i].IsParam && segs[i].ComparePart != "" {
-			for j := i + 1; j <= len(segs)-1; j++ {
-				if !segs[j].IsParam {
-					// count is important for the greedy match
-					segs[i].PartCount += strings.Count(segs[j].Const, segs[i].ComparePart)
-				}
-			}
-		}
-	}
-
-	return segs
-}
-
-// findNextParamPosition search for the next possible parameter start position
-func findNextParamPosition(pattern string) int {
-	nextParamPosition := findNextCharsetPosition(pattern, parameterStartChars)
-	if nextParamPosition != -1 && len(pattern) > nextParamPosition && pattern[nextParamPosition] != wildcardParam {
-		// search for parameter characters for the found parameter start,
-		// if there are more, move the parameter start to the last parameter char
-		for found := findNextCharsetPosition(pattern[nextParamPosition+1:], parameterStartChars); found == 0; {
-			nextParamPosition++
-			if len(pattern) > nextParamPosition {
-				break
-			}
-		}
-	}
-
-	return nextParamPosition
-}
-
-// analyseConstantPart find the end of the constant part and create the route segment
-func (routeParser *routeParser) analyseConstantPart(pattern string, nextParamPosition int) (string, routeSegment) {
-	// handle the constant part
-	processedPart := pattern
-	if nextParamPosition != -1 {
-		// remove the constant part until the parameter
-		processedPart = pattern[:nextParamPosition]
-	}
-	return processedPart, routeSegment{
-		Const: processedPart,
-	}
-}
-
-// analyseParameterPart find the parameter end and create the route segment
-func (routeParser *routeParser) analyseParameterPart(pattern string) (string, routeSegment) {
-	isWildCard := pattern[0] == wildcardParam
-	isPlusParam := pattern[0] == plusParam
-	parameterEndPosition := findNextCharsetPosition(pattern[1:], parameterEndChars)
-
-	// handle wildcard end
-	if isWildCard || isPlusParam {
-		parameterEndPosition = 0
-	} else if parameterEndPosition == -1 {
-		parameterEndPosition = len(pattern) - 1
-	} else if !isInCharset(pattern[parameterEndPosition+1], parameterDelimiterChars) {
-		parameterEndPosition = parameterEndPosition + 1
-	}
-	// cut params part
-	processedPart := pattern[0 : parameterEndPosition+1]
-
-	paramName := utils.GetTrimmedParam(processedPart)
-	// add access iterator to wildcard and plus
-	if isWildCard {
-		routeParser.wildCardCount++
-		paramName += strconv.Itoa(routeParser.wildCardCount)
-	} else if isPlusParam {
-		routeParser.plusCount++
-		paramName += strconv.Itoa(routeParser.plusCount)
-	}
-
-	return processedPart, routeSegment{
-		ParamName:  paramName,
-		IsParam:    true,
-		IsOptional: isWildCard || pattern[parameterEndPosition] == optionalParam,
-		IsGreedy:   isWildCard || isPlusParam,
-	}
-}
-
-// isInCharset check is the given character in the charset list
-func isInCharset(searchChar byte, charset []byte) bool {
-	for _, char := range charset {
-		if char == searchChar {
-			return true
-		}
-	}
-	return false
-}
-
-// findNextCharsetPosition search the next char position from the charset
-func findNextCharsetPosition(search string, charset []byte) int {
-	nextPosition := -1
-	for _, char := range charset {
-		if pos := strings.IndexByte(search, char); pos != -1 && (pos < nextPosition || nextPosition == -1) {
-			nextPosition = pos
-		}
-	}
-
-	return nextPosition
-}
-
-// getMatch parses the passed url and tries to match it against the route segments and determine the parameter positions
-func (routeParser *routeParser) getMatch(s string, partialCheck bool) ([][2]int, bool) {
-	lenKeys := len(routeParser.params)
-	paramsPositions := getAllocFreeParamsPos(lenKeys)
-	var i, paramsIterator, partLen, paramStart int
-	for index, segment := range routeParser.segs {
-		partLen = len(s)
-		// check const segment
-		if !segment.IsParam {
-			optionalPart := false
-			i = len(segment.Const)
-			// check if the end of the segment is a optional slash and then if the segement is optional or the last one
-			if i > 0 && partLen == i-1 && segment.Const[i-1] == slashDelimiter && s[:i-1] == segment.Const[:i-1] {
-				if segment.IsLast || routeParser.segs[index+1].IsOptional {
-					i--
-					optionalPart = true
-				}
-			}
-			// is optional part or the const part must match with the given string
-			if !optionalPart && (partLen < i || (i == 0 && partLen > 0) || s[:i] != segment.Const) {
-				return nil, false
-			}
-		} else {
-			// determine parameter length
-			i = findParamLen(s, routeParser.segs, index)
-			if !segment.IsOptional && i == 0 {
-				return nil, false
-			}
-			// take over the params positions
-			paramsPositions[paramsIterator][0], paramsPositions[paramsIterator][1] = paramStart, paramStart+i
-			paramsIterator++
-		}
-
-		// reduce founded part from the string
-		if partLen > 0 {
-			if partLen < i {
-				i = partLen
-			}
-			paramStart += i
-
-			s = s[i:]
-		}
-	}
-	if len(s) != 0 && !partialCheck {
-		return nil, false
-	}
-
-	return paramsPositions, true
-}
-
-// paramsForPos get parameters for the given positions from the given path
-func (routeParser *routeParser) paramsForPos(path string, paramsPositions [][2]int) []string {
-	size := len(paramsPositions)
-	params := getAllocFreeParams(size)
-	for i, positions := range paramsPositions {
-		if positions[0] != positions[1] && len(path) >= positions[1] {
-			params[i] = path[positions[0]:positions[1]]
-		} else {
-			params[i] = ""
-		}
-	}
-
-	return params
-}
-
-// findParamLen for the expressjs wildcard behavior (right to left greedy)
-// look at the other segments and take what is left for the wildcard from right to left
-func findParamLen(s string, segments []routeSegment, currIndex int) int {
-	if segments[currIndex].IsLast {
-		return findParamLenForLastSegment(s, segments[currIndex])
-	}
-
-	compareSeg := segments[currIndex+1]
-	// check if parameter segments are directly after each other and if one of them is greedy
-	if compareSeg.IsParam && !segments[currIndex].IsGreedy && !compareSeg.IsGreedy && len(s) > 0 {
-		// in case the next parameter or the current parameter is not a wildcard its not greedy, we only want one character
-		return 1
-	}
-	// Search the parameters until the next constant part
-	// special logic for greedy params
-	if segments[currIndex].IsGreedy {
-		searchCount := strings.Count(s, segments[currIndex].ComparePart)
-		if searchCount > 1 {
-			return findGreedyParamLen(s, searchCount, segments[currIndex])
-		}
-	}
-
-	if constPosition := strings.Index(s, segments[currIndex].ComparePart); constPosition != -1 {
-		return constPosition
-	}
-
-	return len(s)
-}
-
-// findParamLenForLastSegment get the length of the parameter if it is the last segment
-func findParamLenForLastSegment(s string, seg routeSegment) int {
-	if seg.IsGreedy {
-		return len(s)
-	}
-	if i := strings.IndexByte(s, slashDelimiter); i != -1 {
-		return i
-	}
-
-	return len(s)
-}
-
-// findGreedyParamLen get the length of the parameter for greedy segments from right to left
-func findGreedyParamLen(s string, searchCount int, segment routeSegment) int {
-	// check all from right to left segments
-	for i := segment.PartCount; i > 0 && searchCount > 0; i-- {
-		searchCount--
-		if constPosition := strings.LastIndex(s, segment.ComparePart); constPosition != -1 {
-			s = s[:constPosition]
-		} else {
-			break
-		}
-	}
-
-	return len(s)
-}
-
-// performance tricks
-// creates predefined arrays that are used to match the request routes so that no allocations need to be made
-var paramsDummy, paramsPosDummy = make([]string, 100000), make([][2]int, 100000)
-
-// positions parameter that moves further and further to the right and remains atomic over all simultaneous requests
-// to assign a separate range to each request
-var startParamList, startParamPosList uint32 = 0, 0
-
-// getAllocFreeParamsPos fetches a slice area from the predefined slice, which is currently not in use
-func getAllocFreeParamsPos(allocLen int) [][2]int {
-	size := uint32(allocLen)
-	start := atomic.AddUint32(&startParamPosList, size)
-	if (start + 10) >= uint32(len(paramsPosDummy)) {
-		atomic.StoreUint32(&startParamPosList, 0)
-		return getAllocFreeParamsPos(allocLen)
-	}
-	start -= size
-	allocLen += int(start)
-	paramsPositions := paramsPosDummy[start:allocLen:allocLen]
-	return paramsPositions
-}
-
-// getAllocFreeParams fetches a slice area from the predefined slice, which is currently not in use
-func getAllocFreeParams(allocLen int) []string {
-	size := uint32(allocLen)
-	start := atomic.AddUint32(&startParamList, size)
-	if (start + 10) >= uint32(len(paramsDummy)) {
-		atomic.StoreUint32(&startParamList, 0)
-		return getAllocFreeParams(allocLen)
-	}
-	start -= size
-	allocLen += int(start)
-	params := paramsDummy[start:allocLen:allocLen]
-	return params
-}

+ 0 - 152
vendor/github.com/gofiber/fiber/prefork.go

@@ -1,152 +0,0 @@
-package fiber
-
-import (
-	"crypto/tls"
-	"fmt"
-	"net"
-	"os"
-	"os/exec"
-	"runtime"
-	"strconv"
-	"strings"
-	"time"
-
-	reuseport "github.com/valyala/fasthttp/reuseport"
-)
-
-const (
-	envPreforkChildKey = "FIBER_PREFORK_CHILD"
-	envPreforkChildVal = "1"
-)
-
-var (
-	testPreforkMaster = false
-)
-
-// IsChild determines if the current process is a result of Prefork
-func (app *App) IsChild() bool {
-	return os.Getenv(envPreforkChildKey) == envPreforkChildVal
-}
-
-// prefork manages child processes to make use of the OS REUSEPORT or REUSEADDR feature
-func (app *App) prefork(addr string, tlsconfig ...*tls.Config) (err error) {
-	// 👶 child process 👶
-	if app.IsChild() {
-		// use 1 cpu core per child process
-		runtime.GOMAXPROCS(1)
-		var ln net.Listener
-		// Set correct network protocol
-		network := "tcp4"
-		if isIPv6(addr) {
-			network = "tcp6"
-		}
-		// Linux will use SO_REUSEPORT and Windows falls back to SO_REUSEADDR
-		// Only tcp4 or tcp6 is supported when preforking, both are not supported
-		if ln, err = reuseport.Listen(network, addr); err != nil {
-			if !app.Settings.DisableStartupMessage {
-				time.Sleep(100 * time.Millisecond) // avoid colliding with startup message
-			}
-			return fmt.Errorf("prefork: %v", err)
-		}
-		// wrap a tls config around the listener if provided
-		if len(tlsconfig) > 0 {
-			ln = tls.NewListener(ln, tlsconfig[0])
-		}
-
-		// kill current child proc when master exits
-		go watchMaster()
-
-		// listen for incoming connections
-		return app.server.Serve(ln)
-	}
-
-	// 👮 master process 👮
-	type child struct {
-		pid int
-		err error
-	}
-	// create variables
-	var max = runtime.GOMAXPROCS(0)
-	var childs = make(map[int]*exec.Cmd)
-	var channel = make(chan child, max)
-
-	// kill child procs when master exits
-	defer func() {
-		for _, proc := range childs {
-			_ = proc.Process.Kill()
-		}
-	}()
-
-	// collect child pids
-	var pids []string
-
-	// launch child procs
-	for i := 0; i < max; i++ {
-		/* #nosec G204 */
-		cmd := exec.Command(os.Args[0], os.Args[1:]...)
-		if testPreforkMaster {
-			// When test prefork master,
-			// just start the child process with a dummy cmd,
-			// which will exit soon
-			cmd = dummyCmd()
-		}
-		cmd.Stdout = os.Stdout
-		cmd.Stderr = os.Stderr
-
-		// add fiber prefork child flag into child proc env
-		cmd.Env = append(os.Environ(),
-			fmt.Sprintf("%s=%s", envPreforkChildKey, envPreforkChildVal),
-		)
-		if err = cmd.Start(); err != nil {
-			return fmt.Errorf("failed to start a child prefork process, error: %v", err)
-		}
-
-		// store child process
-		pid := cmd.Process.Pid
-		childs[pid] = cmd
-		pids = append(pids, strconv.Itoa(pid))
-
-		// notify master if child crashes
-		go func() {
-			channel <- child{pid, cmd.Wait()}
-		}()
-	}
-
-	// Print startup message
-	if !app.Settings.DisableStartupMessage {
-		app.startupMessage(addr, len(tlsconfig) > 0, ","+strings.Join(pids, ","))
-	}
-
-	// return error if child crashes
-	return (<-channel).err
-}
-
-// watchMaster watches child procs
-func watchMaster() {
-	if runtime.GOOS == "windows" {
-		// finds parent process,
-		// and waits for it to exit
-		p, err := os.FindProcess(os.Getppid())
-		if err == nil {
-			_, _ = p.Wait()
-		}
-		os.Exit(1)
-	}
-	// if it is equal to 1 (init process ID),
-	// it indicates that the master process has exited
-	for range time.NewTicker(time.Millisecond * 500).C {
-		if os.Getppid() == 1 {
-			os.Exit(1)
-		}
-	}
-}
-
-var dummyChildCmd = "go"
-
-// dummyCmd is for internal prefork testing
-func dummyCmd() *exec.Cmd {
-	if runtime.GOOS == "windows" {
-		return exec.Command("cmd", "/C", dummyChildCmd, "version")
-	}
-	return exec.Command(dummyChildCmd, "version")
-}

+ 0 - 390
vendor/github.com/gofiber/fiber/router.go

@@ -1,390 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package fiber
-
-import (
-	"fmt"
-	"sort"
-	"strings"
-	"time"
-
-	utils "github.com/gofiber/utils"
-	fasthttp "github.com/valyala/fasthttp"
-)
-
-// Router defines all router handle interface includes app and group router.
-type Router interface {
-	Use(args ...interface{}) Router
-
-	Get(path string, handlers ...Handler) Router
-	Head(path string, handlers ...Handler) Router
-	Post(path string, handlers ...Handler) Router
-	Put(path string, handlers ...Handler) Router
-	Delete(path string, handlers ...Handler) Router
-	Connect(path string, handlers ...Handler) Router
-	Options(path string, handlers ...Handler) Router
-	Trace(path string, handlers ...Handler) Router
-	Patch(path string, handlers ...Handler) Router
-
-	Add(method, path string, handlers ...Handler) Router
-	Static(prefix, root string, config ...Static) Router
-	All(path string, handlers ...Handler) Router
-
-	Group(prefix string, handlers ...Handler) Router
-}
-
-// Route is a struct that holds all metadata for each registered handler
-type Route struct {
-	// Data for routing
-	pos         int         // Position in stack -> important for the sort of the matched routes
-	use         bool        // USE matches path prefixes
-	star        bool        // Path equals '*'
-	root        bool        // Path equals '/'
-	path        string      // Prettified path
-	routeParser routeParser // Parameter parser
-
-	// Public fields
-	Method   string    `json:"method"` // HTTP method
-	Path     string    `json:"path"`   // Original registered route path
-	Params   []string  `json:"params"` // Case sensitive param keys
-	Handlers []Handler `json:"-"`      // Ctx handlers
-}
-
-func (r *Route) match(path, original string) (match bool, values []string) {
-	// root path check
-	if r.root && path == "/" {
-		return true, values
-		// '*' wildcard matches any path
-	} else if r.star {
-		values := getAllocFreeParams(1)
-		if len(original) > 1 {
-			values[0] = original[1:]
-		}
-		return true, values
-	}
-	// Does this route have parameters
-	if len(r.Params) > 0 {
-		// Match params
-		if paramPos, match := r.routeParser.getMatch(path, r.use); match {
-			// Get params from the original path
-			return match, r.routeParser.paramsForPos(original, paramPos)
-		}
-	}
-	// Is this route a Middleware?
-	if r.use {
-		// Single slash will match or path prefix
-		if r.root || strings.HasPrefix(path, r.path) {
-			return true, values
-		}
-		// Check for a simple path match
-	} else if len(r.path) == len(path) && r.path == path {
-		return true, values
-	}
-	// No match
-	return false, values
-}
-
-func (app *App) next(ctx *Ctx) bool {
-	// Get stack length
-	tree, ok := app.treeStack[ctx.methodINT][ctx.treePath]
-	if !ok {
-		tree = app.treeStack[ctx.methodINT][""]
-	}
-	lenr := len(tree) - 1
-	// Loop over the route stack starting from previous index
-	for ctx.indexRoute < lenr {
-		// Increment route index
-		ctx.indexRoute++
-		// Get *Route
-		route := tree[ctx.indexRoute]
-		// Check if it matches the request path
-		match, values := route.match(ctx.path, ctx.pathOriginal)
-		// No match, next route
-		if !match {
-			continue
-		}
-		// Pass route reference and param values
-		ctx.route = route
-		// Non use handler matched
-		if !ctx.matched && !route.use {
-			ctx.matched = true
-		}
-
-		ctx.values = values
-		// Execute first handler of route
-		ctx.indexHandler = 0
-		route.Handlers[0](ctx)
-		// Stop scanning the stack
-		return true
-	}
-	// If c.Next() does not match, return 404
-	ctx.SendStatus(StatusNotFound)
-	ctx.SendString("Cannot " + ctx.method + " " + ctx.pathOriginal)
-
-	// Scan stack for other methods
-	// Moved from app.handler
-	// It should be here,
-	// because middleware may break the route chain
-	if !ctx.matched {
-		setMethodNotAllowed(ctx)
-	}
-	return false
-}
-
-func (app *App) handler(rctx *fasthttp.RequestCtx) {
-	// Acquire Ctx with fasthttp request from pool
-	ctx := app.AcquireCtx(rctx)
-
-	// handle invalid http method directly
-	if ctx.methodINT == -1 {
-		ctx.Status(StatusBadRequest).SendString("Invalid http method")
-		app.ReleaseCtx(ctx)
-		return
-	}
-	// Find match in stack
-	match := app.next(ctx)
-	// Generate ETag if enabled
-	if match && app.Settings.ETag {
-		setETag(ctx, false)
-	}
-	// Release Ctx
-	app.ReleaseCtx(ctx)
-}
-
-func (app *App) register(method, pathRaw string, handlers ...Handler) Route {
-	// Uppercase HTTP methods
-	method = utils.ToUpper(method)
-	// Check if the HTTP method is valid unless it's USE
-	if method != methodUse && methodInt(method) == -1 {
-		panic(fmt.Sprintf("add: invalid http method %s\n", method))
-	}
-	// A route requires atleast one ctx handler
-	if len(handlers) == 0 {
-		panic(fmt.Sprintf("missing handler in route: %s\n", pathRaw))
-	}
-	// Cannot have an empty path
-	if pathRaw == "" {
-		pathRaw = "/"
-	}
-	// Path always start with a '/'
-	if pathRaw[0] != '/' {
-		pathRaw = "/" + pathRaw
-	}
-	// Create a stripped path in-case sensitive / trailing slashes
-	pathPretty := pathRaw
-	// Case sensitive routing, all to lowercase
-	if !app.Settings.CaseSensitive {
-		pathPretty = utils.ToLower(pathPretty)
-	}
-	// Strict routing, remove trailing slashes
-	if !app.Settings.StrictRouting && len(pathPretty) > 1 {
-		pathPretty = utils.TrimRight(pathPretty, '/')
-	}
-	// Is layer a middleware?
-	var isUse = method == methodUse
-	// Is path a direct wildcard?
-	var isStar = pathPretty == "/*"
-	// Is path a root slash?
-	var isRoot = pathPretty == "/"
-	// Parse path parameters
-	var parsedRaw = parseRoute(pathRaw)
-	var parsedPretty = parseRoute(pathPretty)
-
-	// Create route metadata without pointer
-	route := Route{
-		// Router booleans
-		use:  isUse,
-		star: isStar,
-		root: isRoot,
-		// Path data
-		path:        pathPretty,
-		routeParser: parsedPretty,
-		Params:      parsedRaw.params,
-
-		// Public data
-		Path:     pathRaw,
-		Method:   method,
-		Handlers: handlers,
-	}
-	// Increment global handler count
-	app.mutex.Lock()
-	app.handlerCount += len(handlers)
-	app.mutex.Unlock()
-	// Middleware route matches all HTTP methods
-	if isUse {
-		// Add route to all HTTP methods stack
-		for _, m := range intMethod {
-			// create a route copy
-			r := route
-			app.addRoute(m, &r)
-		}
-		return route
-	}
-
-	// Add route to stack
-	app.addRoute(method, &route)
-	return route
-}
-
-func (app *App) registerStatic(prefix, root string, config ...Static) Route {
-	// For security we want to restrict to the current work directory.
-	if len(root) == 0 {
-		root = "."
-	}
-	// Cannot have an empty prefix
-	if prefix == "" {
-		prefix = "/"
-	}
-	// Prefix always start with a '/' or '*'
-	if prefix[0] != '/' {
-		prefix = "/" + prefix
-	}
-	// in case sensitive routing, all to lowercase
-	if !app.Settings.CaseSensitive {
-		prefix = utils.ToLower(prefix)
-	}
-	// Strip trailing slashes from the root path
-	if len(root) > 0 && root[len(root)-1] == '/' {
-		root = root[:len(root)-1]
-	}
-	// Is prefix a direct wildcard?
-	var isStar = prefix == "/*"
-	// Is prefix a root slash?
-	var isRoot = prefix == "/"
-	// Is prefix a partial wildcard?
-	if strings.Contains(prefix, "*") {
-		// /john* -> /john
-		isStar = true
-		prefix = strings.Split(prefix, "*")[0]
-		// Fix this later
-	}
-	prefixLen := len(prefix)
-	// Fileserver settings
-	fs := &fasthttp.FS{
-		Root:                 root,
-		GenerateIndexPages:   false,
-		AcceptByteRange:      false,
-		Compress:             false,
-		CompressedFileSuffix: app.Settings.CompressedFileSuffix,
-		CacheDuration:        10 * time.Second,
-		IndexNames:           []string{"index.html"},
-		PathRewrite: func(ctx *fasthttp.RequestCtx) []byte {
-			path := ctx.Path()
-			if len(path) >= prefixLen {
-				if isStar && getString(path[0:prefixLen]) == prefix {
-					path = append(path[0:0], '/')
-				} else {
-					path = append(path[prefixLen:], '/')
-				}
-			}
-			if len(path) > 0 && path[0] != '/' {
-				path = append([]byte("/"), path...)
-			}
-			return path
-		},
-		PathNotFound: func(ctx *fasthttp.RequestCtx) {
-			ctx.Response.SetStatusCode(StatusNotFound)
-		},
-	}
-	// Set config if provided
-	if len(config) > 0 {
-		fs.Compress = config[0].Compress
-		fs.AcceptByteRange = config[0].ByteRange
-		fs.GenerateIndexPages = config[0].Browse
-		if config[0].Index != "" {
-			fs.IndexNames = []string{config[0].Index}
-		}
-	}
-	fileHandler := fs.NewRequestHandler()
-	handler := func(c *Ctx) {
-		// Serve file
-		fileHandler(c.Fasthttp)
-		// Return request if found and not forbidden
-		status := c.Fasthttp.Response.StatusCode()
-		if status != StatusNotFound && status != StatusForbidden {
-			return
-		}
-		// Reset response to default
-		c.Fasthttp.SetContentType("") // Issue #420
-		c.Fasthttp.Response.SetStatusCode(StatusOK)
-		c.Fasthttp.Response.SetBodyString("")
-		// Next middleware
-		c.Next()
-	}
-
-	// Create route metadata without pointer
-	route := Route{
-		// Router booleans
-		use:  true,
-		root: isRoot,
-		path: prefix,
-		// Public data
-		Method:   MethodGet,
-		Path:     prefix,
-		Handlers: []Handler{handler},
-	}
-	// Increment global handler count
-	app.mutex.Lock()
-	app.handlerCount++
-	app.mutex.Unlock()
-	// Add route to stack
-	app.addRoute(MethodGet, &route)
-	// Add HEAD route
-	headRoute := route
-	app.addRoute(MethodHead, &headRoute)
-	return route
-}
-
-func (app *App) addRoute(method string, route *Route) {
-	// Get unique HTTP method indentifier
-	m := methodInt(method)
-
-	// prevent identically route registration
-	l := len(app.stack[m])
-	if l > 0 && app.stack[m][l-1].Path == route.Path && route.use == app.stack[m][l-1].use {
-		preRoute := app.stack[m][l-1]
-		preRoute.Handlers = append(preRoute.Handlers, route.Handlers...)
-	} else {
-		// Increment global route position
-		app.mutex.Lock()
-		app.routesCount++
-		app.mutex.Unlock()
-		route.pos = app.routesCount
-		route.Method = method
-		// Add route to the stack
-		app.stack[m] = append(app.stack[m], route)
-	}
-}
-
-// buildTree build the prefix tree from the previously registered routes
-func (app *App) buildTree() *App {
-	// loop all the methods and stacks and create the prefix tree
-	for m := range intMethod {
-		app.treeStack[m] = make(map[string][]*Route)
-		for _, route := range app.stack[m] {
-			treePath := ""
-			if len(route.routeParser.segs) > 0 && len(route.routeParser.segs[0].Const) >= 3 {
-				treePath = route.routeParser.segs[0].Const[:3]
-			}
-			// create tree stack
-			app.treeStack[m][treePath] = append(app.treeStack[m][treePath], route)
-		}
-	}
-	// loop the methods and tree stacks and add global stack and sort everything
-	for m := range intMethod {
-		for treePart := range app.treeStack[m] {
-			if treePart != "" {
-				// merge global tree routes in current tree stack
-				app.treeStack[m][treePart] = uniqueRouteStack(append(app.treeStack[m][treePart], app.treeStack[m][""]...))
-			}
-			// sort tree slices with the positions
-			sort.Slice(app.treeStack[m][treePart], func(i, j int) bool {
-				return app.treeStack[m][treePart][i].pos < app.treeStack[m][treePart][j].pos
-			})
-		}
-	}
-
-	return app
-}

+ 0 - 642
vendor/github.com/gofiber/fiber/utils.go

@@ -1,642 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package fiber
-
-import (
-	"bytes"
-	"fmt"
-	"hash/crc32"
-	"io"
-	"net"
-	"os"
-	"path/filepath"
-	"strings"
-	"time"
-
-	utils "github.com/gofiber/utils"
-	bytebufferpool "github.com/valyala/bytebufferpool"
-	fasthttp "github.com/valyala/fasthttp"
-)
-
-// readContent opens a named file and read content from it
-func readContent(rf io.ReaderFrom, name string) (n int64, err error) {
-	// Read file
-	f, err := os.Open(filepath.Clean(name))
-	if err != nil {
-		return 0, err
-	}
-	defer func() {
-		err = f.Close()
-	}()
-	return rf.ReadFrom(f)
-}
-
-// quoteString escape special characters in a given string
-func quoteString(raw string) string {
-	bb := bytebufferpool.Get()
-	quoted := string(fasthttp.AppendQuotedArg(bb.B, getBytes(raw)))
-	bytebufferpool.Put(bb)
-	return quoted
-}
-
-// Scan stack if other methods match
-func setMethodNotAllowed(ctx *Ctx) {
-	var matched bool
-	for i := 0; i < len(intMethod); i++ {
-		// Skip original method
-		if ctx.methodINT == i {
-			continue
-		}
-		// Reset stack index
-		ctx.indexRoute = -1
-		tree, ok := ctx.app.treeStack[i][ctx.treePath]
-		if !ok {
-			tree = ctx.app.treeStack[i][""]
-		}
-		// Get stack length
-		lenr := len(tree) - 1
-		//Loop over the route stack starting from previous index
-		for ctx.indexRoute < lenr {
-			// Increment route index
-			ctx.indexRoute++
-			// Get *Route
-			route := tree[ctx.indexRoute]
-			// Skip use routes
-			if route.use {
-				continue
-			}
-			// Check if it matches the request path
-			match, _ := route.match(ctx.path, ctx.pathOriginal)
-			// No match, next route
-			if match {
-				// We matched
-				matched = true
-				// Add method to Allow header
-				ctx.Append(HeaderAllow, intMethod[i])
-				// Break stack loop
-				break
-			}
-		}
-	}
-	// Update response status
-	if matched {
-		ctx.Status(StatusMethodNotAllowed)
-	}
-}
-
-// defaultString returns the value or a default value if it is set
-func defaultString(value string, defaultValue []string) string {
-	if len(value) == 0 && len(defaultValue) > 0 {
-		return defaultValue[0]
-	}
-	return value
-}
-
-// Generate and set ETag header to response
-func setETag(ctx *Ctx, weak bool) {
-	// Don't generate ETags for invalid responses
-	if ctx.Fasthttp.Response.StatusCode() != StatusOK {
-		return
-	}
-	body := ctx.Fasthttp.Response.Body()
-	// Skips ETag if no response body is present
-	if len(body) <= 0 {
-		return
-	}
-	// Get ETag header from request
-	clientEtag := ctx.Get(HeaderIfNoneMatch)
-
-	// Generate ETag for response
-	crc32q := crc32.MakeTable(0xD5828281)
-	etag := fmt.Sprintf("\"%d-%v\"", len(body), crc32.Checksum(body, crc32q))
-
-	// Enable weak tag
-	if weak {
-		etag = "W/" + etag
-	}
-
-	// Check if client's ETag is weak
-	if strings.HasPrefix(clientEtag, "W/") {
-		// Check if server's ETag is weak
-		if clientEtag[2:] == etag || clientEtag[2:] == etag[2:] {
-			// W/1 == 1 || W/1 == W/1
-			ctx.SendStatus(StatusNotModified)
-			ctx.Fasthttp.ResetBody()
-			return
-		}
-		// W/1 != W/2 || W/1 != 2
-		ctx.Set(HeaderETag, etag)
-		return
-	}
-	if strings.Contains(clientEtag, etag) {
-		// 1 == 1
-		ctx.SendStatus(StatusNotModified)
-		ctx.Fasthttp.ResetBody()
-		return
-	}
-	// 1 != 2
-	ctx.Set(HeaderETag, etag)
-}
-
-func getGroupPath(prefix, path string) string {
-	if path == "/" {
-		return prefix
-	}
-	return utils.TrimRight(prefix, '/') + path
-}
-
-// return valid offer for header negotiation
-func getOffer(header string, offers ...string) string {
-	if len(offers) == 0 {
-		return ""
-	} else 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 = header
-		}
-		if factorSign := strings.IndexByte(spec, ';'); factorSign != -1 {
-			spec = spec[:factorSign]
-		}
-
-		for _, offer := range offers {
-			// has star prefix
-			if len(spec) >= 1 && spec[len(spec)-1] == '*' {
-				return offer
-			} else if strings.HasPrefix(spec, offer) {
-				return offer
-			}
-		}
-		if commaPos != -1 {
-			header = header[commaPos+1:]
-		}
-	}
-
-	return ""
-}
-
-func matchEtag(s string, etag string) bool {
-	if s == etag || s == "W/"+etag || "W/"+s == etag {
-		return true
-	}
-
-	return false
-}
-
-func isEtagStale(etag string, noneMatchBytes []byte) bool {
-	var start, end int
-
-	// Adapted from:
-	// https://github.com/jshttp/fresh/blob/10e0471669dbbfbfd8de65bc6efac2ddd0bfa057/index.js#L110
-	for i := range noneMatchBytes {
-		switch noneMatchBytes[i] {
-		case 0x20:
-			if start == end {
-				start = i + 1
-				end = i + 1
-			}
-		case 0x2c:
-			if matchEtag(getString(noneMatchBytes[start:end]), etag) {
-				return false
-			}
-			start = i + 1
-			end = i + 1
-		default:
-			end = i + 1
-		}
-	}
-
-	return !matchEtag(getString(noneMatchBytes[start:end]), etag)
-}
-
-func isIPv6(address string) bool {
-	return strings.Count(address, ":") >= 2
-}
-
-func parseAddr(raw string) (host, port string) {
-	if i := strings.LastIndex(raw, ":"); i != -1 {
-		return raw[:i], raw[i+1:]
-	}
-	return raw, ""
-}
-
-const noCacheValue = "no-cache"
-
-// isNoCache checks if the cacheControl header value is a `no-cache`.
-func isNoCache(cacheControl string) bool {
-	i := strings.Index(cacheControl, noCacheValue)
-	if i == -1 {
-		return false
-	}
-
-	// Xno-cache
-	if i > 0 && !(cacheControl[i-1] == ' ' || cacheControl[i-1] == ',') {
-		return false
-	}
-
-	// bla bla, no-cache
-	if i+len(noCacheValue) == len(cacheControl) {
-		return true
-	}
-
-	// bla bla, no-cacheX
-	if cacheControl[i+len(noCacheValue)] != ',' {
-		return false
-	}
-
-	// OK
-	return true
-}
-
-// https://golang.org/src/net/net.go#L113
-// Helper methods for application#test
-type testAddr string
-
-func (a testAddr) Network() string {
-	return string(a)
-}
-func (a testAddr) String() string {
-	return string(a)
-}
-
-type testConn struct {
-	r bytes.Buffer
-	w bytes.Buffer
-}
-
-func (c *testConn) Read(b []byte) (int, error)  { return c.r.Read(b) }
-func (c *testConn) Write(b []byte) (int, error) { return c.w.Write(b) }
-func (c *testConn) Close() error                { return nil }
-
-func (c *testConn) LocalAddr() net.Addr                { return testAddr("local-addr") }
-func (c *testConn) RemoteAddr() net.Addr               { return testAddr("remote-addr") }
-func (c *testConn) SetDeadline(t time.Time) error      { return nil }
-func (c *testConn) SetReadDeadline(t time.Time) error  { return nil }
-func (c *testConn) SetWriteDeadline(t time.Time) error { return nil }
-
-// getString converts byte slice to a string without memory allocation.
-var getString = utils.GetString
-var getStringImmutable = func(b []byte) string {
-	return string(b)
-}
-
-// getBytes converts string to a byte slice without memory allocation.
-var getBytes = utils.GetBytes
-var getBytesImmutable = func(s string) (b []byte) {
-	return []byte(s)
-}
-
-// uniqueRouteStack drop all not unique routes from the slice
-func uniqueRouteStack(stack []*Route) []*Route {
-	var unique []*Route
-	m := make(map[*Route]int)
-	for _, v := range stack {
-		if _, ok := m[v]; !ok {
-			// Unique key found. Record position and collect
-			// in result.
-			m[v] = len(unique)
-			unique = append(unique, v)
-		}
-	}
-
-	return unique
-}
-
-// HTTP methods and their unique INTs
-func methodInt(s string) int {
-	switch s {
-	case MethodGet:
-		return 0
-	case MethodHead:
-		return 1
-	case MethodPost:
-		return 2
-	case MethodPut:
-		return 3
-	case MethodDelete:
-		return 4
-	case MethodConnect:
-		return 5
-	case MethodOptions:
-		return 6
-	case MethodTrace:
-		return 7
-	case MethodPatch:
-		return 8
-	default:
-		return -1
-	}
-}
-
-// HTTP methods slice
-var intMethod = []string{
-	MethodGet,
-	MethodHead,
-	MethodPost,
-	MethodPut,
-	MethodDelete,
-	MethodConnect,
-	MethodOptions,
-	MethodTrace,
-	MethodPatch,
-}
-
-// HTTP methods were copied from net/http.
-const (
-	MethodGet     = "GET"     // RFC 7231, 4.3.1
-	MethodHead    = "HEAD"    // RFC 7231, 4.3.2
-	MethodPost    = "POST"    // RFC 7231, 4.3.3
-	MethodPut     = "PUT"     // RFC 7231, 4.3.4
-	MethodPatch   = "PATCH"   // RFC 5789
-	MethodDelete  = "DELETE"  // RFC 7231, 4.3.5
-	MethodConnect = "CONNECT" // RFC 7231, 4.3.6
-	MethodOptions = "OPTIONS" // RFC 7231, 4.3.7
-	MethodTrace   = "TRACE"   // RFC 7231, 4.3.8
-	methodUse     = "USE"
-)
-
-// MIME types that are commonly used
-const (
-	MIMETextXML               = "text/xml"
-	MIMETextHTML              = "text/html"
-	MIMETextPlain             = "text/plain"
-	MIMEApplicationXML        = "application/xml"
-	MIMEApplicationJSON       = "application/json"
-	MIMEApplicationJavaScript = "application/javascript"
-	MIMEApplicationForm       = "application/x-www-form-urlencoded"
-	MIMEOctetStream           = "application/octet-stream"
-	MIMEMultipartForm         = "multipart/form-data"
-
-	MIMETextXMLCharsetUTF8               = "text/xml; charset=utf-8"
-	MIMETextHTMLCharsetUTF8              = "text/html; charset=utf-8"
-	MIMETextPlainCharsetUTF8             = "text/plain; charset=utf-8"
-	MIMEApplicationXMLCharsetUTF8        = "application/xml; charset=utf-8"
-	MIMEApplicationJSONCharsetUTF8       = "application/json; charset=utf-8"
-	MIMEApplicationJavaScriptCharsetUTF8 = "application/javascript; charset=utf-8"
-)
-
-// HTTP status codes were copied from net/http.
-const (
-	StatusContinue                      = 100 // RFC 7231, 6.2.1
-	StatusSwitchingProtocols            = 101 // RFC 7231, 6.2.2
-	StatusProcessing                    = 102 // RFC 2518, 10.1
-	StatusEarlyHints                    = 103 // RFC 8297
-	StatusOK                            = 200 // RFC 7231, 6.3.1
-	StatusCreated                       = 201 // RFC 7231, 6.3.2
-	StatusAccepted                      = 202 // RFC 7231, 6.3.3
-	StatusNonAuthoritativeInfo          = 203 // RFC 7231, 6.3.4
-	StatusNoContent                     = 204 // RFC 7231, 6.3.5
-	StatusResetContent                  = 205 // RFC 7231, 6.3.6
-	StatusPartialContent                = 206 // RFC 7233, 4.1
-	StatusMultiStatus                   = 207 // RFC 4918, 11.1
-	StatusAlreadyReported               = 208 // RFC 5842, 7.1
-	StatusIMUsed                        = 226 // RFC 3229, 10.4.1
-	StatusMultipleChoices               = 300 // RFC 7231, 6.4.1
-	StatusMovedPermanently              = 301 // RFC 7231, 6.4.2
-	StatusFound                         = 302 // RFC 7231, 6.4.3
-	StatusSeeOther                      = 303 // RFC 7231, 6.4.4
-	StatusNotModified                   = 304 // RFC 7232, 4.1
-	StatusUseProxy                      = 305 // RFC 7231, 6.4.5
-	StatusTemporaryRedirect             = 307 // RFC 7231, 6.4.7
-	StatusPermanentRedirect             = 308 // RFC 7538, 3
-	StatusBadRequest                    = 400 // RFC 7231, 6.5.1
-	StatusUnauthorized                  = 401 // RFC 7235, 3.1
-	StatusPaymentRequired               = 402 // RFC 7231, 6.5.2
-	StatusForbidden                     = 403 // RFC 7231, 6.5.3
-	StatusNotFound                      = 404 // RFC 7231, 6.5.4
-	StatusMethodNotAllowed              = 405 // RFC 7231, 6.5.5
-	StatusNotAcceptable                 = 406 // RFC 7231, 6.5.6
-	StatusProxyAuthRequired             = 407 // RFC 7235, 3.2
-	StatusRequestTimeout                = 408 // RFC 7231, 6.5.7
-	StatusConflict                      = 409 // RFC 7231, 6.5.8
-	StatusGone                          = 410 // RFC 7231, 6.5.9
-	StatusLengthRequired                = 411 // RFC 7231, 6.5.10
-	StatusPreconditionFailed            = 412 // RFC 7232, 4.2
-	StatusRequestEntityTooLarge         = 413 // RFC 7231, 6.5.11
-	StatusRequestURITooLong             = 414 // RFC 7231, 6.5.12
-	StatusUnsupportedMediaType          = 415 // RFC 7231, 6.5.13
-	StatusRequestedRangeNotSatisfiable  = 416 // RFC 7233, 4.4
-	StatusExpectationFailed             = 417 // RFC 7231, 6.5.14
-	StatusTeapot                        = 418 // RFC 7168, 2.3.3
-	StatusMisdirectedRequest            = 421 // RFC 7540, 9.1.2
-	StatusUnprocessableEntity           = 422 // RFC 4918, 11.2
-	StatusLocked                        = 423 // RFC 4918, 11.3
-	StatusFailedDependency              = 424 // RFC 4918, 11.4
-	StatusTooEarly                      = 425 // RFC 8470, 5.2.
-	StatusUpgradeRequired               = 426 // RFC 7231, 6.5.15
-	StatusPreconditionRequired          = 428 // RFC 6585, 3
-	StatusTooManyRequests               = 429 // RFC 6585, 4
-	StatusRequestHeaderFieldsTooLarge   = 431 // RFC 6585, 5
-	StatusUnavailableForLegalReasons    = 451 // RFC 7725, 3
-	StatusInternalServerError           = 500 // RFC 7231, 6.6.1
-	StatusNotImplemented                = 501 // RFC 7231, 6.6.2
-	StatusBadGateway                    = 502 // RFC 7231, 6.6.3
-	StatusServiceUnavailable            = 503 // RFC 7231, 6.6.4
-	StatusGatewayTimeout                = 504 // RFC 7231, 6.6.5
-	StatusHTTPVersionNotSupported       = 505 // RFC 7231, 6.6.6
-	StatusVariantAlsoNegotiates         = 506 // RFC 2295, 8.1
-	StatusInsufficientStorage           = 507 // RFC 4918, 11.5
-	StatusLoopDetected                  = 508 // RFC 5842, 7.2
-	StatusNotExtended                   = 510 // RFC 2774, 7
-	StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
-)
-
-// Errors
-var (
-	ErrContinue                      = NewError(StatusContinue)                      // RFC 7231, 6.2.1
-	ErrSwitchingProtocols            = NewError(StatusSwitchingProtocols)            // RFC 7231, 6.2.2
-	ErrProcessing                    = NewError(StatusProcessing)                    // RFC 2518, 10.1
-	ErrEarlyHints                    = NewError(StatusEarlyHints)                    // RFC 8297
-	ErrOK                            = NewError(StatusOK)                            // RFC 7231, 6.3.1
-	ErrCreated                       = NewError(StatusCreated)                       // RFC 7231, 6.3.2
-	ErrAccepted                      = NewError(StatusAccepted)                      // RFC 7231, 6.3.3
-	ErrNonAuthoritativeInfo          = NewError(StatusNonAuthoritativeInfo)          // RFC 7231, 6.3.4
-	ErrNoContent                     = NewError(StatusNoContent)                     // RFC 7231, 6.3.5
-	ErrResetContent                  = NewError(StatusResetContent)                  // RFC 7231, 6.3.6
-	ErrPartialContent                = NewError(StatusPartialContent)                // RFC 7233, 4.1
-	ErrMultiStatus                   = NewError(StatusMultiStatus)                   // RFC 4918, 11.1
-	ErrAlreadyReported               = NewError(StatusAlreadyReported)               // RFC 5842, 7.1
-	ErrIMUsed                        = NewError(StatusIMUsed)                        // RFC 3229, 10.4.1
-	ErrMultipleChoices               = NewError(StatusMultipleChoices)               // RFC 7231, 6.4.1
-	ErrMovedPermanently              = NewError(StatusMovedPermanently)              // RFC 7231, 6.4.2
-	ErrFound                         = NewError(StatusFound)                         // RFC 7231, 6.4.3
-	ErrSeeOther                      = NewError(StatusSeeOther)                      // RFC 7231, 6.4.4
-	ErrNotModified                   = NewError(StatusNotModified)                   // RFC 7232, 4.1
-	ErrUseProxy                      = NewError(StatusUseProxy)                      // RFC 7231, 6.4.5
-	ErrTemporaryRedirect             = NewError(StatusTemporaryRedirect)             // RFC 7231, 6.4.7
-	ErrPermanentRedirect             = NewError(StatusPermanentRedirect)             // RFC 7538, 3
-	ErrBadRequest                    = NewError(StatusBadRequest)                    // RFC 7231, 6.5.1
-	ErrUnauthorized                  = NewError(StatusUnauthorized)                  // RFC 7235, 3.1
-	ErrPaymentRequired               = NewError(StatusPaymentRequired)               // RFC 7231, 6.5.2
-	ErrForbidden                     = NewError(StatusForbidden)                     // RFC 7231, 6.5.3
-	ErrNotFound                      = NewError(StatusNotFound)                      // RFC 7231, 6.5.4
-	ErrMethodNotAllowed              = NewError(StatusMethodNotAllowed)              // RFC 7231, 6.5.5
-	ErrNotAcceptable                 = NewError(StatusNotAcceptable)                 // RFC 7231, 6.5.6
-	ErrProxyAuthRequired             = NewError(StatusProxyAuthRequired)             // RFC 7235, 3.2
-	ErrRequestTimeout                = NewError(StatusRequestTimeout)                // RFC 7231, 6.5.7
-	ErrConflict                      = NewError(StatusConflict)                      // RFC 7231, 6.5.8
-	ErrGone                          = NewError(StatusGone)                          // RFC 7231, 6.5.9
-	ErrLengthRequired                = NewError(StatusLengthRequired)                // RFC 7231, 6.5.10
-	ErrPreconditionFailed            = NewError(StatusPreconditionFailed)            // RFC 7232, 4.2
-	ErrRequestEntityTooLarge         = NewError(StatusRequestEntityTooLarge)         // RFC 7231, 6.5.11
-	ErrRequestURITooLong             = NewError(StatusRequestURITooLong)             // RFC 7231, 6.5.12
-	ErrUnsupportedMediaType          = NewError(StatusUnsupportedMediaType)          // RFC 7231, 6.5.13
-	ErrRequestedRangeNotSatisfiable  = NewError(StatusRequestedRangeNotSatisfiable)  // RFC 7233, 4.4
-	ErrExpectationFailed             = NewError(StatusExpectationFailed)             // RFC 7231, 6.5.14
-	ErrTeapot                        = NewError(StatusTeapot)                        // RFC 7168, 2.3.3
-	ErrMisdirectedRequest            = NewError(StatusMisdirectedRequest)            // RFC 7540, 9.1.2
-	ErrUnprocessableEntity           = NewError(StatusUnprocessableEntity)           // RFC 4918, 11.2
-	ErrLocked                        = NewError(StatusLocked)                        // RFC 4918, 11.3
-	ErrFailedDependency              = NewError(StatusFailedDependency)              // RFC 4918, 11.4
-	ErrTooEarly                      = NewError(StatusTooEarly)                      // RFC 8470, 5.2.
-	ErrUpgradeRequired               = NewError(StatusUpgradeRequired)               // RFC 7231, 6.5.15
-	ErrPreconditionRequired          = NewError(StatusPreconditionRequired)          // RFC 6585, 3
-	ErrTooManyRequests               = NewError(StatusTooManyRequests)               // RFC 6585, 4
-	ErrRequestHeaderFieldsTooLarge   = NewError(StatusRequestHeaderFieldsTooLarge)   // RFC 6585, 5
-	ErrUnavailableForLegalReasons    = NewError(StatusUnavailableForLegalReasons)    // RFC 7725, 3
-	ErrInternalServerError           = NewError(StatusInternalServerError)           // RFC 7231, 6.6.1
-	ErrNotImplemented                = NewError(StatusNotImplemented)                // RFC 7231, 6.6.2
-	ErrBadGateway                    = NewError(StatusBadGateway)                    // RFC 7231, 6.6.3
-	ErrServiceUnavailable            = NewError(StatusServiceUnavailable)            // RFC 7231, 6.6.4
-	ErrGatewayTimeout                = NewError(StatusGatewayTimeout)                // RFC 7231, 6.6.5
-	ErrHTTPVersionNotSupported       = NewError(StatusHTTPVersionNotSupported)       // RFC 7231, 6.6.6
-	ErrVariantAlsoNegotiates         = NewError(StatusVariantAlsoNegotiates)         // RFC 2295, 8.1
-	ErrInsufficientStorage           = NewError(StatusInsufficientStorage)           // RFC 4918, 11.5
-	ErrLoopDetected                  = NewError(StatusLoopDetected)                  // RFC 5842, 7.2
-	ErrNotExtended                   = NewError(StatusNotExtended)                   // RFC 2774, 7
-	ErrNetworkAuthenticationRequired = NewError(StatusNetworkAuthenticationRequired) // RFC 6585, 6
-)
-
-// HTTP Headers were copied from net/http.
-const (
-	HeaderAuthorization                   = "Authorization"
-	HeaderProxyAuthenticate               = "Proxy-Authenticate"
-	HeaderProxyAuthorization              = "Proxy-Authorization"
-	HeaderWWWAuthenticate                 = "WWW-Authenticate"
-	HeaderAge                             = "Age"
-	HeaderCacheControl                    = "Cache-Control"
-	HeaderClearSiteData                   = "Clear-Site-Data"
-	HeaderExpires                         = "Expires"
-	HeaderPragma                          = "Pragma"
-	HeaderWarning                         = "Warning"
-	HeaderAcceptCH                        = "Accept-CH"
-	HeaderAcceptCHLifetime                = "Accept-CH-Lifetime"
-	HeaderContentDPR                      = "Content-DPR"
-	HeaderDPR                             = "DPR"
-	HeaderEarlyData                       = "Early-Data"
-	HeaderSaveData                        = "Save-Data"
-	HeaderViewportWidth                   = "Viewport-Width"
-	HeaderWidth                           = "Width"
-	HeaderETag                            = "ETag"
-	HeaderIfMatch                         = "If-Match"
-	HeaderIfModifiedSince                 = "If-Modified-Since"
-	HeaderIfNoneMatch                     = "If-None-Match"
-	HeaderIfUnmodifiedSince               = "If-Unmodified-Since"
-	HeaderLastModified                    = "Last-Modified"
-	HeaderVary                            = "Vary"
-	HeaderConnection                      = "Connection"
-	HeaderKeepAlive                       = "Keep-Alive"
-	HeaderAccept                          = "Accept"
-	HeaderAcceptCharset                   = "Accept-Charset"
-	HeaderAcceptEncoding                  = "Accept-Encoding"
-	HeaderAcceptLanguage                  = "Accept-Language"
-	HeaderCookie                          = "Cookie"
-	HeaderExpect                          = "Expect"
-	HeaderMaxForwards                     = "Max-Forwards"
-	HeaderSetCookie                       = "Set-Cookie"
-	HeaderAccessControlAllowCredentials   = "Access-Control-Allow-Credentials"
-	HeaderAccessControlAllowHeaders       = "Access-Control-Allow-Headers"
-	HeaderAccessControlAllowMethods       = "Access-Control-Allow-Methods"
-	HeaderAccessControlAllowOrigin        = "Access-Control-Allow-Origin"
-	HeaderAccessControlExposeHeaders      = "Access-Control-Expose-Headers"
-	HeaderAccessControlMaxAge             = "Access-Control-Max-Age"
-	HeaderAccessControlRequestHeaders     = "Access-Control-Request-Headers"
-	HeaderAccessControlRequestMethod      = "Access-Control-Request-Method"
-	HeaderOrigin                          = "Origin"
-	HeaderTimingAllowOrigin               = "Timing-Allow-Origin"
-	HeaderXPermittedCrossDomainPolicies   = "X-Permitted-Cross-Domain-Policies"
-	HeaderDNT                             = "DNT"
-	HeaderTk                              = "Tk"
-	HeaderContentDisposition              = "Content-Disposition"
-	HeaderContentEncoding                 = "Content-Encoding"
-	HeaderContentLanguage                 = "Content-Language"
-	HeaderContentLength                   = "Content-Length"
-	HeaderContentLocation                 = "Content-Location"
-	HeaderContentType                     = "Content-Type"
-	HeaderForwarded                       = "Forwarded"
-	HeaderVia                             = "Via"
-	HeaderXForwardedFor                   = "X-Forwarded-For"
-	HeaderXForwardedHost                  = "X-Forwarded-Host"
-	HeaderXForwardedProto                 = "X-Forwarded-Proto"
-	HeaderXForwardedProtocol              = "X-Forwarded-Protocol"
-	HeaderXForwardedSsl                   = "X-Forwarded-Ssl"
-	HeaderXUrlScheme                      = "X-Url-Scheme"
-	HeaderLocation                        = "Location"
-	HeaderFrom                            = "From"
-	HeaderHost                            = "Host"
-	HeaderReferer                         = "Referer"
-	HeaderReferrerPolicy                  = "Referrer-Policy"
-	HeaderUserAgent                       = "User-Agent"
-	HeaderAllow                           = "Allow"
-	HeaderServer                          = "Server"
-	HeaderAcceptRanges                    = "Accept-Ranges"
-	HeaderContentRange                    = "Content-Range"
-	HeaderIfRange                         = "If-Range"
-	HeaderRange                           = "Range"
-	HeaderContentSecurityPolicy           = "Content-Security-Policy"
-	HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only"
-	HeaderCrossOriginResourcePolicy       = "Cross-Origin-Resource-Policy"
-	HeaderExpectCT                        = "Expect-CT"
-	HeaderFeaturePolicy                   = "Feature-Policy"
-	HeaderPublicKeyPins                   = "Public-Key-Pins"
-	HeaderPublicKeyPinsReportOnly         = "Public-Key-Pins-Report-Only"
-	HeaderStrictTransportSecurity         = "Strict-Transport-Security"
-	HeaderUpgradeInsecureRequests         = "Upgrade-Insecure-Requests"
-	HeaderXContentTypeOptions             = "X-Content-Type-Options"
-	HeaderXDownloadOptions                = "X-Download-Options"
-	HeaderXFrameOptions                   = "X-Frame-Options"
-	HeaderXPoweredBy                      = "X-Powered-By"
-	HeaderXXSSProtection                  = "X-XSS-Protection"
-	HeaderLastEventID                     = "Last-Event-ID"
-	HeaderNEL                             = "NEL"
-	HeaderPingFrom                        = "Ping-From"
-	HeaderPingTo                          = "Ping-To"
-	HeaderReportTo                        = "Report-To"
-	HeaderTE                              = "TE"
-	HeaderTrailer                         = "Trailer"
-	HeaderTransferEncoding                = "Transfer-Encoding"
-	HeaderSecWebSocketAccept              = "Sec-WebSocket-Accept"
-	HeaderSecWebSocketExtensions          = "Sec-WebSocket-Extensions"
-	HeaderSecWebSocketKey                 = "Sec-WebSocket-Key"
-	HeaderSecWebSocketProtocol            = "Sec-WebSocket-Protocol"
-	HeaderSecWebSocketVersion             = "Sec-WebSocket-Version"
-	HeaderAcceptPatch                     = "Accept-Patch"
-	HeaderAcceptPushPolicy                = "Accept-Push-Policy"
-	HeaderAcceptSignature                 = "Accept-Signature"
-	HeaderAltSvc                          = "Alt-Svc"
-	HeaderDate                            = "Date"
-	HeaderIndex                           = "Index"
-	HeaderLargeAllocation                 = "Large-Allocation"
-	HeaderLink                            = "Link"
-	HeaderPushPolicy                      = "Push-Policy"
-	HeaderRetryAfter                      = "Retry-After"
-	HeaderServerTiming                    = "Server-Timing"
-	HeaderSignature                       = "Signature"
-	HeaderSignedHeaders                   = "Signed-Headers"
-	HeaderSourceMap                       = "SourceMap"
-	HeaderUpgrade                         = "Upgrade"
-	HeaderXDNSPrefetchControl             = "X-DNS-Prefetch-Control"
-	HeaderXPingback                       = "X-Pingback"
-	HeaderXRequestID                      = "X-Request-ID"
-	HeaderXRequestedWith                  = "X-Requested-With"
-	HeaderXRobotsTag                      = "X-Robots-Tag"
-	HeaderXUACompatible                   = "X-UA-Compatible"
-)

+ 0 - 21
vendor/github.com/gofiber/utils/LICENSE

@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2020 Fiber
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 0 - 87
vendor/github.com/gofiber/utils/README.md

@@ -1,87 +0,0 @@
-A collection of common functions but with better performance, less allocations and no dependencies created for [Fiber](https://github.com/gofiber/fiber).
-
-```go
-// go test -benchmem -run=^$ -bench=Benchmark_ -count=2
-
-Benchmark_ToLowerBytes/fiber-16                 42847654                25.7 ns/op             0 B/op          0 allocs/op
-Benchmark_ToLowerBytes/fiber-16                 46143196                25.7 ns/op             0 B/op          0 allocs/op
-Benchmark_ToLowerBytes/default-16               17387322                67.4 ns/op            48 B/op          1 allocs/op
-Benchmark_ToLowerBytes/default-16               17906491                67.4 ns/op            48 B/op          1 allocs/op
-
-Benchmark_ToUpperBytes/fiber-16                 46143729                25.7 ns/op             0 B/op          0 allocs/op
-Benchmark_ToUpperBytes/fiber-16                 47989250                25.6 ns/op             0 B/op          0 allocs/op
-Benchmark_ToUpperBytes/default-16               15580854                76.7 ns/op            48 B/op          1 allocs/op
-Benchmark_ToUpperBytes/default-16               15381202                76.9 ns/op            48 B/op          1 allocs/op
-
-Benchmark_TrimRightBytes/fiber-16               70572459                16.3 ns/op             8 B/op          1 allocs/op
-Benchmark_TrimRightBytes/fiber-16               74983597                16.3 ns/op             8 B/op          1 allocs/op
-Benchmark_TrimRightBytes/default-16             16212578                74.1 ns/op            40 B/op          2 allocs/op
-Benchmark_TrimRightBytes/default-16             16434686                74.1 ns/op            40 B/op          2 allocs/op
-
-Benchmark_TrimLeftBytes/fiber-16                74983128                16.3 ns/op             8 B/op          1 allocs/op
-Benchmark_TrimLeftBytes/fiber-16                74985002                16.3 ns/op             8 B/op          1 allocs/op
-Benchmark_TrimLeftBytes/default-16              21047868                56.5 ns/op            40 B/op          2 allocs/op
-Benchmark_TrimLeftBytes/default-16              21048015                56.5 ns/op            40 B/op          2 allocs/op
-
-Benchmark_TrimBytes/fiber-16                    54533307                21.9 ns/op            16 B/op          1 allocs/op
-Benchmark_TrimBytes/fiber-16                    54532812                21.9 ns/op            16 B/op          1 allocs/op
-Benchmark_TrimBytes/default-16                  14282517                84.6 ns/op            48 B/op          2 allocs/op
-Benchmark_TrimBytes/default-16                  14114508                84.7 ns/op            48 B/op          2 allocs/op
-
-Benchmark_EqualFolds/fiber-16                   36355153                32.6 ns/op             0 B/op          0 allocs/op
-Benchmark_EqualFolds/fiber-16                   36355593                32.6 ns/op             0 B/op          0 allocs/op
-Benchmark_EqualFolds/default-16                 15186220                78.1 ns/op             0 B/op          0 allocs/op
-Benchmark_EqualFolds/default-16                 15186412                78.3 ns/op             0 B/op          0 allocs/op
-
-Benchmark_UUID/fiber-16                         23994625                49.8 ns/op            48 B/op          1 allocs/op
-Benchmark_UUID/fiber-16                         23994768                50.1 ns/op            48 B/op          1 allocs/op
-Benchmark_UUID/default-16                        3233772                 371 ns/op           208 B/op          6 allocs/op
-Benchmark_UUID/default-16                        3251295                 370 ns/op           208 B/op          6 allocs/op
-
-Benchmark_GetString/unsafe-16                 1000000000               0.709 ns/op             0 B/op          0 allocs/op
-Benchmark_GetString/unsafe-16                 1000000000               0.713 ns/op             0 B/op          0 allocs/op
-Benchmark_GetString/default-16                  59986202                19.0 ns/op            16 B/op          1 allocs/op
-Benchmark_GetString/default-16                  63142939                19.0 ns/op            16 B/op          1 allocs/op
-
-Benchmark_GetBytes/unsafe-16                   508360195                2.36 ns/op             0 B/op          0 allocs/op
-Benchmark_GetBytes/unsafe-16                   508359979                2.35 ns/op             0 B/op          0 allocs/op
-Benchmark_GetBytes/default-16                   46143019                25.7 ns/op            16 B/op          1 allocs/op
-Benchmark_GetBytes/default-16                   44434734                25.6 ns/op            16 B/op          1 allocs/op
-
-Benchmark_GetMIME/fiber-16                      21423750                56.3 ns/op             0 B/op          0 allocs/op
-Benchmark_GetMIME/fiber-16                      21423559                55.4 ns/op             0 B/op          0 allocs/op
-Benchmark_GetMIME/default-16                     6735282                 173 ns/op             0 B/op          0 allocs/op
-Benchmark_GetMIME/default-16                     6895002                 172 ns/op             0 B/op          0 allocs/op
-
-Benchmark_StatusMessage/fiber-16              1000000000               0.766 ns/op             0 B/op          0 allocs/op
-Benchmark_StatusMessage/fiber-16              1000000000               0.767 ns/op             0 B/op          0 allocs/op
-Benchmark_StatusMessage/default-16             159538528                7.50 ns/op             0 B/op          0 allocs/op
-Benchmark_StatusMessage/default-16             159750830                7.51 ns/op             0 B/op          0 allocs/op
-
-Benchmark_ToUpper/fiber-16                      22217408                53.3 ns/op            48 B/op          1 allocs/op
-Benchmark_ToUpper/fiber-16                      22636554                53.2 ns/op            48 B/op          1 allocs/op
-Benchmark_ToUpper/default-16                    11108600                 108 ns/op            48 B/op          1 allocs/op
-Benchmark_ToUpper/default-16                    11108580                 108 ns/op            48 B/op          1 allocs/op
-
-Benchmark_ToLower/fiber-16                      23994720                49.8 ns/op            48 B/op          1 allocs/op
-Benchmark_ToLower/fiber-16                      23994768                50.1 ns/op            48 B/op          1 allocs/op
-Benchmark_ToLower/default-16                    10808376                 110 ns/op            48 B/op          1 allocs/op
-Benchmark_ToLower/default-16                    10617034                 110 ns/op            48 B/op          1 allocs/op
-
-Benchmark_TrimRight/fiber-16                   413699521                2.94 ns/op             0 B/op          0 allocs/op
-Benchmark_TrimRight/fiber-16                   415131687                2.91 ns/op             0 B/op          0 allocs/op
-Benchmark_TrimRight/default-16                  23994577                49.1 ns/op            32 B/op          1 allocs/op
-Benchmark_TrimRight/default-16                  24484249                49.4 ns/op            32 B/op          1 allocs/op
-
-Benchmark_TrimLeft/fiber-16                    379661170                3.13 ns/op             0 B/op          0 allocs/op
-Benchmark_TrimLeft/fiber-16                    382079941                3.16 ns/op             0 B/op          0 allocs/op
-Benchmark_TrimLeft/default-16                   27900877                41.9 ns/op            32 B/op          1 allocs/op
-Benchmark_TrimLeft/default-16                   28564898                42.0 ns/op            32 B/op          1 allocs/op
-
-Benchmark_Trim/fiber-16                        236632856                 4.96 ns/op            0 B/op          0 allocs/op
-Benchmark_Trim/fiber-16                        237570085                 4.93 ns/op            0 B/op          0 allocs/op
-Benchmark_Trim/default-16                       18457221                 66.0 ns/op           32 B/op          1 allocs/op
-Benchmark_Trim/default-16                       18177328                 65.9 ns/op           32 B/op          1 allocs/op
-Benchmark_Trim/default.trimspace-16            188933770                 6.33 ns/op            0 B/op          0 allocs/op
-Benchmark_Trim/default.trimspace-16            184007649                 6.42 ns/op            0 B/op          0 allocs/op
-```

+ 0 - 62
vendor/github.com/gofiber/utils/assertions.go

@@ -1,62 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package utils
-
-import (
-	"bytes"
-	"fmt"
-	"log"
-	"path/filepath"
-	"reflect"
-	"runtime"
-	"testing"
-	"text/tabwriter"
-)
-
-// AssertEqual checks if values are equal
-func AssertEqual(t testing.TB, expected interface{}, actual interface{}, description ...string) {
-	if reflect.DeepEqual(expected, actual) {
-		return
-	}
-	var aType = "<nil>"
-	var bType = "<nil>"
-	if reflect.ValueOf(expected).IsValid() {
-		aType = reflect.TypeOf(expected).Name()
-	}
-	if reflect.ValueOf(actual).IsValid() {
-		bType = reflect.TypeOf(actual).Name()
-	}
-
-	testName := "AssertEqual"
-	if t != nil {
-		testName = t.Name()
-	}
-
-	_, file, line, _ := runtime.Caller(1)
-
-	var buf bytes.Buffer
-	w := tabwriter.NewWriter(&buf, 0, 0, 5, ' ', 0)
-	fmt.Fprintf(w, "\nTest:\t%s", testName)
-	fmt.Fprintf(w, "\nTrace:\t%s:%d", filepath.Base(file), line)
-	fmt.Fprintf(w, "\nError:\tNot equal")
-	fmt.Fprintf(w, "\nExpect:\t%v\t[%s]", expected, aType)
-	fmt.Fprintf(w, "\nResult:\t%v\t[%s]", actual, bType)
-
-	if len(description) > 0 {
-		fmt.Fprintf(w, "\nDescription:\t%s", description[0])
-	}
-
-	result := ""
-	if err := w.Flush(); err != nil {
-		result = err.Error()
-	} else {
-		result = buf.String()
-	}
-	if t != nil {
-		t.Fatal(result)
-	} else {
-		log.Fatal(result)
-	}
-}

+ 0 - 78
vendor/github.com/gofiber/utils/bytes.go

@@ -1,78 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package utils
-
-// ToLowerBytes is the equivalent of bytes.ToLower
-func ToLowerBytes(b []byte) []byte {
-	for i := 0; i < len(b); i++ {
-		b[i] = toLowerTable[b[i]]
-	}
-	return b
-}
-
-// ToUpperBytes is the equivalent of bytes.ToUpper
-func ToUpperBytes(b []byte) []byte {
-	for i := 0; i < len(b); i++ {
-		b[i] = toUpperTable[b[i]]
-	}
-	return b
-}
-
-// TrimRightBytes is the equivalent of bytes.TrimRight
-func TrimRightBytes(b []byte, cutset byte) []byte {
-	lenStr := len(b)
-	for lenStr > 0 && b[lenStr-1] == cutset {
-		lenStr--
-	}
-	return b[:lenStr]
-}
-
-// TrimLeftBytes is the equivalent of bytes.TrimLeft
-func TrimLeftBytes(b []byte, cutset byte) []byte {
-	lenStr, start := len(b), 0
-	for start < lenStr && b[start] == cutset {
-		start++
-	}
-	return b[start:]
-}
-
-// TrimBytes is the equivalent of bytes.Trim
-func TrimBytes(b []byte, cutset byte) []byte {
-	i, j := 0, len(b)-1
-	for ; i < j; i++ {
-		if b[i] != cutset {
-			break
-		}
-	}
-	for ; i < j; j-- {
-		if b[j] != cutset {
-			break
-		}
-	}
-
-	return b[i : j+1]
-}
-
-// EqualFold the equivalent of bytes.EqualFold
-func EqualsFold(b, s []byte) (equals bool) {
-	n := len(b)
-	equals = n == len(s)
-	if equals {
-		for i := 0; i < n; i++ {
-			if equals = b[i]|0x20 == s[i]|0x20; !equals {
-				break
-			}
-		}
-	}
-	return
-}
-
-// DefaultBytes returns the provided fallback value if []byte is empty
-func DefaultBytes(value []byte, defaultValue []byte) []byte {
-	if len(value) <= 0 {
-		return defaultValue
-	}
-	return value
-}

+ 0 - 83
vendor/github.com/gofiber/utils/common.go

@@ -1,83 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package utils
-
-import (
-	"crypto/rand"
-	"encoding/binary"
-	"encoding/hex"
-	"os"
-	"reflect"
-	"runtime"
-	"sync"
-	"sync/atomic"
-)
-
-const toLowerTable = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
-const toUpperTable = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\u007f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
-
-// Copyright © 2014, Roger Peppe
-// github.com/rogpeppe/fastuuid
-// All rights reserved.
-
-var uuidSeed [24]byte
-var uuidCounter uint64
-var uuidSetup sync.Once
-
-// UUID generates an universally unique identifier (UUID)
-func UUID() string {
-	// Setup seed & counter once
-	uuidSetup.Do(func() {
-		if _, err := rand.Read(uuidSeed[:]); err != nil {
-			return
-		}
-		uuidCounter = binary.LittleEndian.Uint64(uuidSeed[:8])
-	})
-	if atomic.LoadUint64(&uuidCounter) <= 0 {
-		return "00000000-0000-0000-0000-000000000000"
-	}
-	// first 8 bytes differ, taking a slice of the first 16 bytes
-	x := atomic.AddUint64(&uuidCounter, 1)
-	uuid := uuidSeed
-	binary.LittleEndian.PutUint64(uuid[:8], x)
-	uuid[6], uuid[9] = uuid[9], uuid[6]
-
-	// RFC4122 v4
-	uuid[6] = (uuid[6] & 0x0f) | 0x40
-	uuid[8] = uuid[8]&0x3f | 0x80
-
-	// create UUID representation of the first 128 bits
-	b := make([]byte, 36)
-	hex.Encode(b[0:8], uuid[0:4])
-	b[8] = '-'
-	hex.Encode(b[9:13], uuid[4:6])
-	b[13] = '-'
-	hex.Encode(b[14:18], uuid[6:8])
-	b[18] = '-'
-	hex.Encode(b[19:23], uuid[8:10])
-	b[23] = '-'
-	hex.Encode(b[24:], uuid[10:16])
-
-	return GetString(b)
-}
-
-// FunctionName returns function name
-func FunctionName(fn interface{}) string {
-	t := reflect.ValueOf(fn).Type()
-	if t.Kind() == reflect.Func {
-		return runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
-	}
-	return t.String()
-}
-
-// GetArgument check if key is in arguments
-func GetArgument(arg string) bool {
-	for i := range os.Args[1:] {
-		if os.Args[1:][i] == arg {
-			return true
-		}
-	}
-	return false
-}

+ 0 - 104
vendor/github.com/gofiber/utils/convert.go

@@ -1,104 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package utils
-
-import (
-	"reflect"
-	"strconv"
-	"strings"
-	"unsafe"
-)
-
-// #nosec G103
-// GetString returns a string pointer without allocation
-func UnsafeString(b []byte) string {
-	return *(*string)(unsafe.Pointer(&b))
-}
-
-// #nosec G103
-// GetBytes returns a byte pointer without allocation
-func UnsafeBytes(s string) (bs []byte) {
-	sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
-	bh := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
-	bh.Data = sh.Data
-	bh.Len = sh.Len
-	bh.Cap = sh.Len
-	return
-}
-
-// SafeString copies a string to make it immutable
-func SafeString(s string) string {
-	return string(UnsafeBytes(s))
-}
-
-// SafeBytes copies a slice to make it immutable
-func SafeBytes(b []byte) []byte {
-	tmp := make([]byte, len(b))
-	copy(tmp, b)
-	return tmp
-}
-
-const (
-	uByte = 1 << (10 * iota)
-	uKilobyte
-	uMegabyte
-	uGigabyte
-	uTerabyte
-	uPetabyte
-	uExabyte
-)
-
-// ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth.
-// The unit that results in the smallest number greater than or equal to 1 is always chosen.
-func ByteSize(bytes uint64) string {
-	unit := ""
-	value := float64(bytes)
-	switch {
-	case bytes >= uExabyte:
-		unit = "EB"
-		value = value / uExabyte
-	case bytes >= uPetabyte:
-		unit = "PB"
-		value = value / uPetabyte
-	case bytes >= uTerabyte:
-		unit = "TB"
-		value = value / uTerabyte
-	case bytes >= uGigabyte:
-		unit = "GB"
-		value = value / uGigabyte
-	case bytes >= uMegabyte:
-		unit = "MB"
-		value = value / uMegabyte
-	case bytes >= uKilobyte:
-		unit = "KB"
-		value = value / uKilobyte
-	case bytes >= uByte:
-		unit = "B"
-	default:
-		return "0B"
-	}
-	result := strconv.FormatFloat(value, 'f', 1, 64)
-	result = strings.TrimSuffix(result, ".0")
-	return result + unit
-}
-
-// Deprecated fn's
-
-// #nosec G103
-// GetString returns a string pointer without allocation
-func GetString(b []byte) string {
-	return UnsafeString(b)
-}
-
-// #nosec G103
-// GetBytes returns a byte pointer without allocation
-func GetBytes(s string) []byte {
-	return UnsafeBytes(s)
-}
-
-// ImmutableString copies a string to make it immutable
-func ImmutableString(s string) string {
-	return SafeString(s)
-}

+ 0 - 110
vendor/github.com/gofiber/utils/file.go

@@ -1,110 +0,0 @@
-package utils
-
-import (
-	"io"
-	"net/http"
-	"os"
-	pathpkg "path"
-	"path/filepath"
-	"sort"
-)
-
-// Walk walks the filesystem rooted at root, calling walkFn for each file or
-// directory in the filesystem, including root. All errors that arise visiting files
-// and directories are filtered by walkFn. The files are walked in lexical
-// order.
-func Walk(fs http.FileSystem, root string, walkFn filepath.WalkFunc) error {
-	info, err := stat(fs, root)
-	if err != nil {
-		return walkFn(root, nil, err)
-	}
-	return walk(fs, root, info, walkFn)
-}
-
-// #nosec G304
-// ReadFile returns the raw content of a file
-func ReadFile(path string, fs http.FileSystem) ([]byte, error) {
-	if fs != nil {
-		file, err := fs.Open(path)
-		if err != nil {
-			return nil, err
-		}
-		defer file.Close()
-		return io.ReadAll(file)
-	}
-	return os.ReadFile(path)
-}
-
-// readDirNames reads the directory named by dirname and returns
-// a sorted list of directory entries.
-func readDirNames(fs http.FileSystem, dirname string) ([]string, error) {
-	fis, err := readDir(fs, dirname)
-	if err != nil {
-		return nil, err
-	}
-	names := make([]string, len(fis))
-	for i := range fis {
-		names[i] = fis[i].Name()
-	}
-	sort.Strings(names)
-	return names, nil
-}
-
-// walk recursively descends path, calling walkFn.
-func walk(fs http.FileSystem, path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
-	err := walkFn(path, info, nil)
-	if err != nil {
-		if info.IsDir() && err == filepath.SkipDir {
-			return nil
-		}
-		return err
-	}
-
-	if !info.IsDir() {
-		return nil
-	}
-
-	names, err := readDirNames(fs, path)
-	if err != nil {
-		return walkFn(path, info, err)
-	}
-
-	for _, name := range names {
-		filename := pathpkg.Join(path, name)
-		fileInfo, err := stat(fs, filename)
-		if err != nil {
-			if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
-				return err
-			}
-		} else {
-			err = walk(fs, filename, fileInfo, walkFn)
-			if err != nil {
-				if !fileInfo.IsDir() || err != filepath.SkipDir {
-					return err
-				}
-			}
-		}
-	}
-	return nil
-}
-
-// readDir reads the contents of the directory associated with file and
-// returns a slice of FileInfo values in directory order.
-func readDir(fs http.FileSystem, name string) ([]os.FileInfo, error) {
-	f, err := fs.Open(name)
-	if err != nil {
-		return nil, err
-	}
-	defer f.Close()
-	return f.Readdir(0)
-}
-
-// stat returns the FileInfo structure describing file.
-func stat(fs http.FileSystem, name string) (os.FileInfo, error) {
-	f, err := fs.Open(name)
-	if err != nil {
-		return nil, err
-	}
-	defer f.Close()
-	return f.Stat()
-}

+ 0 - 212
vendor/github.com/gofiber/utils/http.go

@@ -1,212 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package utils
-
-const MIMEOctetStream = "application/octet-stream"
-
-// GetMIME returns the content-type of a file extension
-func GetMIME(extension string) (mime string) {
-	if len(extension) == 0 {
-		return mime
-	}
-	if extension[0] == '.' {
-		mime = mimeExtensions[extension[1:]]
-	} else {
-		mime = mimeExtensions[extension]
-	}
-	if len(mime) == 0 {
-		return MIMEOctetStream
-	}
-	return mime
-}
-
-// limits for HTTP statuscodes
-const (
-	statusMessageMin = 100
-	statusMessageMax = 511
-)
-
-// StatusMessage returns the correct message for the provided HTTP statuscode
-func StatusMessage(status int) string {
-	if status < statusMessageMin || status > statusMessageMax {
-		return ""
-	}
-	return statusMessage[status]
-}
-
-// HTTP status codes were copied from net/http.
-var statusMessage = []string{
-	100: "Continue",
-	101: "Switching Protocols",
-	102: "Processing",
-	103: "Early Hints",
-	200: "OK",
-	201: "Created",
-	202: "Accepted",
-	203: "Non-Authoritative Information",
-	204: "No Content",
-	205: "Reset Content",
-	206: "Partial Content",
-	207: "Multi-Status",
-	208: "Already Reported",
-	226: "IM Used",
-	300: "Multiple Choices",
-	301: "Moved Permanently",
-	302: "Found",
-	303: "See Other",
-	304: "Not Modified",
-	305: "Use Proxy",
-	306: "Switch Proxy",
-	307: "Temporary Redirect",
-	308: "Permanent Redirect",
-	400: "Bad Request",
-	401: "Unauthorized",
-	402: "Payment Required",
-	403: "Forbidden",
-	404: "Not Found",
-	405: "Method Not Allowed",
-	406: "Not Acceptable",
-	407: "Proxy Authentication Required",
-	408: "Request Timeout",
-	409: "Conflict",
-	410: "Gone",
-	411: "Length Required",
-	412: "Precondition Failed",
-	413: "Request Entity Too Large",
-	414: "Request URI Too Long",
-	415: "Unsupported Media Type",
-	416: "Requested Range Not Satisfiable",
-	417: "Expectation Failed",
-	418: "I'm a teapot",
-	421: "Misdirected Request",
-	422: "Unprocessable Entity",
-	423: "Locked",
-	424: "Failed Dependency",
-	426: "Upgrade Required",
-	428: "Precondition Required",
-	429: "Too Many Requests",
-	431: "Request Header Fields Too Large",
-	451: "Unavailable For Legal Reasons",
-	500: "Internal Server Error",
-	501: "Not Implemented",
-	502: "Bad Gateway",
-	503: "Service Unavailable",
-	504: "Gateway Timeout",
-	505: "HTTP Version Not Supported",
-	506: "Variant Also Negotiates",
-	507: "Insufficient Storage",
-	508: "Loop Detected",
-	510: "Not Extended",
-	511: "Network Authentication Required",
-}
-
-// MIME types were copied from https://github.com/nginx/nginx/blob/master/conf/mime.types
-var mimeExtensions = map[string]string{
-	"html":    "text/html",
-	"htm":     "text/html",
-	"shtml":   "text/html",
-	"css":     "text/css",
-	"gif":     "image/gif",
-	"jpeg":    "image/jpeg",
-	"jpg":     "image/jpeg",
-	"xml":     "application/xml",
-	"js":      "application/javascript",
-	"atom":    "application/atom+xml",
-	"rss":     "application/rss+xml",
-	"mml":     "text/mathml",
-	"txt":     "text/plain",
-	"jad":     "text/vnd.sun.j2me.app-descriptor",
-	"wml":     "text/vnd.wap.wml",
-	"htc":     "text/x-component",
-	"png":     "image/png",
-	"svg":     "image/svg+xml",
-	"svgz":    "image/svg+xml",
-	"tif":     "image/tiff",
-	"tiff":    "image/tiff",
-	"wbmp":    "image/vnd.wap.wbmp",
-	"webp":    "image/webp",
-	"ico":     "image/x-icon",
-	"jng":     "image/x-jng",
-	"bmp":     "image/x-ms-bmp",
-	"woff":    "font/woff",
-	"woff2":   "font/woff2",
-	"jar":     "application/java-archive",
-	"war":     "application/java-archive",
-	"ear":     "application/java-archive",
-	"json":    "application/json",
-	"hqx":     "application/mac-binhex40",
-	"doc":     "application/msword",
-	"pdf":     "application/pdf",
-	"ps":      "application/postscript",
-	"eps":     "application/postscript",
-	"ai":      "application/postscript",
-	"rtf":     "application/rtf",
-	"m3u8":    "application/vnd.apple.mpegurl",
-	"kml":     "application/vnd.google-earth.kml+xml",
-	"kmz":     "application/vnd.google-earth.kmz",
-	"xls":     "application/vnd.ms-excel",
-	"eot":     "application/vnd.ms-fontobject",
-	"ppt":     "application/vnd.ms-powerpoint",
-	"odg":     "application/vnd.oasis.opendocument.graphics",
-	"odp":     "application/vnd.oasis.opendocument.presentation",
-	"ods":     "application/vnd.oasis.opendocument.spreadsheet",
-	"odt":     "application/vnd.oasis.opendocument.text",
-	"wmlc":    "application/vnd.wap.wmlc",
-	"7z":      "application/x-7z-compressed",
-	"cco":     "application/x-cocoa",
-	"jardiff": "application/x-java-archive-diff",
-	"jnlp":    "application/x-java-jnlp-file",
-	"run":     "application/x-makeself",
-	"pl":      "application/x-perl",
-	"pm":      "application/x-perl",
-	"prc":     "application/x-pilot",
-	"pdb":     "application/x-pilot",
-	"rar":     "application/x-rar-compressed",
-	"rpm":     "application/x-redhat-package-manager",
-	"sea":     "application/x-sea",
-	"swf":     "application/x-shockwave-flash",
-	"sit":     "application/x-stuffit",
-	"tcl":     "application/x-tcl",
-	"tk":      "application/x-tcl",
-	"der":     "application/x-x509-ca-cert",
-	"pem":     "application/x-x509-ca-cert",
-	"crt":     "application/x-x509-ca-cert",
-	"xpi":     "application/x-xpinstall",
-	"xhtml":   "application/xhtml+xml",
-	"xspf":    "application/xspf+xml",
-	"zip":     "application/zip",
-	"bin":     "application/octet-stream",
-	"exe":     "application/octet-stream",
-	"dll":     "application/octet-stream",
-	"deb":     "application/octet-stream",
-	"dmg":     "application/octet-stream",
-	"iso":     "application/octet-stream",
-	"img":     "application/octet-stream",
-	"msi":     "application/octet-stream",
-	"msp":     "application/octet-stream",
-	"msm":     "application/octet-stream",
-	"mid":     "audio/midi",
-	"midi":    "audio/midi",
-	"kar":     "audio/midi",
-	"mp3":     "audio/mpeg",
-	"ogg":     "audio/ogg",
-	"m4a":     "audio/x-m4a",
-	"ra":      "audio/x-realaudio",
-	"3gpp":    "video/3gpp",
-	"3gp":     "video/3gpp",
-	"ts":      "video/mp2t",
-	"mp4":     "video/mp4",
-	"mpeg":    "video/mpeg",
-	"mpg":     "video/mpeg",
-	"mov":     "video/quicktime",
-	"webm":    "video/webm",
-	"flv":     "video/x-flv",
-	"m4v":     "video/x-m4v",
-	"mng":     "video/x-mng",
-	"asx":     "video/x-ms-asf",
-	"asf":     "video/x-ms-asf",
-	"wmv":     "video/x-ms-wmv",
-	"avi":     "video/x-msvideo",
-}

+ 0 - 13
vendor/github.com/gofiber/utils/integer.go

@@ -1,13 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package utils
-
-// DefaultINT returns the provided fallback value if int is 0 or lower
-func DefaultINT(value int, defaultValue int) int {
-	if value <= 0 {
-		return defaultValue
-	}
-	return value
-}

+ 0 - 70
vendor/github.com/gofiber/utils/strings.go

@@ -1,70 +0,0 @@
-// ⚡️ Fiber is an Express inspired web framework written in Go with ☕️
-// 🤖 Github Repository: https://github.com/gofiber/fiber
-// 📌 API Documentation: https://docs.gofiber.io
-
-package utils
-
-// ToLower is the equivalent of strings.ToLower
-func ToLower(b string) string {
-	var res = make([]byte, len(b))
-	copy(res, b)
-	for i := 0; i < len(res); i++ {
-		res[i] = toLowerTable[res[i]]
-	}
-
-	return GetString(res)
-}
-
-// ToUpper is the equivalent of strings.ToUpper
-func ToUpper(b string) string {
-	var res = make([]byte, len(b))
-	copy(res, b)
-	for i := 0; i < len(res); i++ {
-		res[i] = toUpperTable[res[i]]
-	}
-
-	return GetString(res)
-}
-
-// TrimLeft is the equivalent of strings.TrimLeft
-func TrimLeft(s string, cutset byte) string {
-	lenStr, start := len(s), 0
-	for start < lenStr && s[start] == cutset {
-		start++
-	}
-	return s[start:]
-}
-
-// Trim is the equivalent of strings.Trim
-func Trim(s string, cutset byte) string {
-	i, j := 0, len(s)-1
-	for ; i < j; i++ {
-		if s[i] != cutset {
-			break
-		}
-	}
-	for ; i < j; j-- {
-		if s[j] != cutset {
-			break
-		}
-	}
-
-	return s[i : j+1]
-}
-
-// TrimRight is the equivalent of strings.TrimRight
-func TrimRight(s string, cutset byte) string {
-	lenStr := len(s)
-	for lenStr > 0 && s[lenStr-1] == cutset {
-		lenStr--
-	}
-	return s[:lenStr]
-}
-
-// DefaultString returns the provided fallback value if string is empty
-func DefaultString(value string, defaultValue string) string {
-	if len(value) <= 0 {
-		return defaultValue
-	}
-	return value
-}

+ 0 - 27
vendor/github.com/gorilla/schema/LICENSE

@@ -1,27 +0,0 @@
-Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-	 * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-	 * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-	 * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 0 - 90
vendor/github.com/gorilla/schema/README.md

@@ -1,90 +0,0 @@
-schema
-======
-[![GoDoc](https://godoc.org/github.com/gorilla/schema?status.svg)](https://godoc.org/github.com/gorilla/schema) [![Build Status](https://travis-ci.org/gorilla/schema.png?branch=master)](https://travis-ci.org/gorilla/schema)
-[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/schema/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/schema?badge)
-
-
-Package gorilla/schema converts structs to and from form values.
-
-## Example
-
-Here's a quick example: we parse POST form values and then decode them into a struct:
-
-```go
-// Set a Decoder instance as a package global, because it caches
-// meta-data about structs, and an instance can be shared safely.
-var decoder = schema.NewDecoder()
-
-type Person struct {
-    Name  string
-    Phone string
-}
-
-func MyHandler(w http.ResponseWriter, r *http.Request) {
-    err := r.ParseForm()
-    if err != nil {
-        // Handle error
-    }
-
-    var person Person
-
-    // r.PostForm is a map of our POST form values
-    err = decoder.Decode(&person, r.PostForm)
-    if err != nil {
-        // Handle error
-    }
-
-    // Do something with person.Name or person.Phone
-}
-```
-
-Conversely, contents of a struct can be encoded into form values. Here's a variant of the previous example using the Encoder:
-
-```go
-var encoder = schema.NewEncoder()
-
-func MyHttpRequest() {
-    person := Person{"Jane Doe", "555-5555"}
-    form := url.Values{}
-
-    err := encoder.Encode(person, form)
-
-    if err != nil {
-        // Handle error
-    }
-
-    // Use form values, for example, with an http client
-    client := new(http.Client)
-    res, err := client.PostForm("http://my-api.test", form)
-}
-
-```
-
-To define custom names for fields, use a struct tag "schema". To not populate certain fields, use a dash for the name and it will be ignored:
-
-```go
-type Person struct {
-    Name  string `schema:"name,required"`  // custom name, must be supplied
-    Phone string `schema:"phone"`          // custom name
-    Admin bool   `schema:"-"`              // this field is never set
-}
-```
-
-The supported field types in the struct are:
-
-* bool
-* float variants (float32, float64)
-* int variants (int, int8, int16, int32, int64)
-* string
-* uint variants (uint, uint8, uint16, uint32, uint64)
-* struct
-* a pointer to one of the above types
-* a slice or a pointer to a slice of one of the above types
-
-Unsupported types are simply ignored, however custom types can be registered to be converted.
-
-More examples are available on the Gorilla website: https://www.gorillatoolkit.org/pkg/schema
-
-## License
-
-BSD licensed. See the LICENSE file for details.

+ 0 - 305
vendor/github.com/gorilla/schema/cache.go

@@ -1,305 +0,0 @@
-// Copyright 2012 The Gorilla Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package schema
-
-import (
-	"errors"
-	"reflect"
-	"strconv"
-	"strings"
-	"sync"
-)
-
-var invalidPath = errors.New("schema: invalid path")
-
-// newCache returns a new cache.
-func newCache() *cache {
-	c := cache{
-		m:       make(map[reflect.Type]*structInfo),
-		regconv: make(map[reflect.Type]Converter),
-		tag:     "schema",
-	}
-	return &c
-}
-
-// cache caches meta-data about a struct.
-type cache struct {
-	l       sync.RWMutex
-	m       map[reflect.Type]*structInfo
-	regconv map[reflect.Type]Converter
-	tag     string
-}
-
-// registerConverter registers a converter function for a custom type.
-func (c *cache) registerConverter(value interface{}, converterFunc Converter) {
-	c.regconv[reflect.TypeOf(value)] = converterFunc
-}
-
-// parsePath parses a path in dotted notation verifying that it is a valid
-// path to a struct field.
-//
-// It returns "path parts" which contain indices to fields to be used by
-// reflect.Value.FieldByString(). Multiple parts are required for slices of
-// structs.
-func (c *cache) parsePath(p string, t reflect.Type) ([]pathPart, error) {
-	var struc *structInfo
-	var field *fieldInfo
-	var index64 int64
-	var err error
-	parts := make([]pathPart, 0)
-	path := make([]string, 0)
-	keys := strings.Split(p, ".")
-	for i := 0; i < len(keys); i++ {
-		if t.Kind() != reflect.Struct {
-			return nil, invalidPath
-		}
-		if struc = c.get(t); struc == nil {
-			return nil, invalidPath
-		}
-		if field = struc.get(keys[i]); field == nil {
-			return nil, invalidPath
-		}
-		// Valid field. Append index.
-		path = append(path, field.name)
-		if field.isSliceOfStructs && (!field.unmarshalerInfo.IsValid || (field.unmarshalerInfo.IsValid && field.unmarshalerInfo.IsSliceElement)) {
-			// Parse a special case: slices of structs.
-			// i+1 must be the slice index.
-			//
-			// Now that struct can implements TextUnmarshaler interface,
-			// we don't need to force the struct's fields to appear in the path.
-			// So checking i+2 is not necessary anymore.
-			i++
-			if i+1 > len(keys) {
-				return nil, invalidPath
-			}
-			if index64, err = strconv.ParseInt(keys[i], 10, 0); err != nil {
-				return nil, invalidPath
-			}
-			parts = append(parts, pathPart{
-				path:  path,
-				field: field,
-				index: int(index64),
-			})
-			path = make([]string, 0)
-
-			// Get the next struct type, dropping ptrs.
-			if field.typ.Kind() == reflect.Ptr {
-				t = field.typ.Elem()
-			} else {
-				t = field.typ
-			}
-			if t.Kind() == reflect.Slice {
-				t = t.Elem()
-				if t.Kind() == reflect.Ptr {
-					t = t.Elem()
-				}
-			}
-		} else if field.typ.Kind() == reflect.Ptr {
-			t = field.typ.Elem()
-		} else {
-			t = field.typ
-		}
-	}
-	// Add the remaining.
-	parts = append(parts, pathPart{
-		path:  path,
-		field: field,
-		index: -1,
-	})
-	return parts, nil
-}
-
-// get returns a cached structInfo, creating it if necessary.
-func (c *cache) get(t reflect.Type) *structInfo {
-	c.l.RLock()
-	info := c.m[t]
-	c.l.RUnlock()
-	if info == nil {
-		info = c.create(t, "")
-		c.l.Lock()
-		c.m[t] = info
-		c.l.Unlock()
-	}
-	return info
-}
-
-// create creates a structInfo with meta-data about a struct.
-func (c *cache) create(t reflect.Type, parentAlias string) *structInfo {
-	info := &structInfo{}
-	var anonymousInfos []*structInfo
-	for i := 0; i < t.NumField(); i++ {
-		if f := c.createField(t.Field(i), parentAlias); f != nil {
-			info.fields = append(info.fields, f)
-			if ft := indirectType(f.typ); ft.Kind() == reflect.Struct && f.isAnonymous {
-				anonymousInfos = append(anonymousInfos, c.create(ft, f.canonicalAlias))
-			}
-		}
-	}
-	for i, a := range anonymousInfos {
-		others := []*structInfo{info}
-		others = append(others, anonymousInfos[:i]...)
-		others = append(others, anonymousInfos[i+1:]...)
-		for _, f := range a.fields {
-			if !containsAlias(others, f.alias) {
-				info.fields = append(info.fields, f)
-			}
-		}
-	}
-	return info
-}
-
-// createField creates a fieldInfo for the given field.
-func (c *cache) createField(field reflect.StructField, parentAlias string) *fieldInfo {
-	alias, options := fieldAlias(field, c.tag)
-	if alias == "-" {
-		// Ignore this field.
-		return nil
-	}
-	canonicalAlias := alias
-	if parentAlias != "" {
-		canonicalAlias = parentAlias + "." + alias
-	}
-	// Check if the type is supported and don't cache it if not.
-	// First let's get the basic type.
-	isSlice, isStruct := false, false
-	ft := field.Type
-	m := isTextUnmarshaler(reflect.Zero(ft))
-	if ft.Kind() == reflect.Ptr {
-		ft = ft.Elem()
-	}
-	if isSlice = ft.Kind() == reflect.Slice; isSlice {
-		ft = ft.Elem()
-		if ft.Kind() == reflect.Ptr {
-			ft = ft.Elem()
-		}
-	}
-	if ft.Kind() == reflect.Array {
-		ft = ft.Elem()
-		if ft.Kind() == reflect.Ptr {
-			ft = ft.Elem()
-		}
-	}
-	if isStruct = ft.Kind() == reflect.Struct; !isStruct {
-		if c.converter(ft) == nil && builtinConverters[ft.Kind()] == nil {
-			// Type is not supported.
-			return nil
-		}
-	}
-
-	return &fieldInfo{
-		typ:              field.Type,
-		name:             field.Name,
-		alias:            alias,
-		canonicalAlias:   canonicalAlias,
-		unmarshalerInfo:  m,
-		isSliceOfStructs: isSlice && isStruct,
-		isAnonymous:      field.Anonymous,
-		isRequired:       options.Contains("required"),
-	}
-}
-
-// converter returns the converter for a type.
-func (c *cache) converter(t reflect.Type) Converter {
-	return c.regconv[t]
-}
-
-// ----------------------------------------------------------------------------
-
-type structInfo struct {
-	fields []*fieldInfo
-}
-
-func (i *structInfo) get(alias string) *fieldInfo {
-	for _, field := range i.fields {
-		if strings.EqualFold(field.alias, alias) {
-			return field
-		}
-	}
-	return nil
-}
-
-func containsAlias(infos []*structInfo, alias string) bool {
-	for _, info := range infos {
-		if info.get(alias) != nil {
-			return true
-		}
-	}
-	return false
-}
-
-type fieldInfo struct {
-	typ reflect.Type
-	// name is the field name in the struct.
-	name  string
-	alias string
-	// canonicalAlias is almost the same as the alias, but is prefixed with
-	// an embedded struct field alias in dotted notation if this field is
-	// promoted from the struct.
-	// For instance, if the alias is "N" and this field is an embedded field
-	// in a struct "X", canonicalAlias will be "X.N".
-	canonicalAlias string
-	// unmarshalerInfo contains information regarding the
-	// encoding.TextUnmarshaler implementation of the field type.
-	unmarshalerInfo unmarshaler
-	// isSliceOfStructs indicates if the field type is a slice of structs.
-	isSliceOfStructs bool
-	// isAnonymous indicates whether the field is embedded in the struct.
-	isAnonymous bool
-	isRequired  bool
-}
-
-func (f *fieldInfo) paths(prefix string) []string {
-	if f.alias == f.canonicalAlias {
-		return []string{prefix + f.alias}
-	}
-	return []string{prefix + f.alias, prefix + f.canonicalAlias}
-}
-
-type pathPart struct {
-	field *fieldInfo
-	path  []string // path to the field: walks structs using field names.
-	index int      // struct index in slices of structs.
-}
-
-// ----------------------------------------------------------------------------
-
-func indirectType(typ reflect.Type) reflect.Type {
-	if typ.Kind() == reflect.Ptr {
-		return typ.Elem()
-	}
-	return typ
-}
-
-// fieldAlias parses a field tag to get a field alias.
-func fieldAlias(field reflect.StructField, tagName string) (alias string, options tagOptions) {
-	if tag := field.Tag.Get(tagName); tag != "" {
-		alias, options = parseTag(tag)
-	}
-	if alias == "" {
-		alias = field.Name
-	}
-	return alias, options
-}
-
-// tagOptions is the string following a comma in a struct field's tag, or
-// the empty string. It does not include the leading comma.
-type tagOptions []string
-
-// parseTag splits a struct field's url tag into its name and comma-separated
-// options.
-func parseTag(tag string) (string, tagOptions) {
-	s := strings.Split(tag, ",")
-	return s[0], s[1:]
-}
-
-// Contains checks whether the tagOptions contains the specified option.
-func (o tagOptions) Contains(option string) bool {
-	for _, s := range o {
-		if s == option {
-			return true
-		}
-	}
-	return false
-}

+ 0 - 145
vendor/github.com/gorilla/schema/converter.go

@@ -1,145 +0,0 @@
-// Copyright 2012 The Gorilla Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package schema
-
-import (
-	"reflect"
-	"strconv"
-)
-
-type Converter func(string) reflect.Value
-
-var (
-	invalidValue = reflect.Value{}
-	boolType     = reflect.Bool
-	float32Type  = reflect.Float32
-	float64Type  = reflect.Float64
-	intType      = reflect.Int
-	int8Type     = reflect.Int8
-	int16Type    = reflect.Int16
-	int32Type    = reflect.Int32
-	int64Type    = reflect.Int64
-	stringType   = reflect.String
-	uintType     = reflect.Uint
-	uint8Type    = reflect.Uint8
-	uint16Type   = reflect.Uint16
-	uint32Type   = reflect.Uint32
-	uint64Type   = reflect.Uint64
-)
-
-// Default converters for basic types.
-var builtinConverters = map[reflect.Kind]Converter{
-	boolType:    convertBool,
-	float32Type: convertFloat32,
-	float64Type: convertFloat64,
-	intType:     convertInt,
-	int8Type:    convertInt8,
-	int16Type:   convertInt16,
-	int32Type:   convertInt32,
-	int64Type:   convertInt64,
-	stringType:  convertString,
-	uintType:    convertUint,
-	uint8Type:   convertUint8,
-	uint16Type:  convertUint16,
-	uint32Type:  convertUint32,
-	uint64Type:  convertUint64,
-}
-
-func convertBool(value string) reflect.Value {
-	if value == "on" {
-		return reflect.ValueOf(true)
-	} else if v, err := strconv.ParseBool(value); err == nil {
-		return reflect.ValueOf(v)
-	}
-	return invalidValue
-}
-
-func convertFloat32(value string) reflect.Value {
-	if v, err := strconv.ParseFloat(value, 32); err == nil {
-		return reflect.ValueOf(float32(v))
-	}
-	return invalidValue
-}
-
-func convertFloat64(value string) reflect.Value {
-	if v, err := strconv.ParseFloat(value, 64); err == nil {
-		return reflect.ValueOf(v)
-	}
-	return invalidValue
-}
-
-func convertInt(value string) reflect.Value {
-	if v, err := strconv.ParseInt(value, 10, 0); err == nil {
-		return reflect.ValueOf(int(v))
-	}
-	return invalidValue
-}
-
-func convertInt8(value string) reflect.Value {
-	if v, err := strconv.ParseInt(value, 10, 8); err == nil {
-		return reflect.ValueOf(int8(v))
-	}
-	return invalidValue
-}
-
-func convertInt16(value string) reflect.Value {
-	if v, err := strconv.ParseInt(value, 10, 16); err == nil {
-		return reflect.ValueOf(int16(v))
-	}
-	return invalidValue
-}
-
-func convertInt32(value string) reflect.Value {
-	if v, err := strconv.ParseInt(value, 10, 32); err == nil {
-		return reflect.ValueOf(int32(v))
-	}
-	return invalidValue
-}
-
-func convertInt64(value string) reflect.Value {
-	if v, err := strconv.ParseInt(value, 10, 64); err == nil {
-		return reflect.ValueOf(v)
-	}
-	return invalidValue
-}
-
-func convertString(value string) reflect.Value {
-	return reflect.ValueOf(value)
-}
-
-func convertUint(value string) reflect.Value {
-	if v, err := strconv.ParseUint(value, 10, 0); err == nil {
-		return reflect.ValueOf(uint(v))
-	}
-	return invalidValue
-}
-
-func convertUint8(value string) reflect.Value {
-	if v, err := strconv.ParseUint(value, 10, 8); err == nil {
-		return reflect.ValueOf(uint8(v))
-	}
-	return invalidValue
-}
-
-func convertUint16(value string) reflect.Value {
-	if v, err := strconv.ParseUint(value, 10, 16); err == nil {
-		return reflect.ValueOf(uint16(v))
-	}
-	return invalidValue
-}
-
-func convertUint32(value string) reflect.Value {
-	if v, err := strconv.ParseUint(value, 10, 32); err == nil {
-		return reflect.ValueOf(uint32(v))
-	}
-	return invalidValue
-}
-
-func convertUint64(value string) reflect.Value {
-	if v, err := strconv.ParseUint(value, 10, 64); err == nil {
-		return reflect.ValueOf(v)
-	}
-	return invalidValue
-}

+ 0 - 521
vendor/github.com/gorilla/schema/decoder.go

@@ -1,521 +0,0 @@
-// Copyright 2012 The Gorilla Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package schema
-
-import (
-	"encoding"
-	"errors"
-	"fmt"
-	"reflect"
-	"strings"
-)
-
-// NewDecoder returns a new Decoder.
-func NewDecoder() *Decoder {
-	return &Decoder{cache: newCache()}
-}
-
-// Decoder decodes values from a map[string][]string to a struct.
-type Decoder struct {
-	cache             *cache
-	zeroEmpty         bool
-	ignoreUnknownKeys bool
-}
-
-// SetAliasTag changes the tag used to locate custom field aliases.
-// The default tag is "schema".
-func (d *Decoder) SetAliasTag(tag string) {
-	d.cache.tag = tag
-}
-
-// ZeroEmpty controls the behaviour when the decoder encounters empty values
-// in a map.
-// If z is true and a key in the map has the empty string as a value
-// then the corresponding struct field is set to the zero value.
-// If z is false then empty strings are ignored.
-//
-// The default value is false, that is empty values do not change
-// the value of the struct field.
-func (d *Decoder) ZeroEmpty(z bool) {
-	d.zeroEmpty = z
-}
-
-// IgnoreUnknownKeys controls the behaviour when the decoder encounters unknown
-// keys in the map.
-// If i is true and an unknown field is encountered, it is ignored. This is
-// similar to how unknown keys are handled by encoding/json.
-// If i is false then Decode will return an error. Note that any valid keys
-// will still be decoded in to the target struct.
-//
-// To preserve backwards compatibility, the default value is false.
-func (d *Decoder) IgnoreUnknownKeys(i bool) {
-	d.ignoreUnknownKeys = i
-}
-
-// RegisterConverter registers a converter function for a custom type.
-func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) {
-	d.cache.registerConverter(value, converterFunc)
-}
-
-// Decode decodes a map[string][]string to a struct.
-//
-// The first parameter must be a pointer to a struct.
-//
-// The second parameter is a map, typically url.Values from an HTTP request.
-// Keys are "paths" in dotted notation to the struct fields and nested structs.
-//
-// See the package documentation for a full explanation of the mechanics.
-func (d *Decoder) Decode(dst interface{}, src map[string][]string) error {
-	v := reflect.ValueOf(dst)
-	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
-		return errors.New("schema: interface must be a pointer to struct")
-	}
-	v = v.Elem()
-	t := v.Type()
-	errors := MultiError{}
-	for path, values := range src {
-		if parts, err := d.cache.parsePath(path, t); err == nil {
-			if err = d.decode(v, path, parts, values); err != nil {
-				errors[path] = err
-			}
-		} else if !d.ignoreUnknownKeys {
-			errors[path] = UnknownKeyError{Key: path}
-		}
-	}
-	errors.merge(d.checkRequired(t, src))
-	if len(errors) > 0 {
-		return errors
-	}
-	return nil
-}
-
-// checkRequired checks whether required fields are empty
-//
-// check type t recursively if t has struct fields.
-//
-// src is the source map for decoding, we use it here to see if those required fields are included in src
-func (d *Decoder) checkRequired(t reflect.Type, src map[string][]string) MultiError {
-	m, errs := d.findRequiredFields(t, "", "")
-	for key, fields := range m {
-		if isEmptyFields(fields, src) {
-			errs[key] = EmptyFieldError{Key: key}
-		}
-	}
-	return errs
-}
-
-// findRequiredFields recursively searches the struct type t for required fields.
-//
-// canonicalPrefix and searchPrefix are used to resolve full paths in dotted notation
-// for nested struct fields. canonicalPrefix is a complete path which never omits
-// any embedded struct fields. searchPrefix is a user-friendly path which may omit
-// some embedded struct fields to point promoted fields.
-func (d *Decoder) findRequiredFields(t reflect.Type, canonicalPrefix, searchPrefix string) (map[string][]fieldWithPrefix, MultiError) {
-	struc := d.cache.get(t)
-	if struc == nil {
-		// unexpect, cache.get never return nil
-		return nil, MultiError{canonicalPrefix + "*": errors.New("cache fail")}
-	}
-
-	m := map[string][]fieldWithPrefix{}
-	errs := MultiError{}
-	for _, f := range struc.fields {
-		if f.typ.Kind() == reflect.Struct {
-			fcprefix := canonicalPrefix + f.canonicalAlias + "."
-			for _, fspath := range f.paths(searchPrefix) {
-				fm, ferrs := d.findRequiredFields(f.typ, fcprefix, fspath+".")
-				for key, fields := range fm {
-					m[key] = append(m[key], fields...)
-				}
-				errs.merge(ferrs)
-			}
-		}
-		if f.isRequired {
-			key := canonicalPrefix + f.canonicalAlias
-			m[key] = append(m[key], fieldWithPrefix{
-				fieldInfo: f,
-				prefix:    searchPrefix,
-			})
-		}
-	}
-	return m, errs
-}
-
-type fieldWithPrefix struct {
-	*fieldInfo
-	prefix string
-}
-
-// isEmptyFields returns true if all of specified fields are empty.
-func isEmptyFields(fields []fieldWithPrefix, src map[string][]string) bool {
-	for _, f := range fields {
-		for _, path := range f.paths(f.prefix) {
-			v, ok := src[path]
-			if ok && !isEmpty(f.typ, v) {
-				return false
-			}
-			for key := range src {
-				if !isEmpty(f.typ, src[key]) && strings.HasPrefix(key, path) {
-					return false
-				}
-			}
-		}
-	}
-	return true
-}
-
-// isEmpty returns true if value is empty for specific type
-func isEmpty(t reflect.Type, value []string) bool {
-	if len(value) == 0 {
-		return true
-	}
-	switch t.Kind() {
-	case boolType, float32Type, float64Type, intType, int8Type, int32Type, int64Type, stringType, uint8Type, uint16Type, uint32Type, uint64Type:
-		return len(value[0]) == 0
-	}
-	return false
-}
-
-// decode fills a struct field using a parsed path.
-func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values []string) error {
-	// Get the field walking the struct fields by index.
-	for _, name := range parts[0].path {
-		if v.Type().Kind() == reflect.Ptr {
-			if v.IsNil() {
-				v.Set(reflect.New(v.Type().Elem()))
-			}
-			v = v.Elem()
-		}
-
-		// alloc embedded structs
-		if v.Type().Kind() == reflect.Struct {
-			for i := 0; i < v.NumField(); i++ {
-				field := v.Field(i)
-				if field.Type().Kind() == reflect.Ptr && field.IsNil() && v.Type().Field(i).Anonymous == true {
-					field.Set(reflect.New(field.Type().Elem()))
-				}
-			}
-		}
-
-		v = v.FieldByName(name)
-	}
-	// Don't even bother for unexported fields.
-	if !v.CanSet() {
-		return nil
-	}
-
-	// Dereference if needed.
-	t := v.Type()
-	if t.Kind() == reflect.Ptr {
-		t = t.Elem()
-		if v.IsNil() {
-			v.Set(reflect.New(t))
-		}
-		v = v.Elem()
-	}
-
-	// Slice of structs. Let's go recursive.
-	if len(parts) > 1 {
-		idx := parts[0].index
-		if v.IsNil() || v.Len() < idx+1 {
-			value := reflect.MakeSlice(t, idx+1, idx+1)
-			if v.Len() < idx+1 {
-				// Resize it.
-				reflect.Copy(value, v)
-			}
-			v.Set(value)
-		}
-		return d.decode(v.Index(idx), path, parts[1:], values)
-	}
-
-	// Get the converter early in case there is one for a slice type.
-	conv := d.cache.converter(t)
-	m := isTextUnmarshaler(v)
-	if conv == nil && t.Kind() == reflect.Slice && m.IsSliceElement {
-		var items []reflect.Value
-		elemT := t.Elem()
-		isPtrElem := elemT.Kind() == reflect.Ptr
-		if isPtrElem {
-			elemT = elemT.Elem()
-		}
-
-		// Try to get a converter for the element type.
-		conv := d.cache.converter(elemT)
-		if conv == nil {
-			conv = builtinConverters[elemT.Kind()]
-			if conv == nil {
-				// As we are not dealing with slice of structs here, we don't need to check if the type
-				// implements TextUnmarshaler interface
-				return fmt.Errorf("schema: converter not found for %v", elemT)
-			}
-		}
-
-		for key, value := range values {
-			if value == "" {
-				if d.zeroEmpty {
-					items = append(items, reflect.Zero(elemT))
-				}
-			} else if m.IsValid {
-				u := reflect.New(elemT)
-				if m.IsSliceElementPtr {
-					u = reflect.New(reflect.PtrTo(elemT).Elem())
-				}
-				if err := u.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(value)); err != nil {
-					return ConversionError{
-						Key:   path,
-						Type:  t,
-						Index: key,
-						Err:   err,
-					}
-				}
-				if m.IsSliceElementPtr {
-					items = append(items, u.Elem().Addr())
-				} else if u.Kind() == reflect.Ptr {
-					items = append(items, u.Elem())
-				} else {
-					items = append(items, u)
-				}
-			} else if item := conv(value); item.IsValid() {
-				if isPtrElem {
-					ptr := reflect.New(elemT)
-					ptr.Elem().Set(item)
-					item = ptr
-				}
-				if item.Type() != elemT && !isPtrElem {
-					item = item.Convert(elemT)
-				}
-				items = append(items, item)
-			} else {
-				if strings.Contains(value, ",") {
-					values := strings.Split(value, ",")
-					for _, value := range values {
-						if value == "" {
-							if d.zeroEmpty {
-								items = append(items, reflect.Zero(elemT))
-							}
-						} else if item := conv(value); item.IsValid() {
-							if isPtrElem {
-								ptr := reflect.New(elemT)
-								ptr.Elem().Set(item)
-								item = ptr
-							}
-							if item.Type() != elemT && !isPtrElem {
-								item = item.Convert(elemT)
-							}
-							items = append(items, item)
-						} else {
-							return ConversionError{
-								Key:   path,
-								Type:  elemT,
-								Index: key,
-							}
-						}
-					}
-				} else {
-					return ConversionError{
-						Key:   path,
-						Type:  elemT,
-						Index: key,
-					}
-				}
-			}
-		}
-		value := reflect.Append(reflect.MakeSlice(t, 0, 0), items...)
-		v.Set(value)
-	} else {
-		val := ""
-		// Use the last value provided if any values were provided
-		if len(values) > 0 {
-			val = values[len(values)-1]
-		}
-
-		if conv != nil {
-			if value := conv(val); value.IsValid() {
-				v.Set(value.Convert(t))
-			} else {
-				return ConversionError{
-					Key:   path,
-					Type:  t,
-					Index: -1,
-				}
-			}
-		} else if m.IsValid {
-			if m.IsPtr {
-				u := reflect.New(v.Type())
-				if err := u.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(val)); err != nil {
-					return ConversionError{
-						Key:   path,
-						Type:  t,
-						Index: -1,
-						Err:   err,
-					}
-				}
-				v.Set(reflect.Indirect(u))
-			} else {
-				// If the value implements the encoding.TextUnmarshaler interface
-				// apply UnmarshalText as the converter
-				if err := m.Unmarshaler.UnmarshalText([]byte(val)); err != nil {
-					return ConversionError{
-						Key:   path,
-						Type:  t,
-						Index: -1,
-						Err:   err,
-					}
-				}
-			}
-		} else if val == "" {
-			if d.zeroEmpty {
-				v.Set(reflect.Zero(t))
-			}
-		} else if conv := builtinConverters[t.Kind()]; conv != nil {
-			if value := conv(val); value.IsValid() {
-				v.Set(value.Convert(t))
-			} else {
-				return ConversionError{
-					Key:   path,
-					Type:  t,
-					Index: -1,
-				}
-			}
-		} else {
-			return fmt.Errorf("schema: converter not found for %v", t)
-		}
-	}
-	return nil
-}
-
-func isTextUnmarshaler(v reflect.Value) unmarshaler {
-	// Create a new unmarshaller instance
-	m := unmarshaler{}
-	if m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler); m.IsValid {
-		return m
-	}
-	// As the UnmarshalText function should be applied to the pointer of the
-	// type, we check that type to see if it implements the necessary
-	// method.
-	if m.Unmarshaler, m.IsValid = reflect.New(v.Type()).Interface().(encoding.TextUnmarshaler); m.IsValid {
-		m.IsPtr = true
-		return m
-	}
-
-	// if v is []T or *[]T create new T
-	t := v.Type()
-	if t.Kind() == reflect.Ptr {
-		t = t.Elem()
-	}
-	if t.Kind() == reflect.Slice {
-		// Check if the slice implements encoding.TextUnmarshaller
-		if m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler); m.IsValid {
-			return m
-		}
-		// If t is a pointer slice, check if its elements implement
-		// encoding.TextUnmarshaler
-		m.IsSliceElement = true
-		if t = t.Elem(); t.Kind() == reflect.Ptr {
-			t = reflect.PtrTo(t.Elem())
-			v = reflect.Zero(t)
-			m.IsSliceElementPtr = true
-			m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler)
-			return m
-		}
-	}
-
-	v = reflect.New(t)
-	m.Unmarshaler, m.IsValid = v.Interface().(encoding.TextUnmarshaler)
-	return m
-}
-
-// TextUnmarshaler helpers ----------------------------------------------------
-// unmarshaller contains information about a TextUnmarshaler type
-type unmarshaler struct {
-	Unmarshaler encoding.TextUnmarshaler
-	// IsValid indicates whether the resolved type indicated by the other
-	// flags implements the encoding.TextUnmarshaler interface.
-	IsValid bool
-	// IsPtr indicates that the resolved type is the pointer of the original
-	// type.
-	IsPtr bool
-	// IsSliceElement indicates that the resolved type is a slice element of
-	// the original type.
-	IsSliceElement bool
-	// IsSliceElementPtr indicates that the resolved type is a pointer to a
-	// slice element of the original type.
-	IsSliceElementPtr bool
-}
-
-// Errors ---------------------------------------------------------------------
-
-// ConversionError stores information about a failed conversion.
-type ConversionError struct {
-	Key   string       // key from the source map.
-	Type  reflect.Type // expected type of elem
-	Index int          // index for multi-value fields; -1 for single-value fields.
-	Err   error        // low-level error (when it exists)
-}
-
-func (e ConversionError) Error() string {
-	var output string
-
-	if e.Index < 0 {
-		output = fmt.Sprintf("schema: error converting value for %q", e.Key)
-	} else {
-		output = fmt.Sprintf("schema: error converting value for index %d of %q",
-			e.Index, e.Key)
-	}
-
-	if e.Err != nil {
-		output = fmt.Sprintf("%s. Details: %s", output, e.Err)
-	}
-
-	return output
-}
-
-// UnknownKeyError stores information about an unknown key in the source map.
-type UnknownKeyError struct {
-	Key string // key from the source map.
-}
-
-func (e UnknownKeyError) Error() string {
-	return fmt.Sprintf("schema: invalid path %q", e.Key)
-}
-
-// EmptyFieldError stores information about an empty required field.
-type EmptyFieldError struct {
-	Key string // required key in the source map.
-}
-
-func (e EmptyFieldError) Error() string {
-	return fmt.Sprintf("%v is empty", e.Key)
-}
-
-// MultiError stores multiple decoding errors.
-//
-// Borrowed from the App Engine SDK.
-type MultiError map[string]error
-
-func (e MultiError) Error() string {
-	s := ""
-	for _, err := range e {
-		s = err.Error()
-		break
-	}
-	switch len(e) {
-	case 0:
-		return "(0 errors)"
-	case 1:
-		return s
-	case 2:
-		return s + " (and 1 other error)"
-	}
-	return fmt.Sprintf("%s (and %d other errors)", s, len(e)-1)
-}
-
-func (e MultiError) merge(errors MultiError) {
-	for key, err := range errors {
-		if e[key] == nil {
-			e[key] = err
-		}
-	}
-}

+ 0 - 148
vendor/github.com/gorilla/schema/doc.go

@@ -1,148 +0,0 @@
-// Copyright 2012 The Gorilla Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Package gorilla/schema fills a struct with form values.
-
-The basic usage is really simple. Given this struct:
-
-	type Person struct {
-		Name  string
-		Phone string
-	}
-
-...we can fill it passing a map to the Decode() function:
-
-	values := map[string][]string{
-		"Name":  {"John"},
-		"Phone": {"999-999-999"},
-	}
-	person := new(Person)
-	decoder := schema.NewDecoder()
-	decoder.Decode(person, values)
-
-This is just a simple example and it doesn't make a lot of sense to create
-the map manually. Typically it will come from a http.Request object and
-will be of type url.Values, http.Request.Form, or http.Request.MultipartForm:
-
-	func MyHandler(w http.ResponseWriter, r *http.Request) {
-		err := r.ParseForm()
-
-		if err != nil {
-			// Handle error
-		}
-
-		decoder := schema.NewDecoder()
-		// r.PostForm is a map of our POST form values
-		err := decoder.Decode(person, r.PostForm)
-
-		if err != nil {
-			// Handle error
-		}
-
-		// Do something with person.Name or person.Phone
-	}
-
-Note: it is a good idea to set a Decoder instance as a package global,
-because it caches meta-data about structs, and an instance can be shared safely:
-
-	var decoder = schema.NewDecoder()
-
-To define custom names for fields, use a struct tag "schema". To not populate
-certain fields, use a dash for the name and it will be ignored:
-
-	type Person struct {
-		Name  string `schema:"name"`  // custom name
-		Phone string `schema:"phone"` // custom name
-		Admin bool   `schema:"-"`     // this field is never set
-	}
-
-The supported field types in the destination struct are:
-
-	* bool
-	* float variants (float32, float64)
-	* int variants (int, int8, int16, int32, int64)
-	* string
-	* uint variants (uint, uint8, uint16, uint32, uint64)
-	* struct
-	* a pointer to one of the above types
-	* a slice or a pointer to a slice of one of the above types
-
-Non-supported types are simply ignored, however custom types can be registered
-to be converted.
-
-To fill nested structs, keys must use a dotted notation as the "path" for the
-field. So for example, to fill the struct Person below:
-
-	type Phone struct {
-		Label  string
-		Number string
-	}
-
-	type Person struct {
-		Name  string
-		Phone Phone
-	}
-
-...the source map must have the keys "Name", "Phone.Label" and "Phone.Number".
-This means that an HTML form to fill a Person struct must look like this:
-
-	<form>
-		<input type="text" name="Name">
-		<input type="text" name="Phone.Label">
-		<input type="text" name="Phone.Number">
-	</form>
-
-Single values are filled using the first value for a key from the source map.
-Slices are filled using all values for a key from the source map. So to fill
-a Person with multiple Phone values, like:
-
-	type Person struct {
-		Name   string
-		Phones []Phone
-	}
-
-...an HTML form that accepts three Phone values would look like this:
-
-	<form>
-		<input type="text" name="Name">
-		<input type="text" name="Phones.0.Label">
-		<input type="text" name="Phones.0.Number">
-		<input type="text" name="Phones.1.Label">
-		<input type="text" name="Phones.1.Number">
-		<input type="text" name="Phones.2.Label">
-		<input type="text" name="Phones.2.Number">
-	</form>
-
-Notice that only for slices of structs the slice index is required.
-This is needed for disambiguation: if the nested struct also had a slice
-field, we could not translate multiple values to it if we did not use an
-index for the parent struct.
-
-There's also the possibility to create a custom type that implements the
-TextUnmarshaler interface, and in this case there's no need to register
-a converter, like:
-
-	type Person struct {
-	  Emails []Email
-	}
-
-	type Email struct {
-	  *mail.Address
-	}
-
-	func (e *Email) UnmarshalText(text []byte) (err error) {
-		e.Address, err = mail.ParseAddress(string(text))
-		return
-	}
-
-...an HTML form that accepts three Email values would look like this:
-
-	<form>
-		<input type="email" name="Emails.0">
-		<input type="email" name="Emails.1">
-		<input type="email" name="Emails.2">
-	</form>
-*/
-package schema

+ 0 - 202
vendor/github.com/gorilla/schema/encoder.go

@@ -1,202 +0,0 @@
-package schema
-
-import (
-	"errors"
-	"fmt"
-	"reflect"
-	"strconv"
-)
-
-type encoderFunc func(reflect.Value) string
-
-// Encoder encodes values from a struct into url.Values.
-type Encoder struct {
-	cache  *cache
-	regenc map[reflect.Type]encoderFunc
-}
-
-// NewEncoder returns a new Encoder with defaults.
-func NewEncoder() *Encoder {
-	return &Encoder{cache: newCache(), regenc: make(map[reflect.Type]encoderFunc)}
-}
-
-// Encode encodes a struct into map[string][]string.
-//
-// Intended for use with url.Values.
-func (e *Encoder) Encode(src interface{}, dst map[string][]string) error {
-	v := reflect.ValueOf(src)
-
-	return e.encode(v, dst)
-}
-
-// RegisterEncoder registers a converter for encoding a custom type.
-func (e *Encoder) RegisterEncoder(value interface{}, encoder func(reflect.Value) string) {
-	e.regenc[reflect.TypeOf(value)] = encoder
-}
-
-// SetAliasTag changes the tag used to locate custom field aliases.
-// The default tag is "schema".
-func (e *Encoder) SetAliasTag(tag string) {
-	e.cache.tag = tag
-}
-
-// isValidStructPointer test if input value is a valid struct pointer.
-func isValidStructPointer(v reflect.Value) bool {
-	return v.Type().Kind() == reflect.Ptr && v.Elem().IsValid() && v.Elem().Type().Kind() == reflect.Struct
-}
-
-func isZero(v reflect.Value) bool {
-	switch v.Kind() {
-	case reflect.Func:
-	case reflect.Map, reflect.Slice:
-		return v.IsNil() || v.Len() == 0
-	case reflect.Array:
-		z := true
-		for i := 0; i < v.Len(); i++ {
-			z = z && isZero(v.Index(i))
-		}
-		return z
-	case reflect.Struct:
-		type zero interface {
-			IsZero() bool
-		}
-		if v.Type().Implements(reflect.TypeOf((*zero)(nil)).Elem()) {
-			iz := v.MethodByName("IsZero").Call([]reflect.Value{})[0]
-			return iz.Interface().(bool)
-		}
-		z := true
-		for i := 0; i < v.NumField(); i++ {
-			z = z && isZero(v.Field(i))
-		}
-		return z
-	}
-	// Compare other types directly:
-	z := reflect.Zero(v.Type())
-	return v.Interface() == z.Interface()
-}
-
-func (e *Encoder) encode(v reflect.Value, dst map[string][]string) error {
-	if v.Kind() == reflect.Ptr {
-		v = v.Elem()
-	}
-	if v.Kind() != reflect.Struct {
-		return errors.New("schema: interface must be a struct")
-	}
-	t := v.Type()
-
-	errors := MultiError{}
-
-	for i := 0; i < v.NumField(); i++ {
-		name, opts := fieldAlias(t.Field(i), e.cache.tag)
-		if name == "-" {
-			continue
-		}
-
-		// Encode struct pointer types if the field is a valid pointer and a struct.
-		if isValidStructPointer(v.Field(i)) {
-			e.encode(v.Field(i).Elem(), dst)
-			continue
-		}
-
-		encFunc := typeEncoder(v.Field(i).Type(), e.regenc)
-
-		// Encode non-slice types and custom implementations immediately.
-		if encFunc != nil {
-			value := encFunc(v.Field(i))
-			if opts.Contains("omitempty") && isZero(v.Field(i)) {
-				continue
-			}
-
-			dst[name] = append(dst[name], value)
-			continue
-		}
-
-		if v.Field(i).Type().Kind() == reflect.Struct {
-			e.encode(v.Field(i), dst)
-			continue
-		}
-
-		if v.Field(i).Type().Kind() == reflect.Slice {
-			encFunc = typeEncoder(v.Field(i).Type().Elem(), e.regenc)
-		}
-
-		if encFunc == nil {
-			errors[v.Field(i).Type().String()] = fmt.Errorf("schema: encoder not found for %v", v.Field(i))
-			continue
-		}
-
-		// Encode a slice.
-		if v.Field(i).Len() == 0 && opts.Contains("omitempty") {
-			continue
-		}
-
-		dst[name] = []string{}
-		for j := 0; j < v.Field(i).Len(); j++ {
-			dst[name] = append(dst[name], encFunc(v.Field(i).Index(j)))
-		}
-	}
-
-	if len(errors) > 0 {
-		return errors
-	}
-	return nil
-}
-
-func typeEncoder(t reflect.Type, reg map[reflect.Type]encoderFunc) encoderFunc {
-	if f, ok := reg[t]; ok {
-		return f
-	}
-
-	switch t.Kind() {
-	case reflect.Bool:
-		return encodeBool
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return encodeInt
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
-		return encodeUint
-	case reflect.Float32:
-		return encodeFloat32
-	case reflect.Float64:
-		return encodeFloat64
-	case reflect.Ptr:
-		f := typeEncoder(t.Elem(), reg)
-		return func(v reflect.Value) string {
-			if v.IsNil() {
-				return "null"
-			}
-			return f(v.Elem())
-		}
-	case reflect.String:
-		return encodeString
-	default:
-		return nil
-	}
-}
-
-func encodeBool(v reflect.Value) string {
-	return strconv.FormatBool(v.Bool())
-}
-
-func encodeInt(v reflect.Value) string {
-	return strconv.FormatInt(int64(v.Int()), 10)
-}
-
-func encodeUint(v reflect.Value) string {
-	return strconv.FormatUint(uint64(v.Uint()), 10)
-}
-
-func encodeFloat(v reflect.Value, bits int) string {
-	return strconv.FormatFloat(v.Float(), 'f', 6, bits)
-}
-
-func encodeFloat32(v reflect.Value) string {
-	return encodeFloat(v, 32)
-}
-
-func encodeFloat64(v reflect.Value) string {
-	return encodeFloat(v, 64)
-}
-
-func encodeString(v reflect.Value) string {
-	return v.String()
-}

+ 0 - 9
vendor/modules.txt

@@ -1,24 +1,15 @@
 # github.com/andybalholm/brotli v1.0.6
 ## explicit; go 1.12
 github.com/andybalholm/brotli
-# github.com/gofiber/fiber v1.14.6
-## explicit; go 1.11
-github.com/gofiber/fiber
 # github.com/gofiber/fiber/v2 v2.50.0
 ## explicit; go 1.20
 github.com/gofiber/fiber/v2
 github.com/gofiber/fiber/v2/internal/schema
 github.com/gofiber/fiber/v2/log
 github.com/gofiber/fiber/v2/utils
-# github.com/gofiber/utils v1.1.0
-## explicit; go 1.17
-github.com/gofiber/utils
 # github.com/google/uuid v1.4.0
 ## explicit
 github.com/google/uuid
-# github.com/gorilla/schema v1.2.0
-## explicit
-github.com/gorilla/schema
 # github.com/klauspost/compress v1.17.2
 ## explicit; go 1.18
 github.com/klauspost/compress/flate