ci: address multiple lint rules (#2869)

* ci: explicitly disable tagalign

Tagalign requires awkward manual formatting and doesn't provide much
value for readability.

* ci: enable mirror linter

mirror warns against certain cases of useless conversion between string
and []byte.

* ci: enable perfsprint linter

This linter encourages replacing several functions from the fmt package
with faster alternatives. While fixing issues, I also added a few
exported error types rather than returning a naked errors.New().
pull/2870/head
nickajacks1 2024-02-19 05:33:10 -08:00 committed by GitHub
parent 529086aa84
commit 4c68e0242d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 79 additions and 73 deletions

View File

@ -164,7 +164,8 @@ issues:
linters: linters:
disable: disable:
- spancheck - spancheck # opentelemetry, irrelevant
- tagalign # requires awkward manual formatting of struct tags
enable: enable:
- asasalint - asasalint
- asciicheck - asciicheck
@ -199,7 +200,7 @@ linters:
- grouper - grouper
- inamedparam - inamedparam
- loggercheck - loggercheck
# - mirror # TODO https://github.com/gofiber/fiber/issues/2816 - mirror
- misspell - misspell
- nakedret - nakedret
- nilerr - nilerr
@ -208,7 +209,7 @@ linters:
- nolintlint - nolintlint
- nonamedreturns - nonamedreturns
- nosprintfhostport - nosprintfhostport
# - perfsprint # TODO https://github.com/gofiber/fiber/issues/2816 - perfsprint
- predeclared - predeclared
- promlinter - promlinter
- reassign - reassign
@ -217,7 +218,6 @@ linters:
- sqlclosecheck - sqlclosecheck
- staticcheck - staticcheck
- stylecheck - stylecheck
# - tagalign # TODO https://github.com/gofiber/fiber/issues/2816
- tagliatelle - tagliatelle
- testifylint - testifylint
# - testpackage # TODO: Enable once https://github.com/gofiber/fiber/issues/2252 is implemented # - testpackage # TODO: Enable once https://github.com/gofiber/fiber/issues/2252 is implemented

View File

@ -1,7 +1,7 @@
package retry package retry
import ( import (
"fmt" "errors"
"testing" "testing"
"time" "time"
@ -44,9 +44,9 @@ func TestExponentialBackoff_Retry(t *testing.T) {
MaxRetryCount: 5, MaxRetryCount: 5,
}, },
f: func() error { f: func() error {
return fmt.Errorf("failed function") return errors.New("failed function")
}, },
expErr: fmt.Errorf("failed function"), expErr: errors.New("failed function"),
}, },
} }

9
app.go
View File

@ -897,7 +897,7 @@ func (app *App) ShutdownWithContext(ctx context.Context) error {
app.mutex.Lock() app.mutex.Lock()
defer app.mutex.Unlock() defer app.mutex.Unlock()
if app.server == nil { if app.server == nil {
return fmt.Errorf("shutdown: server is not running") return ErrNotRunning
} }
return app.server.ShutdownWithContext(ctx) return app.server.ShutdownWithContext(ctx)
} }
@ -948,7 +948,7 @@ func (app *App) Test(req *http.Request, msTimeout ...int) (*http.Response, error
var returned bool var returned bool
defer func() { defer func() {
if !returned { if !returned {
channel <- fmt.Errorf("runtime.Goexit() called in handler or server panic") channel <- ErrHandlerExited
} }
}() }()
@ -1071,10 +1071,7 @@ func (app *App) ErrorHandler(ctx Ctx, err error) error {
// errors before calling the application's error handler method. // errors before calling the application's error handler method.
func (app *App) serverErrorHandler(fctx *fasthttp.RequestCtx, err error) { func (app *App) serverErrorHandler(fctx *fasthttp.RequestCtx, err error) {
// Acquire Ctx with fasthttp request from pool // Acquire Ctx with fasthttp request from pool
c, ok := app.AcquireCtx().(*DefaultCtx) c := app.AcquireCtx()
if !ok {
panic(fmt.Errorf("failed to type-assert to *DefaultCtx"))
}
c.Reset(fctx) c.Reset(fctx)
defer app.ReleaseCtx(c) defer app.ReleaseCtx(c)

View File

@ -1672,7 +1672,7 @@ func Test_App_ReadBodyStream(t *testing.T) {
require.NoError(t, err, "app.Test(req)") require.NoError(t, err, "app.Test(req)")
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
require.NoError(t, err, "io.ReadAll(resp.Body)") require.NoError(t, err, "io.ReadAll(resp.Body)")
require.Equal(t, fmt.Sprintf("true %s", testString), string(body)) require.Equal(t, "true "+testString, string(body))
} }
func Test_App_DisablePreParseMultipartForm(t *testing.T) { func Test_App_DisablePreParseMultipartForm(t *testing.T) {
@ -1688,7 +1688,7 @@ func Test_App_DisablePreParseMultipartForm(t *testing.T) {
return err return err
} }
if !req.IsBodyStream() { if !req.IsBodyStream() {
return fmt.Errorf("not a body stream") return errors.New("not a body stream")
} }
file, err := mpf.File["test"][0].Open() file, err := mpf.File["test"][0].Open()
if err != nil { if err != nil {
@ -1700,7 +1700,7 @@ func Test_App_DisablePreParseMultipartForm(t *testing.T) {
return fmt.Errorf("failed to read: %w", err) return fmt.Errorf("failed to read: %w", err)
} }
if n != len(testString) { if n != len(testString) {
return fmt.Errorf("bad read length") return errors.New("bad read length")
} }
return c.Send(buffer) return c.Send(buffer)
}) })

View File

@ -1556,7 +1556,7 @@ func (*structValidator) ValidateStruct(out any) error {
out = reflect.ValueOf(out).Elem().Interface() out = reflect.ValueOf(out).Elem().Interface()
sq, ok := out.(simpleQuery) sq, ok := out.(simpleQuery)
if !ok { if !ok {
return fmt.Errorf("failed to type-assert to simpleQuery") return errors.New("failed to type-assert to simpleQuery")
} }
if sq.Name != "john" { if sq.Name != "john" {

View File

@ -5,6 +5,7 @@ import (
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"errors"
"fmt" "fmt"
"io" "io"
"mime/multipart" "mime/multipart"
@ -885,7 +886,7 @@ func AcquireClient() *Client {
} }
c, ok := v.(*Client) c, ok := v.(*Client)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to *Client")) panic(errors.New("failed to type-assert to *Client"))
} }
return c return c
} }
@ -911,7 +912,7 @@ func ReleaseClient(c *Client) {
func AcquireAgent() *Agent { func AcquireAgent() *Agent {
a, ok := agentPool.Get().(*Agent) a, ok := agentPool.Get().(*Agent)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to *Agent")) panic(errors.New("failed to type-assert to *Agent"))
} }
return a return a
} }
@ -938,7 +939,7 @@ func AcquireResponse() *Response {
} }
r, ok := v.(*Response) r, ok := v.(*Response)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to *Response")) panic(errors.New("failed to type-assert to *Response"))
} }
return r return r
} }
@ -965,7 +966,7 @@ func AcquireArgs() *Args {
} }
a, ok := v.(*Args) a, ok := v.(*Args)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to *Args")) panic(errors.New("failed to type-assert to *Args"))
} }
return a return a
} }
@ -990,7 +991,7 @@ func AcquireFormFile() *FormFile {
} }
ff, ok := v.(*FormFile) ff, ok := v.(*FormFile)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to *FormFile")) panic(errors.New("failed to type-assert to *FormFile"))
} }
return ff return ff
} }

View File

@ -8,7 +8,6 @@ import (
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"errors" "errors"
"fmt"
"io" "io"
"mime/multipart" "mime/multipart"
"net" "net"
@ -630,7 +629,7 @@ type readErrorConn struct {
} }
func (*readErrorConn) Read(_ []byte) (int, error) { func (*readErrorConn) Read(_ []byte) (int, error) {
return 0, fmt.Errorf("error") return 0, errors.New("error")
} }
func (*readErrorConn) Write(p []byte) (int, error) { func (*readErrorConn) Write(p []byte) (int, error) {

11
ctx.go
View File

@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"io" "io"
"mime/multipart" "mime/multipart"
@ -615,7 +616,7 @@ func (c *DefaultCtx) Hostname() string {
func (c *DefaultCtx) Port() string { func (c *DefaultCtx) Port() string {
tcpaddr, ok := c.fasthttp.RemoteAddr().(*net.TCPAddr) tcpaddr, ok := c.fasthttp.RemoteAddr().(*net.TCPAddr)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to *net.TCPAddr")) panic(errors.New("failed to type-assert to *net.TCPAddr"))
} }
return strconv.Itoa(tcpaddr.Port) return strconv.Itoa(tcpaddr.Port)
} }
@ -1108,12 +1109,8 @@ func (c *DefaultCtx) Queries() map[string]string {
// age := Query[int](c, "age") // Returns 8 // age := Query[int](c, "age") // Returns 8
// unknown := Query[string](c, "unknown", "default") // Returns "default" since the query parameter "unknown" is not found // unknown := Query[string](c, "unknown", "default") // Returns "default" since the query parameter "unknown" is not found
func Query[V QueryType](c Ctx, key string, defaultValue ...V) V { func Query[V QueryType](c Ctx, key string, defaultValue ...V) V {
ctx, ok := c.(*DefaultCtx)
if !ok {
panic(fmt.Errorf("failed to type-assert to *DefaultCtx"))
}
var v V var v V
q := ctx.app.getString(ctx.fasthttp.QueryArgs().Peek(key)) q := c.App().getString(c.Context().QueryArgs().Peek(key))
switch any(v).(type) { switch any(v).(type) {
case int: case int:
@ -1151,7 +1148,7 @@ func Query[V QueryType](c Ctx, key string, defaultValue ...V) V {
if q == "" && len(defaultValue) > 0 { if q == "" && len(defaultValue) > 0 {
return defaultValue[0] return defaultValue[0]
} }
return assertValueType[V, []byte](ctx.app.getBytes(q)) return assertValueType[V, []byte](c.App().getBytes(q))
default: default:
if len(defaultValue) > 0 { if len(defaultValue) > 0 {
return defaultValue[0] return defaultValue[0]

View File

@ -7,7 +7,7 @@ package fiber
import ( import (
"context" "context"
"crypto/tls" "crypto/tls"
"fmt" "errors"
"io" "io"
"mime/multipart" "mime/multipart"
"sync" "sync"
@ -446,7 +446,7 @@ func (app *App) NewCtx(fctx *fasthttp.RequestCtx) Ctx {
func (app *App) AcquireCtx() Ctx { func (app *App) AcquireCtx() Ctx {
ctx, ok := app.pool.Get().(Ctx) ctx, ok := app.pool.Get().(Ctx)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to Ctx")) panic(errors.New("failed to type-assert to Ctx"))
} }
return ctx return ctx
} }

View File

@ -1271,7 +1271,7 @@ func Test_Ctx_FormValue(t *testing.T) {
require.NoError(t, writer.Close()) require.NoError(t, writer.Close())
req := httptest.NewRequest(MethodPost, "/test", body) req := httptest.NewRequest(MethodPost, "/test", body)
req.Header.Set("Content-Type", fmt.Sprintf("multipart/form-data; boundary=%s", writer.Boundary())) req.Header.Set("Content-Type", "multipart/form-data; boundary="+writer.Boundary())
req.Header.Set("Content-Length", strconv.Itoa(len(body.Bytes()))) req.Header.Set("Content-Length", strconv.Itoa(len(body.Bytes())))
resp, err := app.Test(req) resp, err := app.Test(req)
@ -2155,7 +2155,7 @@ func Test_Ctx_MultipartForm(t *testing.T) {
require.NoError(t, writer.Close()) require.NoError(t, writer.Close())
req := httptest.NewRequest(MethodPost, "/test", body) req := httptest.NewRequest(MethodPost, "/test", body)
req.Header.Set(HeaderContentType, fmt.Sprintf("multipart/form-data; boundary=%s", writer.Boundary())) req.Header.Set(HeaderContentType, "multipart/form-data; boundary="+writer.Boundary())
req.Header.Set(HeaderContentLength, strconv.Itoa(len(body.Bytes()))) req.Header.Set(HeaderContentLength, strconv.Itoa(len(body.Bytes())))
resp, err := app.Test(req) resp, err := app.Test(req)
@ -4181,7 +4181,7 @@ func Test_Ctx_Render_Go_Template(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
}() }()
_, err = file.Write([]byte("template")) _, err = file.WriteString("template")
require.NoError(t, err) require.NoError(t, err)
err = file.Close() err = file.Close()

View File

@ -11,9 +11,13 @@ import (
// Unexported because users will hopefully never need to see it. // Unexported because users will hopefully never need to see it.
var errUnreachable = errors.New("fiber: unreachable code, please create an issue at github.com/gofiber/fiber") var errUnreachable = errors.New("fiber: unreachable code, please create an issue at github.com/gofiber/fiber")
// Graceful shutdown errors // General errors
var ( var (
ErrGracefulTimeout = errors.New("shutdown: graceful timeout has been reached, exiting") ErrGracefulTimeout = errors.New("shutdown: graceful timeout has been reached, exiting")
// ErrNotRunning indicates that a Shutdown method was called when the server was not running.
ErrNotRunning = errors.New("shutdown: server is not running")
// ErrHandlerExited is returned by App.Test if a handler panics or calls runtime.Goexit().
ErrHandlerExited = errors.New("runtime.Goexit() called in handler or server panic")
) )
// Fiber redirection errors // Fiber redirection errors

View File

@ -7,6 +7,7 @@ package fiber
import ( import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"errors"
"fmt" "fmt"
"io" "io"
"net" "net"
@ -41,25 +42,27 @@ func getTLSConfig(ln net.Listener) *tls.Config {
pointer := reflect.ValueOf(ln) pointer := reflect.ValueOf(ln)
// Is it a tls.listener? // Is it a tls.listener?
if pointer.String() == "<*tls.listener Value>" { if pointer.String() != "<*tls.listener Value>" {
// Copy value from pointer return nil
if val := reflect.Indirect(pointer); val.Type() != nil { }
// Get private field from value
if field := val.FieldByName("config"); field.Type() != nil { // Copy value from pointer
// Copy value from pointer field (unsafe) if val := reflect.Indirect(pointer); val.Type() != nil {
newval := reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())) //nolint:gosec // Probably the only way to extract the *tls.Config from a net.Listener. TODO: Verify there really is no easier way without using unsafe. // Get private field from value
if newval.Type() != nil { if field := val.FieldByName("config"); field.Type() != nil {
// Get element from pointer // Copy value from pointer field (unsafe)
if elem := newval.Elem(); elem.Type() != nil { newval := reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())) //nolint:gosec // Probably the only way to extract the *tls.Config from a net.Listener. TODO: Verify there really is no easier way without using unsafe.
// Cast value to *tls.Config if newval.Type() == nil {
c, ok := elem.Interface().(*tls.Config) return nil
//nolint:revive // We need to check if the type assertion was successful }
if !ok { // Get element from pointer
panic(fmt.Errorf("failed to type-assert to *tls.Config")) if elem := newval.Elem(); elem.Type() != nil {
} // Cast value to *tls.Config
return c c, ok := elem.Interface().(*tls.Config)
} if !ok {
panic(errors.New("failed to type-assert to *tls.Config"))
} }
return c
} }
} }
} }

View File

@ -50,7 +50,7 @@ func Test_Cache_Expired(t *testing.T) {
app.Use(New(Config{Expiration: 2 * time.Second})) app.Use(New(Config{Expiration: 2 * time.Second}))
app.Get("/", func(c fiber.Ctx) error { app.Get("/", func(c fiber.Ctx) error {
return c.SendString(fmt.Sprintf("%d", time.Now().UnixNano())) return c.SendString(strconv.FormatInt(time.Now().UnixNano(), 10))
}) })
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
@ -88,7 +88,7 @@ func Test_Cache(t *testing.T) {
app.Use(New()) app.Use(New())
app.Get("/", func(c fiber.Ctx) error { app.Get("/", func(c fiber.Ctx) error {
now := fmt.Sprintf("%d", time.Now().UnixNano()) now := strconv.FormatInt(time.Now().UnixNano(), 10)
return c.SendString(now) return c.SendString(now)
}) })
@ -307,7 +307,7 @@ func Test_Cache_Invalid_Expiration(t *testing.T) {
app.Use(cache) app.Use(cache)
app.Get("/", func(c fiber.Ctx) error { app.Get("/", func(c fiber.Ctx) error {
now := fmt.Sprintf("%d", time.Now().UnixNano()) now := strconv.FormatInt(time.Now().UnixNano(), 10)
return c.SendString(now) return c.SendString(now)
}) })
@ -513,8 +513,7 @@ func Test_CustomExpiration(t *testing.T) {
app.Get("/", func(c fiber.Ctx) error { app.Get("/", func(c fiber.Ctx) error {
c.Response().Header.Add("Cache-Time", "1") c.Response().Header.Add("Cache-Time", "1")
now := fmt.Sprintf("%d", time.Now().UnixNano()) return c.SendString(strconv.FormatInt(time.Now().UnixNano(), 10))
return c.SendString(now)
}) })
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
@ -620,7 +619,7 @@ func Test_Cache_WithHead(t *testing.T) {
app.Use(New()) app.Use(New())
handler := func(c fiber.Ctx) error { handler := func(c fiber.Ctx) error {
now := fmt.Sprintf("%d", time.Now().UnixNano()) now := strconv.FormatInt(time.Now().UnixNano(), 10)
return c.SendString(now) return c.SendString(now)
} }
app.Route("/").Get(handler).Head(handler) app.Route("/").Get(handler).Head(handler)

View File

@ -70,7 +70,7 @@ func appWithConfig(t *testing.T, c *fiber.Config) *fiber.App {
}, "/", func(c fiber.Ctx) error { }, "/", func(c fiber.Ctx) error {
valid, ok := c.Locals(localsKeyTestValid).(bool) valid, ok := c.Locals(localsKeyTestValid).(bool)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to bool")) panic(errors.New("failed to type-assert to bool"))
} }
if !valid { if !valid {
return errors.New("handler called even though validation failed") return errors.New("handler called even though validation failed")

View File

@ -1,6 +1,7 @@
package filesystem package filesystem
import ( import (
"errors"
"fmt" "fmt"
"html" "html"
"io/fs" "io/fs"
@ -12,6 +13,11 @@ import (
"github.com/gofiber/fiber/v3" "github.com/gofiber/fiber/v3"
) )
// ErrDirListingNotSupported is returned from the filesystem middleware handler if
// the given fs.FS does not support directory listing. This is uncommon and may
// indicate an issue with the FS implementation.
var ErrDirListingNotSupported = errors.New("failed to type-assert to fs.ReadDirFile")
func getFileExtension(p string) string { func getFileExtension(p string) string {
n := strings.LastIndexByte(p, '.') n := strings.LastIndexByte(p, '.')
if n < 0 { if n < 0 {
@ -23,7 +29,7 @@ func getFileExtension(p string) string {
func dirList(c fiber.Ctx, f fs.File) error { func dirList(c fiber.Ctx, f fs.File) error {
ff, ok := f.(fs.ReadDirFile) ff, ok := f.(fs.ReadDirFile)
if !ok { if !ok {
return fmt.Errorf("failed to type-assert to fs.ReadDirFile") return ErrDirListingNotSupported
} }
fileinfos, err := ff.ReadDir(-1) fileinfos, err := ff.ReadDir(-1)
if err != nil { if err != nil {

View File

@ -70,7 +70,7 @@ func New(config ...Config) fiber.Handler {
subdomains = "; includeSubDomains" subdomains = "; includeSubDomains"
} }
if cfg.HSTSPreloadEnabled { if cfg.HSTSPreloadEnabled {
subdomains = fmt.Sprintf("%s; preload", subdomains) subdomains += "; preload"
} }
c.Set(fiber.HeaderStrictTransportSecurity, fmt.Sprintf("max-age=%d%s", cfg.HSTSMaxAge, subdomains)) c.Set(fiber.HeaderStrictTransportSecurity, fmt.Sprintf("max-age=%d%s", cfg.HSTSMaxAge, subdomains))
} }

View File

@ -3,7 +3,6 @@ package keyauth
import ( import (
"context" "context"
"fmt"
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -300,7 +299,7 @@ func TestCustomSuccessAndFailureHandlers(t *testing.T) {
// Create a request with a valid API key in the Authorization header // Create a request with a valid API key in the Authorization header
req := httptest.NewRequest(fiber.MethodGet, "/", nil) req := httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", CorrectKey)) req.Header.Add("Authorization", "Bearer "+CorrectKey)
// Send the request to the app // Send the request to the app
res, err = app.Test(req) res, err = app.Test(req)
@ -363,7 +362,7 @@ func TestCustomNextFunc(t *testing.T) {
// Create a request with a different path and send it to the app with correct key // Create a request with a different path and send it to the app with correct key
req = httptest.NewRequest(fiber.MethodGet, "/not-allowed", nil) req = httptest.NewRequest(fiber.MethodGet, "/not-allowed", nil)
req.Header.Add("Authorization", fmt.Sprintf("Basic %s", CorrectKey)) req.Header.Add("Authorization", "Basic "+CorrectKey)
res, err = app.Test(req) res, err = app.Test(req)
require.NoError(t, err) require.NoError(t, err)
@ -397,7 +396,7 @@ func TestAuthSchemeToken(t *testing.T) {
// Create a request with a valid API key in the "Token" Authorization header // Create a request with a valid API key in the "Token" Authorization header
req := httptest.NewRequest(fiber.MethodGet, "/", nil) req := httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Add("Authorization", fmt.Sprintf("Token %s", CorrectKey)) req.Header.Add("Authorization", "Token "+CorrectKey)
// Send the request to the app // Send the request to the app
res, err := app.Test(req) res, err := app.Test(req)
@ -445,7 +444,7 @@ func TestAuthSchemeBasic(t *testing.T) {
// Create a request with a valid API key in the "Authorization" header using the "Basic" scheme // Create a request with a valid API key in the "Authorization" header using the "Basic" scheme
req := httptest.NewRequest(fiber.MethodGet, "/", nil) req := httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Add("Authorization", fmt.Sprintf("Basic %s", CorrectKey)) req.Header.Add("Authorization", "Basic "+CorrectKey)
// Send the request to the app // Send the request to the app
res, err = app.Test(req) res, err = app.Test(req)

View File

@ -5,7 +5,7 @@
package fiber package fiber
import ( import (
"fmt" "errors"
"strings" "strings"
"sync" "sync"
@ -53,7 +53,7 @@ type RedirectConfig struct {
func AcquireRedirect() *Redirect { func AcquireRedirect() *Redirect {
redirect, ok := redirectPool.Get().(*Redirect) redirect, ok := redirectPool.Get().(*Redirect)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to *Redirect")) panic(errors.New("failed to type-assert to *Redirect"))
} }
return redirect return redirect

View File

@ -5,6 +5,7 @@
package fiber package fiber
import ( import (
"errors"
"fmt" "fmt"
"html" "html"
"sort" "sort"
@ -209,12 +210,12 @@ func (app *App) requestHandler(rctx *fasthttp.RequestCtx) {
if app.newCtxFunc != nil { if app.newCtxFunc != nil {
c, ok = app.AcquireCtx().(CustomCtx) c, ok = app.AcquireCtx().(CustomCtx)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to CustomCtx")) panic(errors.New("failed to type-assert to CustomCtx"))
} }
} else { } else {
c, ok = app.AcquireCtx().(*DefaultCtx) c, ok = app.AcquireCtx().(*DefaultCtx)
if !ok { if !ok {
panic(fmt.Errorf("failed to type-assert to *DefaultCtx")) panic(errors.New("failed to type-assert to *DefaultCtx"))
} }
} }
c.Reset(rctx) c.Reset(rctx)