diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 6a4ec76843..0000000000 --- a/.editorconfig +++ /dev/null @@ -1,8 +0,0 @@ -; This file is for unifying the coding style for different editors and IDEs. -; More information at http://editorconfig.org -; This style originates from https://github.com/fewagency/best-practices -root = true - -[*] -charset = utf-8 -end_of_line = lf diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 963a68ec2d..0000000000 --- a/.gitattributes +++ /dev/null @@ -1,12 +0,0 @@ -# Handle line endings automatically for files detected as text -# and leave all files detected as binary untouched. -* text=auto eol=lf - -# Force batch scripts to always use CRLF line endings so that if a repo is accessed -# in Windows via a file share from Linux, the scripts will work. -*.{cmd,[cC][mM][dD]} text eol=crlf -*.{bat,[bB][aA][tT]} text eol=crlf - -# Force bash scripts to always use LF line endings so that if a repo is accessed -# in Unix via a file share from Windows, the scripts will work. -*.sh text eol=lf diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index b259fccfd7..4397113a31 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -1,28 +1,17 @@ -# Adapted from https://github.com/golangci/golangci-lint-action/blob/b56f6f529003f1c81d4d759be6bd5f10bf9a0fa0/README.md#how-to-use - -name: golangci-lint on: - push: - tags: - - v* - branches: - - master - - main - pull_request: -permissions: - contents: read + push: + branches: + - master + - main + pull_request: +name: Linter jobs: - golangci: - name: lint + Golint: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 + - name: Fetch Repository + uses: actions/checkout@v3 + - name: Run Golint + uses: reviewdog/action-golangci-lint@v2 with: - # NOTE: Keep this in sync with the version from go.mod - go-version: 1.19 - - uses: actions/checkout@v3 - - name: golangci-lint - uses: golangci/golangci-lint-action@v3 - with: - # NOTE: Keep this in sync with the version from .golangci.yml - version: v1.50.1 + golangci_lint_flags: "--tests=false" diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000000..e7d8bade55 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,17 @@ +on: + push: + branches: + - master + - main + pull_request: +name: Security +jobs: + Gosec: + runs-on: ubuntu-latest + steps: + - name: Fetch Repository + uses: actions/checkout@v3 + - name: Run Gosec + uses: securego/gosec@master + with: + args: -exclude-dir=internal/*/ ./... diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 87e975e036..0000000000 --- a/.golangci.yml +++ /dev/null @@ -1,258 +0,0 @@ -# Created based on v1.50.1 -# NOTE: Keep this in sync with the version in .github/workflows/linter.yml - -run: - modules-download-mode: readonly - skip-dirs-use-default: false - skip-dirs: - - internal # TODO: Also apply proper linting for internal dir - -output: - sort-results: true - -linters-settings: - # TODO: Eventually enable these checks - # depguard: - # include-go-root: true - # packages: - # - flag - # - io/ioutil - # - reflect - # - unsafe - # packages-with-error-message: - # - flag: '`flag` package is only allowed in main.go' - # - io/ioutil: '`io/ioutil` package is deprecated, use the `io` and `os` package instead' - # - reflect: '`reflect` package is dangerous to use' - # - unsafe: '`unsafe` package is dangerous to use' - - errcheck: - check-type-assertions: true - check-blank: true - disable-default-exclusions: true - - errchkjson: - report-no-exported: true - - exhaustive: - default-signifies-exhaustive: true - - forbidigo: - forbid: - - ^(fmt\.Print(|f|ln)|print|println)$ - - 'http\.Default(Client|Transport)' - # TODO: Eventually enable these patterns - # - 'time\.Sleep' - # - 'panic' - - gci: - sections: - - standard - - prefix(github.com/gofiber/fiber) - - default - - blank - - dot - custom-order: true - - gocritic: - disabled-checks: - - ifElseChain - - gofumpt: - module-path: github.com/gofiber/fiber - extra-rules: true - - gosec: - config: - global: - audit: true - - govet: - check-shadowing: true - enable-all: true - disable: - - shadow - - fieldalignment - - grouper: - import-require-single-import: true - import-require-grouping: true - - misspell: - locale: US - - nolintlint: - require-explanation: true - require-specific: true - - nonamedreturns: - report-error-in-defer: true - - predeclared: - q: true - - promlinter: - strict: true - - revive: - enable-all-rules: true - rules: - # Provided by gomnd linter - - name: add-constant - disabled: true - - name: argument-limit - disabled: true - # Provided by bidichk - - name: banned-characters - disabled: true - - name: cognitive-complexity - disabled: true - - name: cyclomatic - disabled: true - - name: exported - disabled: true - - name: file-header - disabled: true - - name: function-result-limit - disabled: true - - name: function-length - disabled: true - - name: line-length-limit - disabled: true - - name: max-public-structs - disabled: true - - name: modifies-parameter - disabled: true - - name: nested-structs - disabled: true - - name: package-comments - disabled: true - - stylecheck: - checks: - - all - - -ST1000 - - -ST1020 - - -ST1021 - - -ST1022 - - tagliatelle: - case: - rules: - json: snake - - #tenv: - # all: true - - #unparam: - # check-exported: true - - wrapcheck: - ignorePackageGlobs: - - github.com/gofiber/fiber/* - - github.com/valyala/fasthttp - -issues: - exclude-use-default: false - -linters: - enable: - - asasalint - - asciicheck - - bidichk - - bodyclose - - containedctx - - contextcheck - # - cyclop - # - deadcode - # - decorder - - depguard - - dogsled - # - dupl - # - dupword - - durationcheck - - errcheck - - errchkjson - - errname - - errorlint - - execinquery - - exhaustive - # - exhaustivestruct - # - exhaustruct - - exportloopref - - forbidigo - - forcetypeassert - # - funlen - - gci - - gochecknoglobals - - gochecknoinits - # - gocognit - - goconst - - gocritic - # - gocyclo - # - godot - # - godox - # - goerr113 - - gofmt - - gofumpt - # - goheader - - goimports - # - golint - - gomnd - - gomoddirectives - # - gomodguard - - goprintffuncname - - gosec - - gosimple - - govet - - grouper - # - ifshort - # - importas - - ineffassign - # - interfacebloat - # - interfacer - # - ireturn - # - lll - - loggercheck - # - maintidx - # - makezero - # - maligned - - misspell - - nakedret - # - nestif - - nilerr - - nilnil - # - nlreturn - - noctx - - nolintlint - - nonamedreturns - # - nosnakecase - - nosprintfhostport - # - paralleltest # TODO: Enable once https://github.com/gofiber/fiber/issues/2254 is implemented - # - prealloc - - predeclared - - promlinter - - reassign - - revive - - rowserrcheck - # - scopelint - - sqlclosecheck - - staticcheck - # - structcheck - - stylecheck - - tagliatelle - # - tenv # TODO: Enable once we drop support for Go 1.16 - # - testableexamples - # - testpackage # TODO: Enable once https://github.com/gofiber/fiber/issues/2252 is implemented - - thelper - # - tparallel # TODO: Enable once https://github.com/gofiber/fiber/issues/2254 is implemented - - typecheck - - unconvert - - unparam - - unused - - usestdlibvars - # - varcheck - # - varnamelen - - wastedassign - - whitespace - - wrapcheck - # - wsl diff --git a/app.go b/app.go index 002da62c4b..e299075b37 100644 --- a/app.go +++ b/app.go @@ -14,7 +14,6 @@ import ( "encoding/xml" "errors" "fmt" - "log" "net" "net/http" "net/http/httputil" @@ -25,7 +24,6 @@ import ( "time" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -308,7 +306,7 @@ type Config struct { // FEATURE: v2.3.x // The router executes the same handler by default if StrictRouting or CaseSensitive is disabled. - // Enabling RedirectFixedPath will change this behavior into a client redirect to the original route path. + // 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. // // Default: false @@ -456,8 +454,6 @@ const ( ) // HTTP methods enabled by default -// -//nolint:gochecknoglobals // Using a global var is fine here var DefaultMethods = []string{ MethodGet, MethodHead, @@ -471,7 +467,7 @@ var DefaultMethods = []string{ } // DefaultErrorHandler that process return errors from handlers -func DefaultErrorHandler(c *Ctx, err error) error { +var DefaultErrorHandler = func(c *Ctx, err error) error { code := StatusInternalServerError var e *Error if errors.As(err, &e) { @@ -523,7 +519,7 @@ func New(config ...Config) *App { if app.config.ETag { if !IsChild() { - log.Printf("[Warning] Config.ETag is deprecated since v2.0.6, please use 'middleware/etag'.\n") + fmt.Println("[Warning] Config.ETag is deprecated since v2.0.6, please use 'middleware/etag'.") } } @@ -591,7 +587,7 @@ func (app *App) handleTrustedProxy(ipAddress string) { if strings.Contains(ipAddress, "/") { _, ipNet, err := net.ParseCIDR(ipAddress) if err != nil { - log.Printf("[Warning] IP range %q could not be parsed: %v\n", ipAddress, err) + fmt.Printf("[Warning] IP range %q could not be parsed: %v\n", ipAddress, err) } else { app.config.trustedProxyRanges = append(app.config.trustedProxyRanges, ipNet) } @@ -826,7 +822,7 @@ func (app *App) Config() Config { } // Handler returns the server handler. -func (app *App) Handler() fasthttp.RequestHandler { //revive:disable-line:confusing-naming // Having both a Handler() (uppercase) and a handler() (lowercase) is fine. TODO: Use nolint:revive directive instead. See https://github.com/golangci/golangci-lint/issues/3476 +func (app *App) Handler() fasthttp.RequestHandler { // prepare the server for the start app.startupProcess() return app.handler @@ -891,7 +887,7 @@ func (app *App) Hooks() *Hooks { // 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(req *http.Request, msTimeout ...int) (*http.Response, error) { +func (app *App) Test(req *http.Request, msTimeout ...int) (resp *http.Response, err error) { // Set timeout timeout := 1000 if len(msTimeout) > 0 { @@ -906,15 +902,15 @@ func (app *App) Test(req *http.Request, msTimeout ...int) (*http.Response, error // Dump raw http request dump, err := httputil.DumpRequest(req, true) if err != nil { - return nil, fmt.Errorf("failed to dump request: %w", err) + return nil, err } // Create test connection conn := new(testConn) // Write raw http request - if _, err := conn.r.Write(dump); err != nil { - return nil, fmt.Errorf("failed to write: %w", err) + if _, err = conn.r.Write(dump); err != nil { + return nil, err } // prepare the server for the start app.startupProcess() @@ -947,7 +943,7 @@ func (app *App) Test(req *http.Request, msTimeout ...int) (*http.Response, error } // Check for errors - if err != nil && !errors.Is(err, fasthttp.ErrGetOnly) { + if err != nil && err != fasthttp.ErrGetOnly { return nil, err } @@ -955,17 +951,12 @@ func (app *App) Test(req *http.Request, msTimeout ...int) (*http.Response, error buffer := bufio.NewReader(&conn.w) // Convert raw http response to *http.Response - res, err := http.ReadResponse(buffer, req) - if err != nil { - return nil, fmt.Errorf("failed to read response: %w", err) - } - - return res, nil + return http.ReadResponse(buffer, req) } type disableLogger struct{} -func (*disableLogger) Printf(_ string, _ ...interface{}) { +func (dl *disableLogger) Printf(_ string, _ ...interface{}) { // fmt.Println(fmt.Sprintf(format, args...)) } @@ -976,7 +967,7 @@ func (app *App) init() *App { // Only load templates if a view engine is specified if app.config.Views != nil { if err := app.config.Views.Load(); err != nil { - log.Printf("[Warning]: failed to load views: %v\n", err) + fmt.Printf("views: %v\n", err) } } @@ -1048,30 +1039,25 @@ func (app *App) ErrorHandler(ctx *Ctx, err error) error { // errors before calling the application's error handler method. func (app *App) serverErrorHandler(fctx *fasthttp.RequestCtx, err error) { c := app.AcquireCtx(fctx) - defer app.ReleaseCtx(c) - - var errNetOP *net.OpError - - switch { - case errors.As(err, new(*fasthttp.ErrSmallBuffer)): + if _, ok := err.(*fasthttp.ErrSmallBuffer); ok { err = ErrRequestHeaderFieldsTooLarge - case errors.As(err, &errNetOP) && errNetOP.Timeout(): + } else if netErr, ok := err.(*net.OpError); ok && netErr.Timeout() { err = ErrRequestTimeout - case errors.Is(err, fasthttp.ErrBodyTooLarge): + } else if err == fasthttp.ErrBodyTooLarge { err = ErrRequestEntityTooLarge - case errors.Is(err, fasthttp.ErrGetOnly): + } else if err == fasthttp.ErrGetOnly { err = ErrMethodNotAllowed - case strings.Contains(err.Error(), "timeout"): + } else if strings.Contains(err.Error(), "timeout") { err = ErrRequestTimeout - default: + } else { err = NewError(StatusBadRequest, err.Error()) } if catch := app.ErrorHandler(c, err); catch != nil { - log.Printf("serverErrorHandler: failed to call ErrorHandler: %v\n", catch) - _ = c.SendStatus(StatusInternalServerError) //nolint:errcheck // It is fine to ignore the error here - return + _ = c.SendStatus(StatusInternalServerError) } + + app.ReleaseCtx(c) } // startupProcess Is the method which executes all the necessary processes just before the start of the server. diff --git a/app_test.go b/app_test.go index 5f4fbc8767..7182ee6c8a 100644 --- a/app_test.go +++ b/app_test.go @@ -2,7 +2,6 @@ // 🤖 Github Repository: https://github.com/gofiber/fiber // 📌 API Documentation: https://docs.gofiber.io -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package fiber import ( @@ -24,16 +23,15 @@ import ( "time" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" "github.com/valyala/fasthttp/fasthttputil" ) -func testEmptyHandler(_ *Ctx) error { +var testEmptyHandler = func(c *Ctx) error { return nil } -func testStatus200(t *testing.T, app *App, url, method string) { +func testStatus200(t *testing.T, app *App, url string, method string) { t.Helper() req := httptest.NewRequest(method, url, nil) @@ -44,8 +42,6 @@ func testStatus200(t *testing.T, app *App, url, method string) { } func testErrorResponse(t *testing.T, err error, resp *http.Response, expectedBodyError string) { - t.Helper() - utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, 500, resp.StatusCode, "Status code") @@ -144,6 +140,7 @@ func Test_App_ServerErrorHandler_SmallReadBuffer(t *testing.T) { logHeaderSlice := make([]string, 5000) request.Header.Set("Very-Long-Header", strings.Join(logHeaderSlice, "-")) _, err := app.Test(request) + if err == nil { t.Error("Expect an error at app.Test(request)") } @@ -473,6 +470,7 @@ func Test_App_Use_MultiplePrefix(t *testing.T) { body, err = io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "/test/doe", string(body)) + } func Test_App_Use_StrictRouting(t *testing.T) { @@ -517,7 +515,7 @@ func Test_App_Add_Method_Test(t *testing.T) { } }() - methods := append(DefaultMethods, "JOHN") //nolint:gocritic // We want a new slice here + methods := append(DefaultMethods, "JOHN") app := New(Config{ RequestMethods: methods, }) @@ -782,7 +780,7 @@ func Test_App_ShutdownWithTimeout(t *testing.T) { case <-timer.C: t.Fatal("idle connections not closed on shutdown") case err := <-shutdownErr: - if err == nil || !errors.Is(err, context.DeadlineExceeded) { + if err == nil || err != context.DeadlineExceeded { t.Fatalf("unexpected err %v. Expecting %v", err, context.DeadlineExceeded) } } @@ -854,7 +852,7 @@ func Test_App_Static_MaxAge(t *testing.T) { app.Static("/", "./.github", Static{MaxAge: 100}) - resp, err := app.Test(httptest.NewRequest(MethodGet, "/index.html", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/index.html", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, 200, resp.StatusCode, "Status code") utils.AssertEqual(t, false, resp.Header.Get(HeaderContentLength) == "") @@ -868,19 +866,19 @@ func Test_App_Static_Custom_CacheControl(t *testing.T) { app := New() app.Static("/", "./.github", Static{ModifyResponse: func(c *Ctx) error { - if strings.Contains(c.GetRespHeader("Content-Type"), "text/html") { + if strings.Contains(string(c.GetRespHeader("Content-Type")), "text/html") { c.Response().Header.Set("Cache-Control", "no-cache, no-store, must-revalidate") } return nil }}) - resp, err := app.Test(httptest.NewRequest(MethodGet, "/index.html", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/index.html", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, "no-cache, no-store, must-revalidate", resp.Header.Get(HeaderCacheControl), "CacheControl Control") - respNormal, errNormal := app.Test(httptest.NewRequest(MethodGet, "/config.yml", nil)) - utils.AssertEqual(t, nil, errNormal, "app.Test(req)") - utils.AssertEqual(t, "", respNormal.Header.Get(HeaderCacheControl), "CacheControl Control") + normal_resp, normal_err := app.Test(httptest.NewRequest("GET", "/config.yml", nil)) + utils.AssertEqual(t, nil, normal_err, "app.Test(req)") + utils.AssertEqual(t, "", normal_resp.Header.Get(HeaderCacheControl), "CacheControl Control") } // go test -run Test_App_Static_Download @@ -892,7 +890,7 @@ func Test_App_Static_Download(t *testing.T) { app.Static("/fiber.png", "./.github/testdata/fs/img/fiber.png", Static{Download: true}) - resp, err := app.Test(httptest.NewRequest(MethodGet, "/fiber.png", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/fiber.png", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, 200, resp.StatusCode, "Status code") utils.AssertEqual(t, false, resp.Header.Get(HeaderContentLength) == "") @@ -1069,7 +1067,7 @@ func Test_App_Static_Next(t *testing.T) { t.Run("app.Static is skipped: invoking Get handler", func(t *testing.T) { t.Parallel() - req := httptest.NewRequest(MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Set("X-Custom-Header", "skip") resp, err := app.Test(req) utils.AssertEqual(t, nil, err) @@ -1084,7 +1082,7 @@ func Test_App_Static_Next(t *testing.T) { t.Run("app.Static is not skipped: serving index.html", func(t *testing.T) { t.Parallel() - req := httptest.NewRequest(MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Set("X-Custom-Header", "don't skip") resp, err := app.Test(req) utils.AssertEqual(t, nil, err) @@ -1381,7 +1379,7 @@ func Test_Test_DumpError(t *testing.T) { resp, err := app.Test(httptest.NewRequest(MethodGet, "/", errorReader(0))) utils.AssertEqual(t, true, resp == nil) - utils.AssertEqual(t, "failed to dump request: errorReader", err.Error()) + utils.AssertEqual(t, "errorReader", err.Error()) } // go test -run Test_App_Handler @@ -1395,7 +1393,7 @@ type invalidView struct{} func (invalidView) Load() error { return errors.New("invalid view") } -func (invalidView) Render(io.Writer, string, interface{}, ...string) error { panic("implement me") } +func (i invalidView) Render(io.Writer, string, interface{}, ...string) error { panic("implement me") } // go test -run Test_App_Init_Error_View func Test_App_Init_Error_View(t *testing.T) { @@ -1407,9 +1405,7 @@ func Test_App_Init_Error_View(t *testing.T) { utils.AssertEqual(t, "implement me", fmt.Sprintf("%v", err)) } }() - - err := app.config.Views.Render(nil, "", nil) - utils.AssertEqual(t, nil, err) + _ = app.config.Views.Render(nil, "", nil) } // go test -run Test_App_Stack @@ -1539,12 +1535,11 @@ func Test_App_SmallReadBuffer(t *testing.T) { go func() { time.Sleep(500 * time.Millisecond) - req, err := http.NewRequestWithContext(context.Background(), MethodGet, "http://127.0.0.1:4006/small-read-buffer", http.NoBody) - utils.AssertEqual(t, nil, err) - var client http.Client - resp, err := client.Do(req) + resp, err := http.Get("http://127.0.0.1:4006/small-read-buffer") + if resp != nil { + utils.AssertEqual(t, 431, resp.StatusCode) + } utils.AssertEqual(t, nil, err) - utils.AssertEqual(t, 431, resp.StatusCode) utils.AssertEqual(t, nil, app.Shutdown()) }() @@ -1577,13 +1572,13 @@ func Test_App_New_Test_Parallel(t *testing.T) { t.Run("Test_App_New_Test_Parallel_1", func(t *testing.T) { t.Parallel() app := New(Config{Immutable: true}) - _, err := app.Test(httptest.NewRequest(MethodGet, "/", nil)) + _, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) }) t.Run("Test_App_New_Test_Parallel_2", func(t *testing.T) { t.Parallel() app := New(Config{Immutable: true}) - _, err := app.Test(httptest.NewRequest(MethodGet, "/", nil)) + _, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) }) } @@ -1596,7 +1591,7 @@ func Test_App_ReadBodyStream(t *testing.T) { return c.SendString(fmt.Sprintf("%v %s", c.Request().IsBodyStream(), c.Body())) }) testString := "this is a test" - resp, err := app.Test(httptest.NewRequest(MethodPost, "/", bytes.NewBufferString(testString))) + resp, err := app.Test(httptest.NewRequest("POST", "/", bytes.NewBufferString(testString))) utils.AssertEqual(t, nil, err, "app.Test(req)") body, err := io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err, "io.ReadAll(resp.Body)") @@ -1620,12 +1615,12 @@ func Test_App_DisablePreParseMultipartForm(t *testing.T) { } file, err := mpf.File["test"][0].Open() if err != nil { - return fmt.Errorf("failed to open: %w", err) + return err } buffer := make([]byte, len(testString)) n, err := file.Read(buffer) if err != nil { - return fmt.Errorf("failed to read: %w", err) + return err } if n != len(testString) { return fmt.Errorf("bad read length") @@ -1641,7 +1636,7 @@ func Test_App_DisablePreParseMultipartForm(t *testing.T) { utils.AssertEqual(t, len(testString), n, "writer n") utils.AssertEqual(t, nil, w.Close(), "w.Close()") - req := httptest.NewRequest(MethodPost, "/", b) + req := httptest.NewRequest("POST", "/", b) req.Header.Set("Content-Type", w.FormDataContentType()) resp, err := app.Test(req) utils.AssertEqual(t, nil, err, "app.Test(req)") @@ -1664,7 +1659,7 @@ func Test_App_Test_no_timeout_infinitely(t *testing.T) { return nil }) - req := httptest.NewRequest(MethodGet, "/", http.NoBody) + req := httptest.NewRequest(http.MethodGet, "/", http.NoBody) _, err = app.Test(req, -1) }() @@ -1701,7 +1696,7 @@ func Test_App_SetTLSHandler(t *testing.T) { func Test_App_AddCustomRequestMethod(t *testing.T) { t.Parallel() - methods := append(DefaultMethods, "TEST") //nolint:gocritic // We want a new slice here + methods := append(DefaultMethods, "TEST") app := New(Config{ RequestMethods: methods, }) diff --git a/client.go b/client.go index 334b99a890..f2fbec41a0 100644 --- a/client.go +++ b/client.go @@ -15,7 +15,6 @@ import ( "time" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -51,7 +50,6 @@ type Args = fasthttp.Args // Copy from fasthttp type RetryIfFunc = fasthttp.RetryIfFunc -//nolint:gochecknoglobals // TODO: Do not use a global var here var defaultClient Client // Client implements http client. @@ -188,11 +186,11 @@ func (a *Agent) Parse() error { uri := a.req.URI() - var isTLS bool + isTLS := false scheme := uri.Scheme() - if bytes.Equal(scheme, []byte(schemeHTTPS)) { + if bytes.Equal(scheme, strHTTPS) { isTLS = true - } else if !bytes.Equal(scheme, []byte(schemeHTTP)) { + } else if !bytes.Equal(scheme, strHTTP) { return fmt.Errorf("unsupported protocol %q. http and https are supported", scheme) } @@ -243,7 +241,7 @@ func (a *Agent) SetBytesV(k string, v []byte) *Agent { // SetBytesKV sets the given 'key: value' header. // // Use AddBytesKV for setting multiple header values under the same key. -func (a *Agent) SetBytesKV(k, v []byte) *Agent { +func (a *Agent) SetBytesKV(k []byte, v []byte) *Agent { a.req.Header.SetBytesKV(k, v) return a @@ -283,7 +281,7 @@ func (a *Agent) AddBytesV(k string, v []byte) *Agent { // // Multiple headers with the same key may be added with this function. // Use SetBytesKV for setting a single header for the given key. -func (a *Agent) AddBytesKV(k, v []byte) *Agent { +func (a *Agent) AddBytesKV(k []byte, v []byte) *Agent { a.req.Header.AddBytesKV(k, v) return a @@ -654,8 +652,10 @@ func (a *Agent) Reuse() *Agent { // certificate chain and host name. func (a *Agent) InsecureSkipVerify() *Agent { if a.HostClient.TLSConfig == nil { - a.HostClient.TLSConfig = &tls.Config{InsecureSkipVerify: true} //nolint:gosec // We explicitly let the user set insecure mode here + /* #nosec G402 */ + a.HostClient.TLSConfig = &tls.Config{InsecureSkipVerify: true} // #nosec G402 } else { + /* #nosec G402 */ a.HostClient.TLSConfig.InsecureSkipVerify = true } @@ -728,14 +728,14 @@ func (a *Agent) RetryIf(retryIf RetryIfFunc) *Agent { // Bytes returns the status code, bytes body and errors of url. // // it's not safe to use Agent after calling [Agent.Bytes] -func (a *Agent) Bytes() (int, []byte, []error) { +func (a *Agent) Bytes() (code int, body []byte, errs []error) { defer a.release() return a.bytes() } -func (a *Agent) bytes() (code int, body []byte, errs []error) { //nolint:nonamedreturns,revive // We want to overwrite the body in a deferred func. TODO: Check if we really need to do this. We eventually want to get rid of all named returns. +func (a *Agent) bytes() (code int, body []byte, errs []error) { if errs = append(errs, a.errs...); len(errs) > 0 { - return code, body, errs + return } var ( @@ -760,7 +760,7 @@ func (a *Agent) bytes() (code int, body []byte, errs []error) { //nolint:nonamed code = resp.StatusCode() } - body = append(a.dest, resp.Body()...) //nolint:gocritic // We want to append to the returned slice here + body = append(a.dest, resp.Body()...) if nilResp { ReleaseResponse(resp) @@ -770,25 +770,25 @@ func (a *Agent) bytes() (code int, body []byte, errs []error) { //nolint:nonamed if a.timeout > 0 { if err := a.HostClient.DoTimeout(req, resp, a.timeout); err != nil { errs = append(errs, err) - return code, body, errs + return } } else if a.maxRedirectsCount > 0 && (string(req.Header.Method()) == MethodGet || string(req.Header.Method()) == MethodHead) { if err := a.HostClient.DoRedirects(req, resp, a.maxRedirectsCount); err != nil { errs = append(errs, err) - return code, body, errs + return } } else if err := a.HostClient.Do(req, resp); err != nil { errs = append(errs, err) } - return code, body, errs + return } func printDebugInfo(req *Request, resp *Response, w io.Writer) { msg := fmt.Sprintf("Connected to %s(%s)\r\n\r\n", req.URI().Host(), resp.RemoteAddr()) - _, _ = w.Write(utils.UnsafeBytes(msg)) //nolint:errcheck // This will never fail - _, _ = req.WriteTo(w) //nolint:errcheck // This will never fail - _, _ = resp.WriteTo(w) //nolint:errcheck // This will never fail + _, _ = w.Write(utils.UnsafeBytes(msg)) + _, _ = req.WriteTo(w) + _, _ = resp.WriteTo(w) } // String returns the status code, string body and errors of url. @@ -797,7 +797,6 @@ func printDebugInfo(req *Request, resp *Response, w io.Writer) { func (a *Agent) String() (int, string, []error) { defer a.release() code, body, errs := a.bytes() - // TODO: There might be a data race here on body. Maybe use utils.CopyBytes on it? return code, utils.UnsafeString(body), errs } @@ -806,15 +805,12 @@ func (a *Agent) String() (int, string, []error) { // And bytes body will be unmarshalled to given v. // // it's not safe to use Agent after calling [Agent.Struct] -func (a *Agent) Struct(v interface{}) (int, []byte, []error) { +func (a *Agent) Struct(v interface{}) (code int, body []byte, errs []error) { defer a.release() - - code, body, errs := a.bytes() - if len(errs) > 0 { - return code, body, errs + if code, body, errs = a.bytes(); len(errs) > 0 { + return } - // TODO: This should only be done once if a.jsonDecoder == nil { a.jsonDecoder = json.Unmarshal } @@ -823,7 +819,7 @@ func (a *Agent) Struct(v interface{}) (int, []byte, []error) { errs = append(errs, err) } - return code, body, errs + return } func (a *Agent) release() { @@ -859,7 +855,6 @@ func (a *Agent) reset() { a.formFiles = a.formFiles[:0] } -//nolint:gochecknoglobals // TODO: Do not use global vars here var ( clientPool sync.Pool agentPool = sync.Pool{ @@ -882,11 +877,7 @@ func AcquireClient() *Client { if v == nil { return &Client{} } - c, ok := v.(*Client) - if !ok { - panic(fmt.Errorf("failed to type-assert to *Client")) - } - return c + return v.(*Client) } // ReleaseClient returns c acquired via AcquireClient to client pool. @@ -908,11 +899,7 @@ func ReleaseClient(c *Client) { // no longer needed. This allows Agent recycling, reduces GC pressure // and usually improves performance. func AcquireAgent() *Agent { - a, ok := agentPool.Get().(*Agent) - if !ok { - panic(fmt.Errorf("failed to type-assert to *Agent")) - } - return a + return agentPool.Get().(*Agent) } // ReleaseAgent returns a acquired via AcquireAgent to Agent pool. @@ -935,11 +922,7 @@ func AcquireResponse() *Response { if v == nil { return &Response{} } - r, ok := v.(*Response) - if !ok { - panic(fmt.Errorf("failed to type-assert to *Response")) - } - return r + return v.(*Response) } // ReleaseResponse return resp acquired via AcquireResponse to response pool. @@ -962,11 +945,7 @@ func AcquireArgs() *Args { if v == nil { return &Args{} } - a, ok := v.(*Args) - if !ok { - panic(fmt.Errorf("failed to type-assert to *Args")) - } - return a + return v.(*Args) } // ReleaseArgs returns the object acquired via AcquireArgs to the pool. @@ -987,11 +966,7 @@ func AcquireFormFile() *FormFile { if v == nil { return &FormFile{} } - ff, ok := v.(*FormFile) - if !ok { - panic(fmt.Errorf("failed to type-assert to *FormFile")) - } - return ff + return v.(*FormFile) } // ReleaseFormFile returns the object acquired via AcquireFormFile to the pool. @@ -1006,7 +981,9 @@ func ReleaseFormFile(ff *FormFile) { formFilePool.Put(ff) } -const ( +var ( + strHTTP = []byte("http") + strHTTPS = []byte("https") defaultUserAgent = "fiber" ) diff --git a/client_test.go b/client_test.go index 8df0562d61..d9fd61a893 100644 --- a/client_test.go +++ b/client_test.go @@ -1,4 +1,3 @@ -//nolint:wrapcheck // We must not wrap errors in tests package fiber import ( @@ -20,7 +19,6 @@ import ( "github.com/gofiber/fiber/v2/internal/tlstest" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp/fasthttputil" ) @@ -297,10 +295,8 @@ func Test_Client_Agent_Set_Or_Add_Headers(t *testing.T) { handler := func(c *Ctx) error { c.Request().Header.VisitAll(func(key, value []byte) { if k := string(key); k == "K1" || k == "K2" { - _, err := c.Write(key) - utils.AssertEqual(t, nil, err) - _, err = c.Write(value) - utils.AssertEqual(t, nil, err) + _, _ = c.Write(key) + _, _ = c.Write(value) } }) return nil @@ -585,26 +581,25 @@ type readErrorConn struct { net.Conn } -func (*readErrorConn) Read(_ []byte) (int, error) { +func (r *readErrorConn) Read(p []byte) (int, error) { return 0, fmt.Errorf("error") } -func (*readErrorConn) Write(p []byte) (int, error) { +func (r *readErrorConn) Write(p []byte) (int, error) { return len(p), nil } -func (*readErrorConn) Close() error { +func (r *readErrorConn) Close() error { return nil } -func (*readErrorConn) LocalAddr() net.Addr { +func (r *readErrorConn) LocalAddr() net.Addr { return nil } -func (*readErrorConn) RemoteAddr() net.Addr { +func (r *readErrorConn) RemoteAddr() net.Addr { return nil } - func Test_Client_Agent_RetryIf(t *testing.T) { t.Parallel() @@ -788,10 +783,7 @@ func Test_Client_Agent_MultipartForm_SendFiles(t *testing.T) { buf := make([]byte, fh1.Size) f, err := fh1.Open() utils.AssertEqual(t, nil, err) - defer func() { - err := f.Close() - utils.AssertEqual(t, nil, err) - }() + defer func() { _ = f.Close() }() _, err = f.Read(buf) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "form file", string(buf)) @@ -839,16 +831,13 @@ func checkFormFile(t *testing.T, fh *multipart.FileHeader, filename string) { basename := filepath.Base(filename) utils.AssertEqual(t, fh.Filename, basename) - b1, err := os.ReadFile(filename) //nolint:gosec // We're in a test so reading user-provided files by name is fine + b1, err := os.ReadFile(filename) utils.AssertEqual(t, nil, err) b2 := make([]byte, fh.Size) f, err := fh.Open() utils.AssertEqual(t, nil, err) - defer func() { - err := f.Close() - utils.AssertEqual(t, nil, err) - }() + defer func() { _ = f.Close() }() _, err = f.Read(b2) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, b1, b2) @@ -973,7 +962,6 @@ func Test_Client_Agent_InsecureSkipVerify(t *testing.T) { cer, err := tls.LoadX509KeyPair("./.github/testdata/ssl.pem", "./.github/testdata/ssl.key") utils.AssertEqual(t, nil, err) - //nolint:gosec // We're in a test so using old ciphers is fine serverTLSConf := &tls.Config{ Certificates: []tls.Certificate{cer}, } @@ -1149,7 +1137,7 @@ func Test_Client_Agent_Struct(t *testing.T) { defer ReleaseAgent(a) defer a.ConnectionClose() request := a.Request() - request.Header.SetMethod(MethodGet) + request.Header.SetMethod("GET") request.SetRequestURI("http://example.com") err := a.Parse() utils.AssertEqual(t, nil, err) @@ -1210,8 +1198,8 @@ type errorMultipartWriter struct { count int } -func (*errorMultipartWriter) Boundary() string { return "myBoundary" } -func (*errorMultipartWriter) SetBoundary(_ string) error { return nil } +func (e *errorMultipartWriter) Boundary() string { return "myBoundary" } +func (e *errorMultipartWriter) SetBoundary(_ string) error { return nil } func (e *errorMultipartWriter) CreateFormFile(_, _ string) (io.Writer, error) { if e.count == 0 { e.count++ @@ -1219,8 +1207,8 @@ func (e *errorMultipartWriter) CreateFormFile(_, _ string) (io.Writer, error) { } return errorWriter{}, nil } -func (*errorMultipartWriter) WriteField(_, _ string) error { return errors.New("WriteField error") } -func (*errorMultipartWriter) Close() error { return errors.New("Close error") } +func (e *errorMultipartWriter) WriteField(_, _ string) error { return errors.New("WriteField error") } +func (e *errorMultipartWriter) Close() error { return errors.New("Close error") } type errorWriter struct{} diff --git a/color.go b/color.go index 944a9b3695..cbccd2ebee 100644 --- a/color.go +++ b/color.go @@ -53,8 +53,6 @@ type Colors struct { } // DefaultColors Default color codes -// -//nolint:gochecknoglobals // Using a global var is fine here var DefaultColors = Colors{ Black: "\u001b[90m", Red: "\u001b[91m", diff --git a/ctx.go b/ctx.go index 2b648fe8d7..4d91d311b0 100644 --- a/ctx.go +++ b/ctx.go @@ -27,16 +27,10 @@ import ( "github.com/gofiber/fiber/v2/internal/dictpool" "github.com/gofiber/fiber/v2/internal/schema" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) -const ( - schemeHTTP = "http" - schemeHTTPS = "https" -) - // maxParams defines the maximum number of parameters per route. const maxParams = 30 @@ -51,7 +45,6 @@ const ( // userContextKey define the key name for storing context.Context in *fasthttp.RequestCtx const userContextKey = "__local_user_context__" -//nolint:gochecknoglobals // TODO: Do not use global vars here var ( // decoderPoolMap helps to improve BodyParser's, QueryParser's and ReqHeaderParser's performance decoderPoolMap = map[string]*sync.Pool{} @@ -59,7 +52,6 @@ var ( tags = []string{queryTag, bodyTag, reqHeaderTag, paramsTag} ) -//nolint:gochecknoinits // init() is used to initialize a global map variable func init() { for _, tag := range tags { decoderPoolMap[tag] = &sync.Pool{New: func() interface{} { @@ -108,10 +100,9 @@ type TLSHandler struct { } // GetClientInfo Callback function to set CHI -// TODO: Why is this a getter which sets stuff? func (t *TLSHandler) GetClientInfo(info *tls.ClientHelloInfo) (*tls.Certificate, error) { t.clientHelloInfo = info - return nil, nil //nolint:nilnil // Not returning anything useful here is probably fine + return nil, nil } // Range data for c.Range @@ -160,10 +151,7 @@ type ParserConfig struct { // AcquireCtx retrieves a new Ctx from the pool. func (app *App) AcquireCtx(fctx *fasthttp.RequestCtx) *Ctx { - c, ok := app.pool.Get().(*Ctx) - if !ok { - panic(fmt.Errorf("failed to type-assert to *Ctx")) - } + c := app.pool.Get().(*Ctx) // Set app reference c.app = app // Reset route and handler index @@ -400,6 +388,7 @@ func (c *Ctx) BodyParser(out interface{}) error { } else { data[k] = append(data[k], v) } + }) return c.parseToStruct(bodyTag, out, data) @@ -412,10 +401,7 @@ func (c *Ctx) BodyParser(out interface{}) error { return c.parseToStruct(bodyTag, out, data.Value) } if strings.HasPrefix(ctype, MIMETextXML) || strings.HasPrefix(ctype, MIMEApplicationXML) { - if err := xml.Unmarshal(c.Body(), out); err != nil { - return fmt.Errorf("failed to unmarshal: %w", err) - } - return nil + return xml.Unmarshal(c.Body(), out) } // No suitable content type found return ErrUnprocessableEntity @@ -687,11 +673,8 @@ func (c *Ctx) Hostname() string { // Port returns the remote port of the request. func (c *Ctx) Port() string { - tcpaddr, ok := c.fasthttp.RemoteAddr().(*net.TCPAddr) - if !ok { - panic(fmt.Errorf("failed to type-assert to *net.TCPAddr")) - } - return strconv.Itoa(tcpaddr.Port) + port := c.fasthttp.RemoteAddr().(*net.TCPAddr).Port + return strconv.Itoa(port) } // IP returns the remote IP address of the request. @@ -708,16 +691,13 @@ func (c *Ctx) IP() string { // extractIPsFromHeader will return a slice of IPs it found given a header name in the order they appear. // When IP validation is enabled, any invalid IPs will be omitted. func (c *Ctx) extractIPsFromHeader(header string) []string { - // TODO: Reuse the c.extractIPFromHeader func somehow in here - headerValue := c.Get(header) // We can't know how many IPs we will return, but we will try to guess with this constant division. // Counting ',' makes function slower for about 50ns in general case. - const maxEstimatedCount = 8 - estimatedCount := len(headerValue) / maxEstimatedCount - if estimatedCount > maxEstimatedCount { - estimatedCount = maxEstimatedCount // Avoid big allocation on big header + estimatedCount := len(headerValue) / 8 + if estimatedCount > 8 { + estimatedCount = 8 // Avoid big allocation on big header } ipsFound := make([]string, 0, estimatedCount) @@ -727,10 +707,11 @@ func (c *Ctx) extractIPsFromHeader(header string) []string { iploop: for { - var v4, v6 bool + v4 := false + v6 := false // Manually splitting string without allocating slice, working with parts directly - i, j = j+1, j+2 //nolint:gomnd // Using these values is fine + i, j = j+1, j+2 if j > len(headerValue) { break @@ -777,10 +758,9 @@ func (c *Ctx) extractIPFromHeader(header string) string { iploop: for { - var v4, v6 bool - - // Manually splitting string without allocating slice, working with parts directly - i, j = j+1, j+2 //nolint:gomnd // Using these values is fine + v4 := false + v6 := false + i, j = j+1, j+2 if j > len(headerValue) { break @@ -813,14 +793,14 @@ func (c *Ctx) extractIPFromHeader(header string) string { return c.fasthttp.RemoteIP().String() } - // default behavior if IP validation is not enabled is just to return whatever value is + // default behaviour if IP validation is not enabled is just to return whatever value is // in the proxy header. Even if it is empty or invalid return c.Get(c.app.config.ProxyHeader) } // IPs returns a string slice of IP addresses specified in the X-Forwarded-For request header. // When IP validation is enabled, only valid IPs are returned. -func (c *Ctx) IPs() []string { +func (c *Ctx) IPs() (ips []string) { return c.extractIPsFromHeader(HeaderXForwardedFor) } @@ -859,7 +839,7 @@ func (c *Ctx) JSON(data interface{}) error { func (c *Ctx) JSONP(data interface{}, callback ...string) error { raw, err := json.Marshal(data) if err != nil { - return fmt.Errorf("failed to marshal: %w", err) + return err } var result, cb string @@ -897,11 +877,11 @@ func (c *Ctx) Links(link ...string) { bb := bytebufferpool.Get() for i := range link { if i%2 == 0 { - _ = bb.WriteByte('<') //nolint:errcheck // This will never fail - _, _ = bb.WriteString(link[i]) //nolint:errcheck // This will never fail - _ = bb.WriteByte('>') //nolint:errcheck // This will never fail + _ = bb.WriteByte('<') + _, _ = bb.WriteString(link[i]) + _ = bb.WriteByte('>') } else { - _, _ = bb.WriteString(`; rel="` + link[i] + `",`) //nolint:errcheck // This will never fail + _, _ = bb.WriteString(`; rel="` + link[i] + `",`) } } c.setCanonical(HeaderLink, utils.TrimRight(c.app.getString(bb.Bytes()), ',')) @@ -910,7 +890,7 @@ func (c *Ctx) Links(link ...string) { // Locals makes it possible to pass interface{} values under keys scoped to the request // and therefore available to all following routes that match the request. -func (c *Ctx) Locals(key interface{}, value ...interface{}) interface{} { +func (c *Ctx) Locals(key interface{}, value ...interface{}) (val interface{}) { if len(value) == 0 { return c.fasthttp.UserValue(key) } @@ -953,10 +933,9 @@ func (c *Ctx) ClientHelloInfo() *tls.ClientHelloInfo { } // Next executes the next method in the stack that matches the current route. -func (c *Ctx) Next() error { +func (c *Ctx) Next() (err error) { // Increment handler index c.indexHandler++ - var err error // Did we executed all route handlers? if c.indexHandler < len(c.route.Handlers) { // Continue route stack @@ -968,7 +947,7 @@ func (c *Ctx) Next() error { return err } -// RestartRouting instead of going to the next handler. This may be useful after +// RestartRouting instead of going to the next handler. This may be usefull after // changing the request path. Note that handlers might be executed again. func (c *Ctx) RestartRouting() error { c.indexRoute = -1 @@ -1038,8 +1017,9 @@ func (c *Ctx) ParamsInt(key string, defaultValue ...int) (int, error) { if err != nil { if len(defaultValue) > 0 { return defaultValue[0], nil + } else { + return 0, err } - return 0, fmt.Errorf("failed to convert: %w", err) } return value, nil @@ -1064,16 +1044,15 @@ func (c *Ctx) Path(override ...string) string { // Please use Config.EnableTrustedProxyCheck to prevent header spoofing, in case when your app is behind the proxy. func (c *Ctx) Protocol() string { if c.fasthttp.IsTLS() { - return schemeHTTPS + return "https" } if !c.IsProxyTrusted() { - return schemeHTTP + return "http" } - scheme := schemeHTTP - const lenXHeaderName = 12 + scheme := "http" c.fasthttp.Request.Header.VisitAll(func(key, val []byte) { - if len(key) < lenXHeaderName { + if len(key) < 12 { return // Neither "X-Forwarded-" nor "X-Url-Scheme" } switch { @@ -1088,7 +1067,7 @@ func (c *Ctx) Protocol() string { scheme = v } } else if bytes.Equal(key, []byte(HeaderXForwardedSsl)) && bytes.Equal(val, []byte("on")) { - scheme = schemeHTTPS + scheme = "https" } case bytes.Equal(key, []byte(HeaderXUrlScheme)): @@ -1121,8 +1100,9 @@ func (c *Ctx) QueryInt(key string, defaultValue ...int) int { if err != nil { if len(defaultValue) > 0 { return defaultValue[0] + } else { + return 0 } - return 0 } return value @@ -1153,6 +1133,7 @@ func (c *Ctx) QueryParser(out interface{}) error { } else { data[k] = append(data[k], v) } + }) if err != nil { @@ -1169,9 +1150,10 @@ func parseParamSquareBrackets(k string) (string, error) { kbytes := []byte(k) for i, b := range kbytes { + if b == '[' && kbytes[i+1] != ']' { if err := bb.WriteByte('.'); err != nil { - return "", fmt.Errorf("failed to write: %w", err) + return "", err } } @@ -1180,7 +1162,7 @@ func parseParamSquareBrackets(k string) (string, error) { } if err := bb.WriteByte(b); err != nil { - return "", fmt.Errorf("failed to write: %w", err) + return "", err } } @@ -1202,27 +1184,21 @@ func (c *Ctx) ReqHeaderParser(out interface{}) error { } else { data[k] = append(data[k], v) } + }) return c.parseToStruct(reqHeaderTag, out, data) } -func (*Ctx) parseToStruct(aliasTag string, out interface{}, data map[string][]string) error { +func (c *Ctx) parseToStruct(aliasTag string, out interface{}, data map[string][]string) error { // Get decoder from pool - schemaDecoder, ok := decoderPoolMap[aliasTag].Get().(*schema.Decoder) - if !ok { - panic(fmt.Errorf("failed to type-assert to *schema.Decoder")) - } + schemaDecoder := decoderPoolMap[aliasTag].Get().(*schema.Decoder) defer decoderPoolMap[aliasTag].Put(schemaDecoder) // Set alias tag schemaDecoder.SetAliasTag(aliasTag) - if err := schemaDecoder.Decode(out, data); err != nil { - return fmt.Errorf("failed to decode: %w", err) - } - - return nil + return schemaDecoder.Decode(out, data) } func equalFieldType(out interface{}, kind reflect.Kind, key string) bool { @@ -1272,23 +1248,24 @@ var ( ) // Range returns a struct containing the type and a slice of ranges. -func (c *Ctx) Range(size int) (Range, error) { - var rangeData Range +func (c *Ctx) Range(size int) (rangeData Range, err error) { rangeStr := c.Get(HeaderRange) if rangeStr == "" || !strings.Contains(rangeStr, "=") { - return rangeData, ErrRangeMalformed + err = ErrRangeMalformed + return } data := strings.Split(rangeStr, "=") - const expectedDataParts = 2 - if len(data) != expectedDataParts { - return rangeData, ErrRangeMalformed + 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 { - return rangeData, ErrRangeMalformed + err = ErrRangeMalformed + return } start, startErr := strconv.Atoi(item[0]) end, endErr := strconv.Atoi(item[1]) @@ -1313,10 +1290,11 @@ func (c *Ctx) Range(size int) (Range, error) { }) } if len(rangeData.Ranges) < 1 { - return rangeData, ErrRangeUnsatisfiable + err = ErrRangeUnsatisfiable + return } - return rangeData, nil + return } // Redirect to the URL derived from the specified path, with specified status. @@ -1352,7 +1330,7 @@ func (c *Ctx) getLocationFromRoute(route Route, params Map) (string, error) { if !segment.IsParam { _, err := buf.WriteString(segment.Const) if err != nil { - return "", fmt.Errorf("failed to write string: %w", err) + return "", err } continue } @@ -1363,7 +1341,7 @@ func (c *Ctx) getLocationFromRoute(route Route, params Map) (string, error) { if isSame || isGreedy { _, err := buf.WriteString(utils.ToString(val)) if err != nil { - return "", fmt.Errorf("failed to write string: %w", err) + return "", err } } } @@ -1395,10 +1373,10 @@ func (c *Ctx) RedirectToRoute(routeName string, params Map, status ...int) error i := 1 for k, v := range queries { - _, _ = queryText.WriteString(k + "=" + v) //nolint:errcheck // This will never fail + _, _ = queryText.WriteString(k + "=" + v) if i != len(queries) { - _, _ = queryText.WriteString("&") //nolint:errcheck // This will never fail + _, _ = queryText.WriteString("&") } i++ } @@ -1421,6 +1399,7 @@ func (c *Ctx) RedirectBack(fallback string, status ...int) error { // Render a template with data and sends a text/html response. // We support the following engines: html, amber, handlebars, mustache, pug func (c *Ctx) Render(name string, bind interface{}, layouts ...string) error { + var err error // Get new buffer from pool buf := bytebufferpool.Get() defer bytebufferpool.Put(buf) @@ -1442,7 +1421,7 @@ func (c *Ctx) Render(name string, bind interface{}, layouts ...string) error { // Render template from Views if app.config.Views != nil { if err := app.config.Views.Render(buf, name, bind, layouts...); err != nil { - return fmt.Errorf("failed to render: %w", err) + return err } rendered = true @@ -1454,18 +1433,17 @@ func (c *Ctx) Render(name string, bind interface{}, layouts ...string) error { if !rendered { // Render raw template using 'name' as filepath if no engine is set var tmpl *template.Template - if _, err := readContent(buf, name); err != nil { + if _, err = readContent(buf, name); err != nil { return err } // Parse template - tmpl, err := template.New("").Parse(c.app.getString(buf.Bytes())) - if err != nil { - return fmt.Errorf("failed to parse: %w", err) + if tmpl, err = template.New("").Parse(c.app.getString(buf.Bytes())); err != nil { + return err } buf.Reset() // Render template - if err := tmpl.Execute(buf, bind); err != nil { - return fmt.Errorf("failed to execute: %w", err) + if err = tmpl.Execute(buf, bind); err != nil { + return err } } @@ -1473,8 +1451,8 @@ func (c *Ctx) Render(name string, bind interface{}, layouts ...string) error { c.fasthttp.Response.Header.SetContentType(MIMETextHTMLCharsetUTF8) // Set rendered template to body c.fasthttp.Response.SetBody(buf.Bytes()) - - return nil + // Return err if exist + return err } func (c *Ctx) renderExtensions(bind interface{}) { @@ -1523,32 +1501,28 @@ func (c *Ctx) Route() *Route { } // SaveFile saves any multipart file to disk. -func (*Ctx) SaveFile(fileheader *multipart.FileHeader, path string) error { +func (c *Ctx) SaveFile(fileheader *multipart.FileHeader, path string) error { return fasthttp.SaveMultipartFile(fileheader, path) } // SaveFileToStorage saves any multipart file to an external storage system. -func (*Ctx) SaveFileToStorage(fileheader *multipart.FileHeader, path string, storage Storage) error { +func (c *Ctx) SaveFileToStorage(fileheader *multipart.FileHeader, path string, storage Storage) error { file, err := fileheader.Open() if err != nil { - return fmt.Errorf("failed to open: %w", err) + return err } content, err := io.ReadAll(file) if err != nil { - return fmt.Errorf("failed to read: %w", err) - } - - if err := storage.Set(path, content, 0); err != nil { - return fmt.Errorf("failed to store: %w", err) + return err } - return nil + return storage.Set(path, content, 0) } // Secure returns whether a secure connection was established. func (c *Ctx) Secure() bool { - return c.Protocol() == schemeHTTPS + return c.Protocol() == "https" } // Send sets the HTTP response body without copying it. @@ -1559,7 +1533,6 @@ func (c *Ctx) Send(body []byte) error { return nil } -//nolint:gochecknoglobals // TODO: Do not use global vars here var ( sendFileOnce sync.Once sendFileFS *fasthttp.FS @@ -1575,7 +1548,6 @@ func (c *Ctx) SendFile(file string, compress ...bool) error { // https://github.com/valyala/fasthttp/blob/c7576cc10cabfc9c993317a2d3f8355497bea156/fs.go#L129-L134 sendFileOnce.Do(func() { - const cacheDuration = 10 * time.Second sendFileFS = &fasthttp.FS{ Root: "", AllowEmptyRoot: true, @@ -1583,7 +1555,7 @@ func (c *Ctx) SendFile(file string, compress ...bool) error { AcceptByteRange: true, Compress: true, CompressedFileSuffix: c.app.config.CompressedFileSuffix, - CacheDuration: cacheDuration, + CacheDuration: 10 * time.Second, IndexNames: []string{"index.html"}, PathNotFound: func(ctx *fasthttp.RequestCtx) { ctx.Response.SetStatusCode(StatusNotFound) @@ -1607,7 +1579,7 @@ func (c *Ctx) SendFile(file string, compress ...bool) error { var err error file = filepath.FromSlash(file) if file, err = filepath.Abs(file); err != nil { - return fmt.Errorf("failed to determine abs file path: %w", err) + return err } if hasTrailingSlash { file += "/" @@ -1672,11 +1644,11 @@ func (c *Ctx) SendStream(stream io.Reader, size ...int) error { } // Set sets the response's HTTP header field to the specified key, value. -func (c *Ctx) Set(key, val string) { +func (c *Ctx) Set(key string, val string) { c.fasthttp.Response.Header.Set(key, val) } -func (c *Ctx) setCanonical(key, val string) { +func (c *Ctx) setCanonical(key string, val string) { c.fasthttp.Response.Header.SetCanonical(c.app.getBytes(key), c.app.getBytes(val)) } @@ -1747,7 +1719,6 @@ func (c *Ctx) Write(p []byte) (int, error) { // Writef appends f & a into response body writer. func (c *Ctx) Writef(f string, a ...interface{}) (int, error) { - //nolint:wrapcheck // This must not be wrapped return fmt.Fprintf(c.fasthttp.Response.BodyWriter(), f, a...) } @@ -1789,9 +1760,8 @@ func (c *Ctx) configDependentPaths() { // Define the path for dividing routes into areas for fast tree detection, so that fewer routes need to be traversed, // since the first three characters area select a list of routes c.treePath = c.treePath[0:0] - const maxDetectionPaths = 3 - if len(c.detectionPath) >= maxDetectionPaths { - c.treePath = c.detectionPath[:maxDetectionPaths] + if len(c.detectionPath) >= 3 { + c.treePath = c.detectionPath[:3] } } @@ -1816,7 +1786,7 @@ func (c *Ctx) IsProxyTrusted() bool { } // IsLocalHost will return true if address is a localhost address. -func (*Ctx) isLocalHost(address string) bool { +func (c *Ctx) isLocalHost(address string) bool { localHosts := []string{"127.0.0.1", "0.0.0.0", "::1"} for _, h := range localHosts { if strings.Contains(address, h) { diff --git a/ctx_test.go b/ctx_test.go index 7fc59dc89c..b8ae027bd5 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -2,7 +2,6 @@ // 🤖 Github Repository: https://github.com/gofiber/fiber // 📌 API Documentation: https://docs.gofiber.io -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package fiber import ( @@ -29,7 +28,6 @@ import ( "github.com/gofiber/fiber/v2/internal/storage/memory" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) @@ -363,10 +361,8 @@ func Test_Ctx_BodyParser(t *testing.T) { { var gzipJSON bytes.Buffer w := gzip.NewWriter(&gzipJSON) - _, err := w.Write([]byte(`{"name":"john"}`)) - utils.AssertEqual(t, nil, err) - err = w.Close() - utils.AssertEqual(t, nil, err) + _, _ = w.Write([]byte(`{"name":"john"}`)) + _ = w.Close() c.Request().Header.SetContentType(MIMEApplicationJSON) c.Request().Header.Set(HeaderContentEncoding, "gzip") @@ -435,7 +431,9 @@ func Test_Ctx_ParamParser(t *testing.T) { UserID uint `params:"userId"` RoleID uint `params:"roleId"` } - d := new(Demo) + var ( + d = new(Demo) + ) if err := ctx.ParamsParser(d); err != nil { t.Fatal(err) } @@ -521,7 +519,7 @@ func Benchmark_Ctx_BodyParser_JSON(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { - _ = c.BodyParser(d) //nolint:errcheck // It is fine to ignore the error here as we check it once further below + _ = c.BodyParser(d) } utils.AssertEqual(b, nil, c.BodyParser(d)) utils.AssertEqual(b, "john", d.Name) @@ -545,7 +543,7 @@ func Benchmark_Ctx_BodyParser_XML(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { - _ = c.BodyParser(d) //nolint:errcheck // It is fine to ignore the error here as we check it once further below + _ = c.BodyParser(d) } utils.AssertEqual(b, nil, c.BodyParser(d)) utils.AssertEqual(b, "john", d.Name) @@ -569,7 +567,7 @@ func Benchmark_Ctx_BodyParser_Form(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { - _ = c.BodyParser(d) //nolint:errcheck // It is fine to ignore the error here as we check it once further below + _ = c.BodyParser(d) } utils.AssertEqual(b, nil, c.BodyParser(d)) utils.AssertEqual(b, "john", d.Name) @@ -594,7 +592,7 @@ func Benchmark_Ctx_BodyParser_MultipartForm(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { - _ = c.BodyParser(d) //nolint:errcheck // It is fine to ignore the error here as we check it once further below + _ = c.BodyParser(d) } utils.AssertEqual(b, nil, c.BodyParser(d)) utils.AssertEqual(b, "john", d.Name) @@ -881,13 +879,12 @@ func Test_Ctx_FormFile(t *testing.T) { f, err := fh.Open() utils.AssertEqual(t, nil, err) - defer func() { - utils.AssertEqual(t, nil, f.Close()) - }() b := new(bytes.Buffer) _, err = io.Copy(b, f) utils.AssertEqual(t, nil, err) + + f.Close() utils.AssertEqual(t, "hello world", b.String()) return nil }) @@ -900,7 +897,8 @@ func Test_Ctx_FormFile(t *testing.T) { _, err = ioWriter.Write([]byte("hello world")) utils.AssertEqual(t, nil, err) - utils.AssertEqual(t, nil, writer.Close()) + + writer.Close() req := httptest.NewRequest(MethodPost, "/test", body) req.Header.Set(HeaderContentType, writer.FormDataContentType()) @@ -923,9 +921,10 @@ func Test_Ctx_FormValue(t *testing.T) { body := &bytes.Buffer{} writer := multipart.NewWriter(body) + utils.AssertEqual(t, nil, writer.WriteField("name", "john")) - utils.AssertEqual(t, nil, writer.Close()) + writer.Close() req := httptest.NewRequest(MethodPost, "/test", body) req.Header.Set("Content-Type", fmt.Sprintf("multipart/form-data; boundary=%s", writer.Boundary())) req.Header.Set("Content-Length", strconv.Itoa(len(body.Bytes()))) @@ -1241,7 +1240,7 @@ func Test_Ctx_IP(t *testing.T) { c := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(c) - // default behavior will return the remote IP from the stack + // default behaviour will return the remote IP from the stack utils.AssertEqual(t, "0.0.0.0", c.IP()) // X-Forwarded-For is set, but it is ignored because proxyHeader is not set @@ -1253,7 +1252,7 @@ func Test_Ctx_IP(t *testing.T) { func Test_Ctx_IP_ProxyHeader(t *testing.T) { t.Parallel() - // make sure that the same behavior exists for different proxy header names + // make sure that the same behaviour exists for different proxy header names proxyHeaderNames := []string{"Real-Ip", HeaderXForwardedFor} for _, proxyHeaderName := range proxyHeaderNames { @@ -1287,7 +1286,7 @@ func Test_Ctx_IP_ProxyHeader(t *testing.T) { func Test_Ctx_IP_ProxyHeader_With_IP_Validation(t *testing.T) { t.Parallel() - // make sure that the same behavior exists for different proxy header names + // make sure that the same behaviour exists for different proxy header names proxyHeaderNames := []string{"Real-Ip", HeaderXForwardedFor} for _, proxyHeaderName := range proxyHeaderNames { @@ -1626,43 +1625,35 @@ func Test_Ctx_ClientHelloInfo(t *testing.T) { }) // Test without TLS handler - resp, err := app.Test(httptest.NewRequest(MethodGet, "/ServerName", nil)) - utils.AssertEqual(t, nil, err) - body, err := io.ReadAll(resp.Body) - utils.AssertEqual(t, nil, err) + resp, _ := app.Test(httptest.NewRequest(MethodGet, "/ServerName", nil)) + body, _ := io.ReadAll(resp.Body) utils.AssertEqual(t, []byte("ClientHelloInfo is nil"), body) // Test with TLS Handler const ( - pssWithSHA256 = 0x0804 - versionTLS13 = 0x0304 + PSSWithSHA256 = 0x0804 + VersionTLS13 = 0x0304 ) app.tlsHandler = &TLSHandler{clientHelloInfo: &tls.ClientHelloInfo{ ServerName: "example.golang", - SignatureSchemes: []tls.SignatureScheme{pssWithSHA256}, - SupportedVersions: []uint16{versionTLS13}, + SignatureSchemes: []tls.SignatureScheme{PSSWithSHA256}, + SupportedVersions: []uint16{VersionTLS13}, }} // Test ServerName - resp, err = app.Test(httptest.NewRequest(MethodGet, "/ServerName", nil)) - utils.AssertEqual(t, nil, err) - body, err = io.ReadAll(resp.Body) - utils.AssertEqual(t, nil, err) + resp, _ = app.Test(httptest.NewRequest(MethodGet, "/ServerName", nil)) + body, _ = io.ReadAll(resp.Body) utils.AssertEqual(t, []byte("example.golang"), body) // Test SignatureSchemes - resp, err = app.Test(httptest.NewRequest(MethodGet, "/SignatureSchemes", nil)) - utils.AssertEqual(t, nil, err) - body, err = io.ReadAll(resp.Body) - utils.AssertEqual(t, nil, err) - utils.AssertEqual(t, "["+strconv.Itoa(pssWithSHA256)+"]", string(body)) + resp, _ = app.Test(httptest.NewRequest(MethodGet, "/SignatureSchemes", nil)) + body, _ = io.ReadAll(resp.Body) + utils.AssertEqual(t, "["+strconv.Itoa(PSSWithSHA256)+"]", string(body)) // Test SupportedVersions - resp, err = app.Test(httptest.NewRequest(MethodGet, "/SupportedVersions", nil)) - utils.AssertEqual(t, nil, err) - body, err = io.ReadAll(resp.Body) - utils.AssertEqual(t, nil, err) - utils.AssertEqual(t, "["+strconv.Itoa(versionTLS13)+"]", string(body)) + resp, _ = app.Test(httptest.NewRequest(MethodGet, "/SupportedVersions", nil)) + body, _ = io.ReadAll(resp.Body) + utils.AssertEqual(t, "["+strconv.Itoa(VersionTLS13)+"]", string(body)) } // go test -run Test_Ctx_InvalidMethod @@ -1697,9 +1688,10 @@ func Test_Ctx_MultipartForm(t *testing.T) { body := &bytes.Buffer{} writer := multipart.NewWriter(body) + utils.AssertEqual(t, nil, writer.WriteField("name", "john")) - utils.AssertEqual(t, nil, writer.Close()) + writer.Close() req := httptest.NewRequest(MethodPost, "/test", body) req.Header.Set(HeaderContentType, fmt.Sprintf("multipart/form-data; boundary=%s", writer.Boundary())) req.Header.Set(HeaderContentLength, strconv.Itoa(len(body.Bytes()))) @@ -1714,8 +1706,8 @@ func Benchmark_Ctx_MultipartForm(b *testing.B) { app := New() app.Post("/", func(c *Ctx) error { - _, err := c.MultipartForm() - return err + _, _ = c.MultipartForm() + return nil }) c := &fasthttp.RequestCtx{} @@ -1897,16 +1889,11 @@ func Benchmark_Ctx_AllParams(b *testing.B) { for n := 0; n < b.N; n++ { res = c.AllParams() } - utils.AssertEqual( - b, - map[string]string{ - "param1": "john", - "param2": "doe", - "param3": "is", - "param4": "awesome", - }, - res, - ) + utils.AssertEqual(b, map[string]string{"param1": "john", + "param2": "doe", + "param3": "is", + "param4": "awesome"}, + res) } // go test -v -run=^$ -bench=Benchmark_Ctx_ParamsParse -benchmem -count=4 @@ -1977,31 +1964,31 @@ func Test_Ctx_Protocol(t *testing.T) { c := app.AcquireCtx(freq) defer app.ReleaseCtx(c) - c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProto, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXForwardedProtocol, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProtocol, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() c.Request().Header.Set(HeaderXForwardedProto, "https, http") - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() c.Request().Header.Set(HeaderXForwardedProtocol, "https, http") - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() c.Request().Header.Set(HeaderXForwardedSsl, "on") - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXUrlScheme, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXUrlScheme, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + utils.AssertEqual(t, "http", c.Protocol()) } // go test -v -run=^$ -bench=Benchmark_Ctx_Protocol -benchmem -count=4 @@ -2015,7 +2002,7 @@ func Benchmark_Ctx_Protocol(b *testing.B) { for n := 0; n < b.N; n++ { res = c.Protocol() } - utils.AssertEqual(b, schemeHTTP, res) + utils.AssertEqual(b, "http", res) } // go test -run Test_Ctx_Protocol_TrustedProxy @@ -2025,23 +2012,23 @@ func Test_Ctx_Protocol_TrustedProxy(t *testing.T) { c := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(c) - c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProto, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXForwardedProtocol, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProtocol, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() c.Request().Header.Set(HeaderXForwardedSsl, "on") - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXUrlScheme, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXUrlScheme, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + utils.AssertEqual(t, "http", c.Protocol()) } // go test -run Test_Ctx_Protocol_TrustedProxyRange @@ -2051,23 +2038,23 @@ func Test_Ctx_Protocol_TrustedProxyRange(t *testing.T) { c := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(c) - c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProto, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXForwardedProtocol, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProtocol, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() c.Request().Header.Set(HeaderXForwardedSsl, "on") - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXUrlScheme, schemeHTTPS) - utils.AssertEqual(t, schemeHTTPS, c.Protocol()) + c.Request().Header.Set(HeaderXUrlScheme, "https") + utils.AssertEqual(t, "https", c.Protocol()) c.Request().Header.Reset() - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + utils.AssertEqual(t, "http", c.Protocol()) } // go test -run Test_Ctx_Protocol_UntrustedProxyRange @@ -2077,23 +2064,23 @@ func Test_Ctx_Protocol_UntrustedProxyRange(t *testing.T) { c := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(c) - c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS) - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProto, "https") + utils.AssertEqual(t, "http", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXForwardedProtocol, schemeHTTPS) - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProtocol, "https") + utils.AssertEqual(t, "http", c.Protocol()) c.Request().Header.Reset() c.Request().Header.Set(HeaderXForwardedSsl, "on") - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + utils.AssertEqual(t, "http", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXUrlScheme, schemeHTTPS) - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + c.Request().Header.Set(HeaderXUrlScheme, "https") + utils.AssertEqual(t, "http", c.Protocol()) c.Request().Header.Reset() - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + utils.AssertEqual(t, "http", c.Protocol()) } // go test -run Test_Ctx_Protocol_UnTrustedProxy @@ -2103,23 +2090,23 @@ func Test_Ctx_Protocol_UnTrustedProxy(t *testing.T) { c := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(c) - c.Request().Header.Set(HeaderXForwardedProto, schemeHTTPS) - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProto, "https") + utils.AssertEqual(t, "http", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXForwardedProtocol, schemeHTTPS) - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + c.Request().Header.Set(HeaderXForwardedProtocol, "https") + utils.AssertEqual(t, "http", c.Protocol()) c.Request().Header.Reset() c.Request().Header.Set(HeaderXForwardedSsl, "on") - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + utils.AssertEqual(t, "http", c.Protocol()) c.Request().Header.Reset() - c.Request().Header.Set(HeaderXUrlScheme, schemeHTTPS) - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + c.Request().Header.Set(HeaderXUrlScheme, "https") + utils.AssertEqual(t, "http", c.Protocol()) c.Request().Header.Reset() - utils.AssertEqual(t, schemeHTTP, c.Protocol()) + utils.AssertEqual(t, "http", c.Protocol()) } // go test -run Test_Ctx_Query @@ -2237,12 +2224,7 @@ func Test_Ctx_SaveFile(t *testing.T) { tempFile, err := os.CreateTemp(os.TempDir(), "test-") utils.AssertEqual(t, nil, err) - defer func(file *os.File) { - err := file.Close() - utils.AssertEqual(t, nil, err) - err = os.Remove(file.Name()) - utils.AssertEqual(t, nil, err) - }(tempFile) + defer os.Remove(tempFile.Name()) err = c.SaveFile(fh, tempFile.Name()) utils.AssertEqual(t, nil, err) @@ -2260,7 +2242,7 @@ func Test_Ctx_SaveFile(t *testing.T) { _, err = ioWriter.Write([]byte("hello world")) utils.AssertEqual(t, nil, err) - utils.AssertEqual(t, nil, writer.Close()) + writer.Close() req := httptest.NewRequest(MethodPost, "/test", body) req.Header.Set("Content-Type", writer.FormDataContentType()) @@ -2302,7 +2284,7 @@ func Test_Ctx_SaveFileToStorage(t *testing.T) { _, err = ioWriter.Write([]byte("hello world")) utils.AssertEqual(t, nil, err) - utils.AssertEqual(t, nil, writer.Close()) + writer.Close() req := httptest.NewRequest(MethodPost, "/test", body) req.Header.Set("Content-Type", writer.FormDataContentType()) @@ -2388,9 +2370,7 @@ func Test_Ctx_Download(t *testing.T) { f, err := os.Open("./ctx.go") utils.AssertEqual(t, nil, err) - defer func() { - utils.AssertEqual(t, nil, f.Close()) - }() + defer f.Close() expect, err := io.ReadAll(f) utils.AssertEqual(t, nil, err) @@ -2409,9 +2389,7 @@ func Test_Ctx_SendFile(t *testing.T) { // fetch file content f, err := os.Open("./ctx.go") utils.AssertEqual(t, nil, err) - defer func() { - utils.AssertEqual(t, nil, f.Close()) - }() + defer f.Close() expectFileContent, err := io.ReadAll(f) utils.AssertEqual(t, nil, err) // fetch file info for the not modified test case @@ -2457,7 +2435,7 @@ func Test_Ctx_SendFile_404(t *testing.T) { return err }) - resp, err := app.Test(httptest.NewRequest(MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, StatusNotFound, resp.StatusCode) } @@ -2495,11 +2473,11 @@ func Test_Ctx_SendFile_Immutable(t *testing.T) { for _, endpoint := range endpointsForTest { t.Run(endpoint, func(t *testing.T) { // 1st try - resp, err := app.Test(httptest.NewRequest(MethodGet, endpoint, nil)) + resp, err := app.Test(httptest.NewRequest("GET", endpoint, nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, StatusOK, resp.StatusCode) // 2nd try - resp, err = app.Test(httptest.NewRequest(MethodGet, endpoint, nil)) + resp, err = app.Test(httptest.NewRequest("GET", endpoint, nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, StatusOK, resp.StatusCode) }) @@ -2517,9 +2495,9 @@ func Test_Ctx_SendFile_RestoreOriginalURL(t *testing.T) { return err }) - _, err1 := app.Test(httptest.NewRequest(MethodGet, "/?test=true", nil)) + _, err1 := app.Test(httptest.NewRequest("GET", "/?test=true", nil)) // second request required to confirm with zero allocation - _, err2 := app.Test(httptest.NewRequest(MethodGet, "/?test=true", nil)) + _, err2 := app.Test(httptest.NewRequest("GET", "/?test=true", nil)) utils.AssertEqual(t, nil, err1) utils.AssertEqual(t, nil, err2) @@ -2915,12 +2893,12 @@ func Test_Ctx_Render(t *testing.T) { err := c.Render("./.github/testdata/index.tmpl", Map{ "Title": "Hello, World!", }) - utils.AssertEqual(t, nil, err) buf := bytebufferpool.Get() - _, _ = buf.WriteString("overwrite") //nolint:errcheck // This will never fail + _, _ = buf.WriteString("overwrite") defer bytebufferpool.Put(buf) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World!

", string(c.Response().Body())) err = c.Render("./.github/testdata/template-non-exists.html", nil) @@ -2940,12 +2918,12 @@ func Test_Ctx_RenderWithoutLocals(t *testing.T) { c.Locals("Title", "Hello, World!") defer app.ReleaseCtx(c) err := c.Render("./.github/testdata/index.tmpl", Map{}) - utils.AssertEqual(t, nil, err) buf := bytebufferpool.Get() - _, _ = buf.WriteString("overwrite") //nolint:errcheck // This will never fail + _, _ = buf.WriteString("overwrite") defer bytebufferpool.Put(buf) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

", string(c.Response().Body())) } @@ -2959,13 +2937,14 @@ func Test_Ctx_RenderWithLocals(t *testing.T) { c.Locals("Title", "Hello, World!") defer app.ReleaseCtx(c) err := c.Render("./.github/testdata/index.tmpl", Map{}) - utils.AssertEqual(t, nil, err) buf := bytebufferpool.Get() - _, _ = buf.WriteString("overwrite") //nolint:errcheck // This will never fail + _, _ = buf.WriteString("overwrite") defer bytebufferpool.Put(buf) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World!

", string(c.Response().Body())) + } func Test_Ctx_RenderWithBind(t *testing.T) { @@ -2980,13 +2959,14 @@ func Test_Ctx_RenderWithBind(t *testing.T) { utils.AssertEqual(t, nil, err) defer app.ReleaseCtx(c) err = c.Render("./.github/testdata/index.tmpl", Map{}) - utils.AssertEqual(t, nil, err) buf := bytebufferpool.Get() - _, _ = buf.WriteString("overwrite") //nolint:errcheck // This will never fail + _, _ = buf.WriteString("overwrite") defer bytebufferpool.Put(buf) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World!

", string(c.Response().Body())) + } func Test_Ctx_RenderWithOverwrittenBind(t *testing.T) { @@ -3002,12 +2982,12 @@ func Test_Ctx_RenderWithOverwrittenBind(t *testing.T) { err = c.Render("./.github/testdata/index.tmpl", Map{ "Title": "Hello from Fiber!", }) - utils.AssertEqual(t, nil, err) buf := bytebufferpool.Get() - _, _ = buf.WriteString("overwrite") //nolint:errcheck // This will never fail + _, _ = buf.WriteString("overwrite") defer bytebufferpool.Put(buf) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello from Fiber!

", string(c.Response().Body())) } @@ -3025,12 +3005,13 @@ func Test_Ctx_RenderWithBindLocals(t *testing.T) { utils.AssertEqual(t, nil, err) c.Locals("Summary", "Test") - defer app.ReleaseCtx(c) + defer app.ReleaseCtx(c) err = c.Render("./.github/testdata/template.tmpl", Map{}) - utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World! Test

", string(c.Response().Body())) + } func Test_Ctx_RenderWithLocalsAndBinding(t *testing.T) { @@ -3046,12 +3027,11 @@ func Test_Ctx_RenderWithLocalsAndBinding(t *testing.T) { c.Locals("Title", "This is a test.") defer app.ReleaseCtx(c) - err = c.Render("index.tmpl", Map{ "Title": "Hello, World!", }) - utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

Hello, World!

", string(c.Response().Body())) } @@ -3080,8 +3060,8 @@ func Benchmark_Ctx_RenderWithLocalsAndBinding(b *testing.B) { for n := 0; n < b.N; n++ { err = c.Render("template.tmpl", Map{}) } - utils.AssertEqual(b, nil, err) + utils.AssertEqual(b, nil, err) utils.AssertEqual(b, "

Hello, World! Test

", string(c.Response().Body())) } @@ -3103,8 +3083,8 @@ func Benchmark_Ctx_RedirectToRoute(b *testing.B) { "name": "fiber", }) } - utils.AssertEqual(b, nil, err) + utils.AssertEqual(b, nil, err) utils.AssertEqual(b, 302, c.Response().StatusCode()) utils.AssertEqual(b, "/user/fiber", string(c.Response().Header.Peek(HeaderLocation))) } @@ -3128,8 +3108,8 @@ func Benchmark_Ctx_RedirectToRouteWithQueries(b *testing.B) { "queries": map[string]string{"a": "a", "b": "b"}, }) } - utils.AssertEqual(b, nil, err) + utils.AssertEqual(b, nil, err) utils.AssertEqual(b, 302, c.Response().StatusCode()) // analysis of query parameters with url parsing, since a map pass is always randomly ordered location, err := url.Parse(string(c.Response().Header.Peek(HeaderLocation))) @@ -3158,8 +3138,8 @@ func Benchmark_Ctx_RenderLocals(b *testing.B) { for n := 0; n < b.N; n++ { err = c.Render("index.tmpl", Map{}) } - utils.AssertEqual(b, nil, err) + utils.AssertEqual(b, nil, err) utils.AssertEqual(b, "

Hello, World!

", string(c.Response().Body())) } @@ -3184,8 +3164,8 @@ func Benchmark_Ctx_RenderBind(b *testing.B) { for n := 0; n < b.N; n++ { err = c.Render("index.tmpl", Map{}) } - utils.AssertEqual(b, nil, err) + utils.AssertEqual(b, nil, err) utils.AssertEqual(b, "

Hello, World!

", string(c.Response().Body())) } @@ -3211,7 +3191,8 @@ func Test_Ctx_RestartRouting(t *testing.T) { func Test_Ctx_RestartRoutingWithChangedPath(t *testing.T) { t.Parallel() app := New() - var executedOldHandler, executedNewHandler bool + executedOldHandler := false + executedNewHandler := false app.Get("/old", func(c *Ctx) error { c.Path("/new") @@ -3261,18 +3242,10 @@ type testTemplateEngine struct { func (t *testTemplateEngine) Render(w io.Writer, name string, bind interface{}, layout ...string) error { if len(layout) == 0 { - if err := t.templates.ExecuteTemplate(w, name, bind); err != nil { - return fmt.Errorf("failed to execute template without layout: %w", err) - } - return nil - } - if err := t.templates.ExecuteTemplate(w, name, bind); err != nil { - return fmt.Errorf("failed to execute template: %w", err) + return t.templates.ExecuteTemplate(w, name, bind) } - if err := t.templates.ExecuteTemplate(w, layout[0], bind); err != nil { - return fmt.Errorf("failed to execute template with layout: %w", err) - } - return nil + _ = t.templates.ExecuteTemplate(w, name, bind) + return t.templates.ExecuteTemplate(w, layout[0], bind) } func (t *testTemplateEngine) Load() error { @@ -3351,6 +3324,7 @@ func Benchmark_Ctx_Get_Location_From_Route(b *testing.B) { } utils.AssertEqual(b, "/user/fiber", location) utils.AssertEqual(b, nil, err) + } // go test -run Test_Ctx_Get_Location_From_Route_name @@ -3433,11 +3407,11 @@ func Test_Ctx_Get_Location_From_Route_name_Optional_greedy_one_param(t *testing. type errorTemplateEngine struct{} -func (errorTemplateEngine) Render(_ io.Writer, _ string, _ interface{}, _ ...string) error { +func (t errorTemplateEngine) Render(w io.Writer, name string, bind interface{}, layout ...string) error { return errors.New("errorTemplateEngine") } -func (errorTemplateEngine) Load() error { return nil } +func (t errorTemplateEngine) Load() error { return nil } // go test -run Test_Ctx_Render_Engine_Error func Test_Ctx_Render_Engine_Error(t *testing.T) { @@ -3455,10 +3429,7 @@ func Test_Ctx_Render_Go_Template(t *testing.T) { t.Parallel() file, err := os.CreateTemp(os.TempDir(), "fiber") utils.AssertEqual(t, nil, err) - defer func() { - err := os.Remove(file.Name()) - utils.AssertEqual(t, nil, err) - }() + defer os.Remove(file.Name()) _, err = file.Write([]byte("template")) utils.AssertEqual(t, nil, err) @@ -3850,7 +3821,7 @@ func Test_Ctx_QueryParser(t *testing.T) { } rq := new(RequiredQuery) c.Request().URI().SetQueryString("") - utils.AssertEqual(t, "failed to decode: name is empty", c.QueryParser(rq).Error()) + utils.AssertEqual(t, "name is empty", c.QueryParser(rq).Error()) type ArrayQuery struct { Data []string @@ -3866,7 +3837,7 @@ func Test_Ctx_QueryParser_WithSetParserDecoder(t *testing.T) { t.Parallel() type NonRFCTime time.Time - nonRFCConverter := func(value string) reflect.Value { + NonRFCConverter := func(value string) reflect.Value { if v, err := time.Parse("2006-01-02", value); err == nil { return reflect.ValueOf(v) } @@ -3875,7 +3846,7 @@ func Test_Ctx_QueryParser_WithSetParserDecoder(t *testing.T) { nonRFCTime := ParserType{ Customtype: NonRFCTime{}, - Converter: nonRFCConverter, + Converter: NonRFCConverter, } SetParserDecoder(ParserConfig{ @@ -3901,6 +3872,7 @@ func Test_Ctx_QueryParser_WithSetParserDecoder(t *testing.T) { c.Request().URI().SetQueryString("date=2021-04-10&title=CustomDateTest&Body=October") utils.AssertEqual(t, nil, c.QueryParser(q)) + fmt.Println(q.Date, "q.Date") utils.AssertEqual(t, "CustomDateTest", q.Title) date := fmt.Sprintf("%v", q.Date) utils.AssertEqual(t, "{0 63753609600 }", date) @@ -3935,7 +3907,7 @@ func Test_Ctx_QueryParser_Schema(t *testing.T) { c.Request().URI().SetQueryString("namex=tom&nested.age=10") q = new(Query1) - utils.AssertEqual(t, "failed to decode: name is empty", c.QueryParser(q).Error()) + utils.AssertEqual(t, "name is empty", c.QueryParser(q).Error()) c.Request().URI().SetQueryString("name=tom&nested.agex=10") q = new(Query1) @@ -3943,7 +3915,7 @@ func Test_Ctx_QueryParser_Schema(t *testing.T) { c.Request().URI().SetQueryString("name=tom&test.age=10") q = new(Query1) - utils.AssertEqual(t, "failed to decode: nested is empty", c.QueryParser(q).Error()) + utils.AssertEqual(t, "nested is empty", c.QueryParser(q).Error()) type Query2 struct { Name string `query:"name"` @@ -3961,11 +3933,11 @@ func Test_Ctx_QueryParser_Schema(t *testing.T) { c.Request().URI().SetQueryString("nested.agex=10") q2 = new(Query2) - utils.AssertEqual(t, "failed to decode: nested.age is empty", c.QueryParser(q2).Error()) + utils.AssertEqual(t, "nested.age is empty", c.QueryParser(q2).Error()) c.Request().URI().SetQueryString("nested.agex=10") q2 = new(Query2) - utils.AssertEqual(t, "failed to decode: nested.age is empty", c.QueryParser(q2).Error()) + utils.AssertEqual(t, "nested.age is empty", c.QueryParser(q2).Error()) type Node struct { Value int `query:"val,required"` @@ -3979,7 +3951,7 @@ func Test_Ctx_QueryParser_Schema(t *testing.T) { c.Request().URI().SetQueryString("next.val=2") n = new(Node) - utils.AssertEqual(t, "failed to decode: val is empty", c.QueryParser(n).Error()) + utils.AssertEqual(t, "val is empty", c.QueryParser(n).Error()) c.Request().URI().SetQueryString("val=3&next.value=2") n = new(Node) @@ -4085,7 +4057,7 @@ func Test_Ctx_ReqHeaderParser(t *testing.T) { } rh := new(RequiredHeader) c.Request().Header.Del("name") - utils.AssertEqual(t, "failed to decode: name is empty", c.ReqHeaderParser(rh).Error()) + utils.AssertEqual(t, "name is empty", c.ReqHeaderParser(rh).Error()) } // go test -run Test_Ctx_ReqHeaderParser_WithSetParserDecoder -v @@ -4093,7 +4065,7 @@ func Test_Ctx_ReqHeaderParser_WithSetParserDecoder(t *testing.T) { t.Parallel() type NonRFCTime time.Time - nonRFCConverter := func(value string) reflect.Value { + NonRFCConverter := func(value string) reflect.Value { if v, err := time.Parse("2006-01-02", value); err == nil { return reflect.ValueOf(v) } @@ -4102,7 +4074,7 @@ func Test_Ctx_ReqHeaderParser_WithSetParserDecoder(t *testing.T) { nonRFCTime := ParserType{ Customtype: NonRFCTime{}, - Converter: nonRFCConverter, + Converter: NonRFCConverter, } SetParserDecoder(ParserConfig{ @@ -4131,6 +4103,7 @@ func Test_Ctx_ReqHeaderParser_WithSetParserDecoder(t *testing.T) { c.Request().Header.Add("Body", "October") utils.AssertEqual(t, nil, c.ReqHeaderParser(r)) + fmt.Println(r.Date, "q.Date") utils.AssertEqual(t, "CustomDateTest", r.Title) date := fmt.Sprintf("%v", r.Date) utils.AssertEqual(t, "{0 63753609600 }", date) @@ -4167,7 +4140,7 @@ func Test_Ctx_ReqHeaderParser_Schema(t *testing.T) { c.Request().Header.Del("Name") q = new(Header1) - utils.AssertEqual(t, "failed to decode: Name is empty", c.ReqHeaderParser(q).Error()) + utils.AssertEqual(t, "Name is empty", c.ReqHeaderParser(q).Error()) c.Request().Header.Add("Name", "tom") c.Request().Header.Del("Nested.Age") @@ -4177,7 +4150,7 @@ func Test_Ctx_ReqHeaderParser_Schema(t *testing.T) { c.Request().Header.Del("Nested.Agex") q = new(Header1) - utils.AssertEqual(t, "failed to decode: Nested is empty", c.ReqHeaderParser(q).Error()) + utils.AssertEqual(t, "Nested is empty", c.ReqHeaderParser(q).Error()) c.Request().Header.Del("Nested.Agex") c.Request().Header.Del("Name") @@ -4203,7 +4176,7 @@ func Test_Ctx_ReqHeaderParser_Schema(t *testing.T) { c.Request().Header.Del("Nested.Age") c.Request().Header.Add("Nested.Agex", "10") h2 = new(Header2) - utils.AssertEqual(t, "failed to decode: Nested.age is empty", c.ReqHeaderParser(h2).Error()) + utils.AssertEqual(t, "Nested.age is empty", c.ReqHeaderParser(h2).Error()) type Node struct { Value int `reqHeader:"Val,required"` @@ -4218,7 +4191,7 @@ func Test_Ctx_ReqHeaderParser_Schema(t *testing.T) { c.Request().Header.Del("Val") n = new(Node) - utils.AssertEqual(t, "failed to decode: Val is empty", c.ReqHeaderParser(n).Error()) + utils.AssertEqual(t, "Val is empty", c.ReqHeaderParser(n).Error()) c.Request().Header.Add("Val", "3") c.Request().Header.Del("Next.Val") @@ -4655,9 +4628,8 @@ func Test_Ctx_RepeatParserWithSameStruct(t *testing.T) { var gzipJSON bytes.Buffer w := gzip.NewWriter(&gzipJSON) - _, _ = w.Write([]byte(`{"body_param":"body_param"}`)) //nolint:errcheck // This will never fail - err := w.Close() - utils.AssertEqual(t, nil, err) + _, _ = w.Write([]byte(`{"body_param":"body_param"}`)) + _ = w.Close() c.Request().Header.SetContentType(MIMEApplicationJSON) c.Request().Header.Set(HeaderContentEncoding, "gzip") c.Request().SetBody(gzipJSON.Bytes()) diff --git a/error_test.go b/error_test.go index 5cd47e33fe..fe0ec36605 100644 --- a/error_test.go +++ b/error_test.go @@ -1,10 +1,11 @@ package fiber import ( - "encoding/json" "errors" "testing" + jerrors "encoding/json" + "github.com/gofiber/fiber/v2/internal/schema" "github.com/gofiber/fiber/v2/utils" ) @@ -35,42 +36,42 @@ func TestMultiError(t *testing.T) { func TestInvalidUnmarshalError(t *testing.T) { t.Parallel() - var e *json.InvalidUnmarshalError + var e *jerrors.InvalidUnmarshalError ok := errors.As(&InvalidUnmarshalError{}, &e) utils.AssertEqual(t, true, ok) } func TestMarshalerError(t *testing.T) { t.Parallel() - var e *json.MarshalerError + var e *jerrors.MarshalerError ok := errors.As(&MarshalerError{}, &e) utils.AssertEqual(t, true, ok) } func TestSyntaxError(t *testing.T) { t.Parallel() - var e *json.SyntaxError + var e *jerrors.SyntaxError ok := errors.As(&SyntaxError{}, &e) utils.AssertEqual(t, true, ok) } func TestUnmarshalTypeError(t *testing.T) { t.Parallel() - var e *json.UnmarshalTypeError + var e *jerrors.UnmarshalTypeError ok := errors.As(&UnmarshalTypeError{}, &e) utils.AssertEqual(t, true, ok) } func TestUnsupportedTypeError(t *testing.T) { t.Parallel() - var e *json.UnsupportedTypeError + var e *jerrors.UnsupportedTypeError ok := errors.As(&UnsupportedTypeError{}, &e) utils.AssertEqual(t, true, ok) } func TestUnsupportedValeError(t *testing.T) { t.Parallel() - var e *json.UnsupportedValueError + var e *jerrors.UnsupportedValueError ok := errors.As(&UnsupportedValueError{}, &e) utils.AssertEqual(t, true, ok) } diff --git a/group.go b/group.go index 91c2806244..ce1e1b2db5 100644 --- a/group.go +++ b/group.go @@ -168,6 +168,7 @@ func (grp *Group) Group(prefix string, handlers ...Handler) Router { } return newGrp + } // Route is used to define routes with a common prefix inside the common function. diff --git a/helpers.go b/helpers.go index e0e523d8ad..b074c6ca8e 100644 --- a/helpers.go +++ b/helpers.go @@ -20,13 +20,13 @@ import ( "unsafe" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) -// getTLSConfig returns a net listener's tls config -func getTLSConfig(ln net.Listener) *tls.Config { +/* #nosec */ +// getTlsConfig returns a net listener's tls config +func getTlsConfig(ln net.Listener) *tls.Config { // Get listener type pointer := reflect.ValueOf(ln) @@ -37,16 +37,12 @@ func getTLSConfig(ln net.Listener) *tls.Config { // Get private field from value if field := val.FieldByName("config"); field.Type() != nil { // Copy value from pointer field (unsafe) - 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. + newval := reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())) // #nosec G103 if newval.Type() != nil { // Get element from pointer if elem := newval.Elem(); elem.Type() != nil { // Cast value to *tls.Config - c, ok := elem.Interface().(*tls.Config) - if !ok { - panic(fmt.Errorf("failed to type-assert to *tls.Config")) - } - return c + return elem.Interface().(*tls.Config) } } } @@ -57,21 +53,19 @@ func getTLSConfig(ln net.Listener) *tls.Config { } // readContent opens a named file and read content from it -func readContent(rf io.ReaderFrom, name string) (int64, error) { +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, fmt.Errorf("failed to open: %w", err) + return 0, err } + // #nosec G307 defer func() { if err = f.Close(); err != nil { log.Printf("Error closing file: %s\n", err) } }() - if n, err := rf.ReadFrom(f); err != nil { - return n, fmt.Errorf("failed to read: %w", err) - } - return 0, nil + return rf.ReadFrom(f) } // quoteString escape special characters in a given string @@ -84,8 +78,7 @@ func (app *App) quoteString(raw string) string { } // Scan stack if other methods match the request -func (app *App) methodExist(ctx *Ctx) bool { - var exists bool +func (app *App) methodExist(ctx *Ctx) (exist bool) { methods := app.config.RequestMethods for i := 0; i < len(methods); i++ { // Skip original method @@ -115,7 +108,7 @@ func (app *App) methodExist(ctx *Ctx) bool { // No match, next route if match { // We matched - exists = true + exist = true // Add method to Allow header ctx.Append(HeaderAllow, methods[i]) // Break stack loop @@ -123,7 +116,7 @@ func (app *App) methodExist(ctx *Ctx) bool { } } } - return exists + return } // uniqueRouteStack drop all not unique routes from the slice @@ -153,7 +146,7 @@ func defaultString(value string, defaultValue []string) string { const normalizedHeaderETag = "Etag" // Generate and set ETag header to response -func setETag(c *Ctx, weak bool) { //nolint: revive // Accepting a bool param is fine here +func setETag(c *Ctx, weak bool) { // Don't generate ETags for invalid responses if c.fasthttp.Response.StatusCode() != StatusOK { return @@ -167,8 +160,7 @@ func setETag(c *Ctx, weak bool) { //nolint: revive // Accepting a bool param is clientEtag := c.Get(HeaderIfNoneMatch) // Generate ETag for response - const pol = 0xD5828281 - crc32q := crc32.MakeTable(pol) + crc32q := crc32.MakeTable(0xD5828281) etag := fmt.Sprintf("\"%d-%v\"", len(body), crc32.Checksum(body, crc32q)) // Enable weak tag @@ -181,9 +173,7 @@ func setETag(c *Ctx, weak bool) { //nolint: revive // Accepting a bool param is // Check if server's ETag is weak if clientEtag[2:] == etag || clientEtag[2:] == etag[2:] { // W/1 == 1 || W/1 == W/1 - if err := c.SendStatus(StatusNotModified); err != nil { - log.Printf("setETag: failed to SendStatus: %v\n", err) - } + _ = c.SendStatus(StatusNotModified) c.fasthttp.ResetBody() return } @@ -193,9 +183,7 @@ func setETag(c *Ctx, weak bool) { //nolint: revive // Accepting a bool param is } if strings.Contains(clientEtag, etag) { // 1 == 1 - if err := c.SendStatus(StatusNotModified); err != nil { - log.Printf("setETag: failed to SendStatus: %v\n", err) - } + _ = c.SendStatus(StatusNotModified) c.fasthttp.ResetBody() return } @@ -251,7 +239,7 @@ func getOffer(header string, offers ...string) string { return "" } -func matchEtag(s, etag string) bool { +func matchEtag(s string, etag string) bool { if s == etag || s == "W/"+etag || "W/"+s == etag { return true } @@ -266,12 +254,12 @@ func (app *App) isEtagStale(etag string, noneMatchBytes []byte) bool { // https://github.com/jshttp/fresh/blob/10e0471669dbbfbfd8de65bc6efac2ddd0bfa057/index.js#L110 for i := range noneMatchBytes { switch noneMatchBytes[i] { - case 0x20: //nolint:gomnd // This is a space (" ") + case 0x20: if start == end { start = i + 1 end = i + 1 } - case 0x2c: //nolint:gomnd // This is a comma (",") + case 0x2c: if matchEtag(app.getString(noneMatchBytes[start:end]), etag) { return false } @@ -285,7 +273,7 @@ func (app *App) isEtagStale(etag string, noneMatchBytes []byte) bool { return !matchEtag(app.getString(noneMatchBytes[start:end]), etag) } -func parseAddr(raw string) (string, string) { //nolint:revive // Returns (host, port) +func parseAddr(raw string) (host, port string) { if i := strings.LastIndex(raw, ":"); i != -1 { return raw[:i], raw[i+1:] } @@ -325,21 +313,21 @@ type testConn struct { w bytes.Buffer } -func (c *testConn) Read(b []byte) (int, error) { return c.r.Read(b) } //nolint:wrapcheck // This must not be wrapped -func (c *testConn) Write(b []byte) (int, error) { return c.w.Write(b) } //nolint:wrapcheck // This must not be wrapped -func (*testConn) Close() error { return nil } +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 (*testConn) LocalAddr() net.Addr { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} } -func (*testConn) RemoteAddr() net.Addr { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} } -func (*testConn) SetDeadline(_ time.Time) error { return nil } -func (*testConn) SetReadDeadline(_ time.Time) error { return nil } -func (*testConn) SetWriteDeadline(_ time.Time) error { return nil } +func (c *testConn) LocalAddr() net.Addr { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} } +func (c *testConn) RemoteAddr() net.Addr { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} } +func (c *testConn) SetDeadline(_ time.Time) error { return nil } +func (c *testConn) SetReadDeadline(_ time.Time) error { return nil } +func (c *testConn) SetWriteDeadline(_ time.Time) error { return nil } -func getStringImmutable(b []byte) string { +var getStringImmutable = func(b []byte) string { return string(b) } -func getBytesImmutable(s string) []byte { +var getBytesImmutable = func(s string) (b []byte) { return []byte(s) } @@ -347,7 +335,6 @@ func getBytesImmutable(s string) []byte { func (app *App) methodInt(s string) int { // For better performance if len(app.configured.RequestMethods) == 0 { - //nolint:gomnd // TODO: Use iota instead switch s { case MethodGet: return 0 @@ -404,7 +391,8 @@ func IsMethodIdempotent(m string) bool { } switch m { - case MethodPut, MethodDelete: + case MethodPut, + MethodDelete: return true default: return false @@ -726,7 +714,7 @@ const ( ConstraintBool = "bool" ConstraintFloat = "float" ConstraintAlpha = "alpha" - ConstraintGuid = "guid" //nolint:revive,stylecheck // TODO: Rename to "ConstraintGUID" in v3 + ConstraintGuid = "guid" ConstraintMinLen = "minLen" ConstraintMaxLen = "maxLen" ConstraintLen = "len" diff --git a/helpers_test.go b/helpers_test.go index 7bb394e520..fefb8f2527 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -11,7 +11,6 @@ import ( "time" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) diff --git a/hooks.go b/hooks.go index c66e49fde8..b2766a8cab 100644 --- a/hooks.go +++ b/hooks.go @@ -1,20 +1,14 @@ package fiber -import ( - "log" -) - // OnRouteHandler Handlers define a function to create hooks for Fiber. -type ( - OnRouteHandler = func(Route) error - OnNameHandler = OnRouteHandler - OnGroupHandler = func(Group) error - OnGroupNameHandler = OnGroupHandler - OnListenHandler = func() error - OnShutdownHandler = OnListenHandler - OnForkHandler = func(int) error - OnMountHandler = func(*App) error -) +type OnRouteHandler = func(Route) error +type OnNameHandler = OnRouteHandler +type OnGroupHandler = func(Group) error +type OnGroupNameHandler = OnGroupHandler +type OnListenHandler = func() error +type OnShutdownHandler = OnListenHandler +type OnForkHandler = func(int) error +type OnMountHandler = func(*App) error // Hooks is a struct to use it with App. type Hooks struct { @@ -186,17 +180,13 @@ func (h *Hooks) executeOnListenHooks() error { func (h *Hooks) executeOnShutdownHooks() { for _, v := range h.onShutdown { - if err := v(); err != nil { - log.Printf("failed to call shutdown hook: %v\n", err) - } + _ = v() } } func (h *Hooks) executeOnForkHooks(pid int) { for _, v := range h.onFork { - if err := v(pid); err != nil { - log.Printf("failed to call fork hook: %v\n", err) - } + _ = v(pid) } } diff --git a/hooks_test.go b/hooks_test.go index 6a2fc3bfbb..df3c2aed96 100644 --- a/hooks_test.go +++ b/hooks_test.go @@ -7,11 +7,10 @@ import ( "time" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/bytebufferpool" ) -func testSimpleHandler(c *Ctx) error { +var testSimpleHandler = func(c *Ctx) error { return c.SendString("simple") } diff --git a/internal/dictpool/pool.go b/internal/dictpool/pool.go index baebe7e236..6160a4ff65 100644 --- a/internal/dictpool/pool.go +++ b/internal/dictpool/pool.go @@ -10,7 +10,7 @@ var defaultPool = sync.Pool{ // AcquireDict acquire new dict. func AcquireDict() *Dict { - return defaultPool.Get().(*Dict) + return defaultPool.Get().(*Dict) // nolint:forcetypeassert } // ReleaseDict release dict. diff --git a/internal/gopsutil/common/common.go b/internal/gopsutil/common/common.go index ed4a3bfcb3..a02fce4b1a 100644 --- a/internal/gopsutil/common/common.go +++ b/internal/gopsutil/common/common.go @@ -366,7 +366,7 @@ func HostDev(combineWith ...string) string { // getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running // sysctl commands (see DoSysctrl). func getSysctrlEnv(env []string) []string { - var foundLC bool + foundLC := false for i, line := range env { if strings.HasPrefix(line, "LC_ALL") { env[i] = "LC_ALL=C" diff --git a/internal/gopsutil/mem/mem.go b/internal/gopsutil/mem/mem.go index e2ee01e5c6..b039c4ce4e 100644 --- a/internal/gopsutil/mem/mem.go +++ b/internal/gopsutil/mem/mem.go @@ -6,7 +6,8 @@ import ( "github.com/gofiber/fiber/v2/internal/gopsutil/common" ) -var invoke common.Invoker = common.Invoke{} //nolint:unused // We use this only for some OS'es +//lint:ignore U1000 we need this elsewhere +var invoke common.Invoker = common.Invoke{} //nolint:all // Memory usage statistics. Total, Available and Used contain numbers of bytes // for human consumption. diff --git a/internal/gopsutil/mem/mem_freebsd.go b/internal/gopsutil/mem/mem_freebsd.go index d30e7bd315..0682edb7cf 100644 --- a/internal/gopsutil/mem/mem_freebsd.go +++ b/internal/gopsutil/mem/mem_freebsd.go @@ -86,6 +86,7 @@ func SwapMemory() (*SwapMemoryStat, error) { } // Constants from vm/vm_param.h +// nolint: golint const ( XSWDEV_VERSION11 = 1 XSWDEV_VERSION = 2 diff --git a/internal/gopsutil/mem/mem_linux.go b/internal/gopsutil/mem/mem_linux.go index 3e7e93b5a8..a0fc7fd44c 100644 --- a/internal/gopsutil/mem/mem_linux.go +++ b/internal/gopsutil/mem/mem_linux.go @@ -57,12 +57,10 @@ func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *Virtu lines, _ := common.ReadLines(filename) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+) - var ( - memavail bool - activeFile bool // "Active(file)" not available: 2.6.28 / Dec 2008 - inactiveFile bool // "Inactive(file)" not available: 2.6.28 / Dec 2008 - sReclaimable bool // "SReclaimable:" not available: 2.6.19 / Nov 2006 - ) + memavail := false + activeFile := false // "Active(file)" not available: 2.6.28 / Dec 2008 + inactiveFile := false // "Inactive(file)" not available: 2.6.28 / Dec 2008 + sReclaimable := false // "SReclaimable:" not available: 2.6.19 / Nov 2006 ret := &VirtualMemoryStat{} retEx := &VirtualMemoryExStat{} diff --git a/internal/msgp/json.go b/internal/msgp/json.go index 80d39635ca..0e11e603c0 100644 --- a/internal/msgp/json.go +++ b/internal/msgp/json.go @@ -168,7 +168,7 @@ func rwArray(dst jsWriter, src *Reader) (n int, err error) { if err != nil { return } - var comma bool + comma := false for i := uint32(0); i < sz; i++ { if comma { err = dst.WriteByte(',') diff --git a/internal/schema/cache.go b/internal/schema/cache.go index cb227a6969..bf21697cf1 100644 --- a/internal/schema/cache.go +++ b/internal/schema/cache.go @@ -163,7 +163,7 @@ func (c *cache) createField(field reflect.StructField, parentAlias string) *fiel } // Check if the type is supported and don't cache it if not. // First let's get the basic type. - var isSlice, isStruct bool + isSlice, isStruct := false, false ft := field.Type m := isTextUnmarshaler(reflect.Zero(ft)) if ft.Kind() == reflect.Ptr { diff --git a/internal/storage/memory/memory_test.go b/internal/storage/memory/memory_test.go index 7fc6b955d8..fb2b88a0e5 100644 --- a/internal/storage/memory/memory_test.go +++ b/internal/storage/memory/memory_test.go @@ -149,13 +149,13 @@ func Benchmark_Storage_Memory(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { for _, key := range keys { - _ = d.Set(key, value, ttl) + d.Set(key, value, ttl) } for _, key := range keys { _, _ = d.Get(key) } for _, key := range keys { - _ = d.Delete(key) + d.Delete(key) } } }) diff --git a/internal/template/html/html.go b/internal/template/html/html.go index 446431f7b2..71f6f02cb5 100644 --- a/internal/template/html/html.go +++ b/internal/template/html/html.go @@ -156,6 +156,7 @@ func (e *Engine) Load() error { name = strings.TrimSuffix(name, e.extension) // name = strings.Replace(name, e.extension, "", -1) // Read the file + // #gosec G304 buf, err := utils.ReadFile(path, e.fileSystem) if err != nil { return err diff --git a/internal/template/utils/utils.go b/internal/template/utils/utils.go index ee681b4f99..0ae8f22fd8 100644 --- a/internal/template/utils/utils.go +++ b/internal/template/utils/utils.go @@ -21,6 +21,7 @@ func Walk(fs http.FileSystem, root string, walkFn filepath.WalkFunc) error { 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 { diff --git a/listen.go b/listen.go index 19dbae3621..ddbf8c81fc 100644 --- a/listen.go +++ b/listen.go @@ -9,7 +9,6 @@ import ( "crypto/x509" "errors" "fmt" - "log" "net" "os" "path/filepath" @@ -32,7 +31,7 @@ func (app *App) Listener(ln net.Listener) error { // Print startup message if !app.config.DisableStartupMessage { - app.startupMessage(ln.Addr().String(), getTLSConfig(ln) != nil, "") + app.startupMessage(ln.Addr().String(), getTlsConfig(ln) != nil, "") } // Print routes @@ -42,7 +41,7 @@ func (app *App) Listener(ln net.Listener) error { // Prefork is not supported for custom listeners if app.config.Prefork { - log.Printf("[Warning] Prefork isn't supported for custom listeners.\n") + fmt.Println("[Warning] Prefork isn't supported for custom listeners.") } // Start listening @@ -62,7 +61,7 @@ func (app *App) Listen(addr string) error { // Setup listener ln, err := net.Listen(app.config.Network, addr) if err != nil { - return fmt.Errorf("failed to listen: %w", err) + return err } // prepare the server for the start @@ -95,7 +94,7 @@ func (app *App) ListenTLS(addr, certFile, keyFile string) error { // Set TLS config with handler cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { - return fmt.Errorf("tls: cannot load TLS key pair from certFile=%q and keyFile=%q: %w", certFile, keyFile, err) + return fmt.Errorf("tls: cannot load TLS key pair from certFile=%q and keyFile=%q: %s", certFile, keyFile, err) } tlsHandler := &TLSHandler{} @@ -116,7 +115,7 @@ func (app *App) ListenTLS(addr, certFile, keyFile string) error { ln, err := net.Listen(app.config.Network, addr) ln = tls.NewListener(ln, config) if err != nil { - return fmt.Errorf("failed to listen: %w", err) + return err } // prepare the server for the start @@ -151,12 +150,12 @@ func (app *App) ListenMutualTLS(addr, certFile, keyFile, clientCertFile string) cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { - return fmt.Errorf("tls: cannot load TLS key pair from certFile=%q and keyFile=%q: %w", certFile, keyFile, err) + return fmt.Errorf("tls: cannot load TLS key pair from certFile=%q and keyFile=%q: %s", certFile, keyFile, err) } clientCACert, err := os.ReadFile(filepath.Clean(clientCertFile)) if err != nil { - return fmt.Errorf("failed to read file: %w", err) + return err } clientCertPool := x509.NewCertPool() clientCertPool.AppendCertsFromPEM(clientCACert) @@ -180,7 +179,7 @@ func (app *App) ListenMutualTLS(addr, certFile, keyFile, clientCertFile string) // Setup listener ln, err := tls.Listen(app.config.Network, addr, config) if err != nil { - return fmt.Errorf("failed to listen: %w", err) + return err } // prepare the server for the start @@ -204,7 +203,7 @@ func (app *App) ListenMutualTLS(addr, certFile, keyFile, clientCertFile string) } // startupMessage prepares the startup message with the handler number, port, address and other information -func (app *App) startupMessage(addr string, tls bool, pids string) { //nolint: revive // Accepting a bool param is fine here +func (app *App) startupMessage(addr string, tls bool, pids string) { // ignore child processes if IsChild() { return @@ -228,8 +227,7 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { //nolint: r } center := func(s string, width int) string { - const padDiv = 2 - pad := strconv.Itoa((width - len(s)) / padDiv) + pad := strconv.Itoa((width - len(s)) / 2) str := fmt.Sprintf("%"+pad+"s", " ") str += s str += fmt.Sprintf("%"+pad+"s", " ") @@ -240,8 +238,7 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { //nolint: r } centerValue := func(s string, width int) string { - const padDiv = 2 - pad := strconv.Itoa((width - runewidth.StringWidth(s)) / padDiv) + pad := strconv.Itoa((width - runewidth.StringWidth(s)) / 2) str := fmt.Sprintf("%"+pad+"s", " ") str += fmt.Sprintf("%s%s%s", colors.Cyan, s, colors.Black) str += fmt.Sprintf("%"+pad+"s", " ") @@ -252,13 +249,13 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { //nolint: r return str } - pad := func(s string, width int) string { + pad := func(s string, width int) (str string) { toAdd := width - len(s) - str := s + str += s for i := 0; i < toAdd; i++ { str += " " } - return str + return } host, port := parseAddr(addr) @@ -270,9 +267,9 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { //nolint: r } } - scheme := schemeHTTP + scheme := "http" if tls { - scheme = schemeHTTPS + scheme = "https" } isPrefork := "Disabled" @@ -285,18 +282,19 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { //nolint: r procs = "1" } - const lineLen = 49 mainLogo := colors.Black + " ┌───────────────────────────────────────────────────┐\n" if app.config.AppName != "" { - mainLogo += " │ " + centerValue(app.config.AppName, lineLen) + " │\n" + mainLogo += " │ " + centerValue(app.config.AppName, 49) + " │\n" } - mainLogo += " │ " + centerValue("Fiber v"+Version, lineLen) + " │\n" + mainLogo += " │ " + centerValue("Fiber v"+Version, 49) + " │\n" if host == "0.0.0.0" { - mainLogo += " │ " + center(fmt.Sprintf("%s://127.0.0.1:%s", scheme, port), lineLen) + " │\n" + - " │ " + center(fmt.Sprintf("(bound on host 0.0.0.0 and port %s)", port), lineLen) + " │\n" + mainLogo += + " │ " + center(fmt.Sprintf("%s://127.0.0.1:%s", scheme, port), 49) + " │\n" + + " │ " + center(fmt.Sprintf("(bound on host 0.0.0.0 and port %s)", port), 49) + " │\n" } else { - mainLogo += " │ " + center(fmt.Sprintf("%s://%s:%s", scheme, host, port), lineLen) + " │\n" + mainLogo += + " │ " + center(fmt.Sprintf("%s://%s:%s", scheme, host, port), 49) + " │\n" } mainLogo += fmt.Sprintf( @@ -305,8 +303,8 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { //nolint: r " │ Prefork .%s PID ....%s │\n"+ " └───────────────────────────────────────────────────┘"+ colors.Reset, - value(strconv.Itoa(int(app.handlersCount)), 14), value(procs, 12), //nolint:gomnd // Using random padding lengths is fine here - value(isPrefork, 14), value(strconv.Itoa(os.Getpid()), 14), //nolint:gomnd // Using random padding lengths is fine here + value(strconv.Itoa(int(app.handlersCount)), 14), value(procs, 12), + value(isPrefork, 14), value(strconv.Itoa(os.Getpid()), 14), ) var childPidsLogo string @@ -331,21 +329,19 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { //nolint: r thisLine := "Child PIDs ... " var itemsOnThisLine []string - const maxLineLen = 49 - addLine := func() { lines = append(lines, fmt.Sprintf( newLine, colors.Black, - thisLine+colors.Cyan+pad(strings.Join(itemsOnThisLine, ", "), maxLineLen-len(thisLine)), + thisLine+colors.Cyan+pad(strings.Join(itemsOnThisLine, ", "), 49-len(thisLine)), colors.Black, ), ) } for _, pid := range pidSlice { - if len(thisLine+strings.Join(append(itemsOnThisLine, pid), ", ")) > maxLineLen { + if len(thisLine+strings.Join(append(itemsOnThisLine, pid), ", ")) > 49 { addLine() thisLine = "" itemsOnThisLine = []string{pid} @@ -419,7 +415,7 @@ func (app *App) printRoutesMessage() { var routes []RouteMessage for _, routeStack := range app.stack { for _, route := range routeStack { - var newRoute RouteMessage + var newRoute = RouteMessage{} newRoute.name = route.Name newRoute.method = route.Method newRoute.path = route.Path @@ -447,5 +443,5 @@ func (app *App) printRoutesMessage() { _, _ = fmt.Fprintf(w, "%s%s\t%s| %s%s\t%s| %s%s\t%s| %s%s\n", colors.Blue, route.method, colors.White, colors.Green, route.path, colors.White, colors.Cyan, route.name, colors.White, colors.Yellow, route.handlers) } - _ = w.Flush() //nolint:errcheck // It is fine to ignore the error here + _ = w.Flush() } diff --git a/listen_test.go b/listen_test.go index 63283d3485..0dd2cb2937 100644 --- a/listen_test.go +++ b/listen_test.go @@ -7,6 +7,7 @@ package fiber import ( "bytes" "crypto/tls" + "fmt" "io" "log" "os" @@ -16,7 +17,6 @@ import ( "time" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp/fasthttputil" ) @@ -125,10 +125,8 @@ func Test_App_Listener_TLS_Listener(t *testing.T) { if err != nil { utils.AssertEqual(t, nil, err) } - //nolint:gosec // We're in a test so using old ciphers is fine config := &tls.Config{Certificates: []tls.Certificate{cer}} - //nolint:gosec // We're in a test so listening on all interfaces is fine ln, err := tls.Listen(NetworkTCP4, ":0", config) utils.AssertEqual(t, nil, err) @@ -184,6 +182,7 @@ func Test_App_Master_Process_Show_Startup_Message(t *testing.T) { New(Config{Prefork: true}). startupMessage(":3000", true, strings.Repeat(",11111,22222,33333,44444,55555,60000", 10)) }) + fmt.Println(startupMessage) utils.AssertEqual(t, true, strings.Contains(startupMessage, "https://127.0.0.1:3000")) utils.AssertEqual(t, true, strings.Contains(startupMessage, "(bound on host 0.0.0.0 and port 3000)")) utils.AssertEqual(t, true, strings.Contains(startupMessage, "Child PIDs")) @@ -197,6 +196,7 @@ func Test_App_Master_Process_Show_Startup_MessageWithAppName(t *testing.T) { startupMessage := captureOutput(func() { app.startupMessage(":3000", true, strings.Repeat(",11111,22222,33333,44444,55555,60000", 10)) }) + fmt.Println(startupMessage) utils.AssertEqual(t, "Test App v1.0.1", app.Config().AppName) utils.AssertEqual(t, true, strings.Contains(startupMessage, app.Config().AppName)) } @@ -208,6 +208,7 @@ func Test_App_Master_Process_Show_Startup_MessageWithAppNameNonAscii(t *testing. startupMessage := captureOutput(func() { app.startupMessage(":3000", false, "") }) + fmt.Println(startupMessage) utils.AssertEqual(t, true, strings.Contains(startupMessage, "│ Serveur de vérification des données │")) } @@ -218,7 +219,8 @@ func Test_App_print_Route(t *testing.T) { printRoutesMessage := captureOutput(func() { app.printRoutesMessage() }) - utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, MethodGet)) + fmt.Println(printRoutesMessage) + utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "GET")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "/")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "emptyHandler")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "routeName")) @@ -238,11 +240,11 @@ func Test_App_print_Route_with_group(t *testing.T) { app.printRoutesMessage() }) - utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, MethodGet)) + utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "GET")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "/")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "emptyHandler")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "/v1/test")) - utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, MethodPost)) + utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "POST")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "/v1/test/fiber")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "PUT")) utils.AssertEqual(t, true, strings.Contains(printRoutesMessage, "/v1/test/fiber/*")) diff --git a/middleware/basicauth/basicauth_test.go b/middleware/basicauth/basicauth_test.go index 1284163203..20f103e6b6 100644 --- a/middleware/basicauth/basicauth_test.go +++ b/middleware/basicauth/basicauth_test.go @@ -1,15 +1,15 @@ package basicauth import ( - "encoding/base64" "fmt" "io" "net/http/httptest" "testing" + b64 "encoding/base64" + "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -23,7 +23,7 @@ func Test_BasicAuth_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -39,7 +39,6 @@ func Test_Middleware_BasicAuth(t *testing.T) { }, })) - //nolint:forcetypeassert,errcheck // TODO: Do not force-type assert app.Get("/testauth", func(c *fiber.Ctx) error { username := c.Locals("username").(string) password := c.Locals("password").(string) @@ -75,9 +74,9 @@ func Test_Middleware_BasicAuth(t *testing.T) { for _, tt := range tests { // Base64 encode credentials for http auth header - creds := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", tt.username, tt.password))) + creds := b64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", tt.username, tt.password))) - req := httptest.NewRequest(fiber.MethodGet, "/testauth", nil) + req := httptest.NewRequest("GET", "/testauth", nil) req.Header.Add("Authorization", "Basic "+creds) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) @@ -109,7 +108,7 @@ func Benchmark_Middleware_BasicAuth(b *testing.B) { h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/") fctx.Request.Header.Set(fiber.HeaderAuthorization, "basic am9objpkb2U=") // john:doe diff --git a/middleware/basicauth/config.go b/middleware/basicauth/config.go index b19d5087ea..3845e91538 100644 --- a/middleware/basicauth/config.go +++ b/middleware/basicauth/config.go @@ -53,8 +53,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, Users: map[string]string{}, diff --git a/middleware/cache/cache.go b/middleware/cache/cache.go index 8a733b7571..f6db49e2cf 100644 --- a/middleware/cache/cache.go +++ b/middleware/cache/cache.go @@ -34,7 +34,6 @@ const ( noStore = "no-store" ) -//nolint:gochecknoglobals // TODO: Do not use a global var here var ignoreHeaders = map[string]interface{}{ "Connection": nil, "Keep-Alive": nil, @@ -44,8 +43,8 @@ var ignoreHeaders = map[string]interface{}{ "Trailers": nil, "Transfer-Encoding": nil, "Upgrade": nil, - "Content-Type": nil, // already stored explicitly by the cache manager - "Content-Encoding": nil, // already stored explicitly by the cache manager + "Content-Type": nil, // already stored explicitely by the cache manager + "Content-Encoding": nil, // already stored explicitely by the cache manager } // New creates a new middleware handler @@ -70,7 +69,7 @@ func New(config ...Config) fiber.Handler { // Create indexed heap for tracking expirations ( see heap.go ) heap := &indexedHeap{} // count stored bytes (sizes of response bodies) - var storedBytes uint + var storedBytes uint = 0 // Update timestamp in the configured interval go func() { @@ -82,10 +81,10 @@ func New(config ...Config) fiber.Handler { // Delete key from both manager and storage deleteKey := func(dkey string) { - manager.del(dkey) + manager.delete(dkey) // External storage saves body data with different key if cfg.Storage != nil { - manager.del(dkey + "_body") + manager.delete(dkey + "_body") } } @@ -206,7 +205,7 @@ func New(config ...Config) fiber.Handler { if cfg.StoreResponseHeaders { e.headers = make(map[string][]byte) c.Response().Header.VisitAll( - func(key, value []byte) { + func(key []byte, value []byte) { // create real copy keyS := string(key) if _, ok := ignoreHeaders[keyS]; !ok { diff --git a/middleware/cache/cache_test.go b/middleware/cache/cache_test.go index 404a1edf2d..e261023820 100644 --- a/middleware/cache/cache_test.go +++ b/middleware/cache/cache_test.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "math" + "net/http" "net/http/httptest" "os" "strconv" @@ -17,7 +18,6 @@ import ( "github.com/gofiber/fiber/v2/internal/storage/memory" "github.com/gofiber/fiber/v2/middleware/etag" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -35,10 +35,10 @@ func Test_Cache_CacheControl(t *testing.T) { return c.SendString("Hello, World!") }) - _, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + _, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "public, max-age=10", resp.Header.Get(fiber.HeaderCacheControl)) } @@ -53,7 +53,7 @@ func Test_Cache_Expired(t *testing.T) { return c.SendString(fmt.Sprintf("%d", time.Now().UnixNano())) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) body, err := io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) @@ -61,7 +61,7 @@ func Test_Cache_Expired(t *testing.T) { // Sleep until the cache is expired time.Sleep(3 * time.Second) - respCached, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + respCached, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) bodyCached, err := io.ReadAll(respCached.Body) utils.AssertEqual(t, nil, err) @@ -71,7 +71,7 @@ func Test_Cache_Expired(t *testing.T) { } // Next response should be also cached - respCachedNextRound, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + respCachedNextRound, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) bodyCachedNextRound, err := io.ReadAll(respCachedNextRound.Body) utils.AssertEqual(t, nil, err) @@ -92,11 +92,11 @@ func Test_Cache(t *testing.T) { return c.SendString(now) }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) - cachedReq := httptest.NewRequest(fiber.MethodGet, "/", nil) + cachedReq := httptest.NewRequest("GET", "/", nil) cachedResp, err := app.Test(cachedReq) utils.AssertEqual(t, nil, err) @@ -120,31 +120,31 @@ func Test_Cache_WithNoCacheRequestDirective(t *testing.T) { }) // Request id = 1 - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) resp, err := app.Test(req) - utils.AssertEqual(t, nil, err) - body, err := io.ReadAll(resp.Body) + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheMiss, resp.Header.Get("X-Cache")) utils.AssertEqual(t, []byte("1"), body) // Response cached, entry id = 1 // Request id = 2 without Cache-Control: no-cache - cachedReq := httptest.NewRequest(fiber.MethodGet, "/?id=2", nil) + cachedReq := httptest.NewRequest("GET", "/?id=2", nil) cachedResp, err := app.Test(cachedReq) - utils.AssertEqual(t, nil, err) - cachedBody, err := io.ReadAll(cachedResp.Body) + defer cachedResp.Body.Close() + cachedBody, _ := io.ReadAll(cachedResp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheHit, cachedResp.Header.Get("X-Cache")) utils.AssertEqual(t, []byte("1"), cachedBody) // Response not cached, returns cached response, entry id = 1 // Request id = 2 with Cache-Control: no-cache - noCacheReq := httptest.NewRequest(fiber.MethodGet, "/?id=2", nil) + noCacheReq := httptest.NewRequest("GET", "/?id=2", nil) noCacheReq.Header.Set(fiber.HeaderCacheControl, noCache) noCacheResp, err := app.Test(noCacheReq) - utils.AssertEqual(t, nil, err) - noCacheBody, err := io.ReadAll(noCacheResp.Body) + defer noCacheResp.Body.Close() + noCacheBody, _ := io.ReadAll(noCacheResp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheMiss, noCacheResp.Header.Get("X-Cache")) utils.AssertEqual(t, []byte("2"), noCacheBody) @@ -152,21 +152,21 @@ func Test_Cache_WithNoCacheRequestDirective(t *testing.T) { /* Check Test_Cache_WithETagAndNoCacheRequestDirective */ // Request id = 2 with Cache-Control: no-cache again - noCacheReq1 := httptest.NewRequest(fiber.MethodGet, "/?id=2", nil) + noCacheReq1 := httptest.NewRequest("GET", "/?id=2", nil) noCacheReq1.Header.Set(fiber.HeaderCacheControl, noCache) noCacheResp1, err := app.Test(noCacheReq1) - utils.AssertEqual(t, nil, err) - noCacheBody1, err := io.ReadAll(noCacheResp1.Body) + defer noCacheResp1.Body.Close() + noCacheBody1, _ := io.ReadAll(noCacheResp1.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheMiss, noCacheResp1.Header.Get("X-Cache")) utils.AssertEqual(t, []byte("2"), noCacheBody1) // Response cached, returns updated response, entry = 2 // Request id = 1 without Cache-Control: no-cache - cachedReq1 := httptest.NewRequest(fiber.MethodGet, "/", nil) + cachedReq1 := httptest.NewRequest("GET", "/", nil) cachedResp1, err := app.Test(cachedReq1) - utils.AssertEqual(t, nil, err) - cachedBody1, err := io.ReadAll(cachedResp1.Body) + defer cachedResp1.Body.Close() + cachedBody1, _ := io.ReadAll(cachedResp1.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheHit, cachedResp1.Header.Get("X-Cache")) utils.AssertEqual(t, []byte("2"), cachedBody1) @@ -188,7 +188,7 @@ func Test_Cache_WithETagAndNoCacheRequestDirective(t *testing.T) { }) // Request id = 1 - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheMiss, resp.Header.Get("X-Cache")) @@ -199,7 +199,7 @@ func Test_Cache_WithETagAndNoCacheRequestDirective(t *testing.T) { etagToken := resp.Header.Get("Etag") // Request id = 2 with ETag but without Cache-Control: no-cache - cachedReq := httptest.NewRequest(fiber.MethodGet, "/?id=2", nil) + cachedReq := httptest.NewRequest("GET", "/?id=2", nil) cachedReq.Header.Set(fiber.HeaderIfNoneMatch, etagToken) cachedResp, err := app.Test(cachedReq) utils.AssertEqual(t, nil, err) @@ -208,7 +208,7 @@ func Test_Cache_WithETagAndNoCacheRequestDirective(t *testing.T) { // Response not cached, returns cached response, entry id = 1, status not modified // Request id = 2 with ETag and Cache-Control: no-cache - noCacheReq := httptest.NewRequest(fiber.MethodGet, "/?id=2", nil) + noCacheReq := httptest.NewRequest("GET", "/?id=2", nil) noCacheReq.Header.Set(fiber.HeaderCacheControl, noCache) noCacheReq.Header.Set(fiber.HeaderIfNoneMatch, etagToken) noCacheResp, err := app.Test(noCacheReq) @@ -221,7 +221,7 @@ func Test_Cache_WithETagAndNoCacheRequestDirective(t *testing.T) { etagToken = noCacheResp.Header.Get("Etag") // Request id = 2 with ETag and Cache-Control: no-cache again - noCacheReq1 := httptest.NewRequest(fiber.MethodGet, "/?id=2", nil) + noCacheReq1 := httptest.NewRequest("GET", "/?id=2", nil) noCacheReq1.Header.Set(fiber.HeaderCacheControl, noCache) noCacheReq1.Header.Set(fiber.HeaderIfNoneMatch, etagToken) noCacheResp1, err := app.Test(noCacheReq1) @@ -231,7 +231,7 @@ func Test_Cache_WithETagAndNoCacheRequestDirective(t *testing.T) { // Response cached, returns updated response, entry id = 2, status not modified // Request id = 1 without ETag and Cache-Control: no-cache - cachedReq1 := httptest.NewRequest(fiber.MethodGet, "/", nil) + cachedReq1 := httptest.NewRequest("GET", "/", nil) cachedResp1, err := app.Test(cachedReq1) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheHit, cachedResp1.Header.Get("X-Cache")) @@ -251,11 +251,11 @@ func Test_Cache_WithNoStoreRequestDirective(t *testing.T) { }) // Request id = 2 - noStoreReq := httptest.NewRequest(fiber.MethodGet, "/?id=2", nil) + noStoreReq := httptest.NewRequest("GET", "/?id=2", nil) noStoreReq.Header.Set(fiber.HeaderCacheControl, noStore) noStoreResp, err := app.Test(noStoreReq) - utils.AssertEqual(t, nil, err) - noStoreBody, err := io.ReadAll(noStoreResp.Body) + defer noStoreResp.Body.Close() + noStoreBody, _ := io.ReadAll(noStoreResp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, []byte("2"), noStoreBody) // Response not cached, returns updated response @@ -278,11 +278,11 @@ func Test_Cache_WithSeveralRequests(t *testing.T) { for runs := 0; runs < 10; runs++ { for i := 0; i < 10; i++ { func(id int) { - rsp, err := app.Test(httptest.NewRequest(fiber.MethodGet, fmt.Sprintf("/%d", id), nil)) + rsp, err := app.Test(httptest.NewRequest(http.MethodGet, fmt.Sprintf("/%d", id), nil)) utils.AssertEqual(t, nil, err) - defer func(body io.ReadCloser) { - err := body.Close() + defer func(Body io.ReadCloser) { + err := Body.Close() utils.AssertEqual(t, nil, err) }(rsp.Body) @@ -311,11 +311,11 @@ func Test_Cache_Invalid_Expiration(t *testing.T) { return c.SendString(now) }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) - cachedReq := httptest.NewRequest(fiber.MethodGet, "/", nil) + cachedReq := httptest.NewRequest("GET", "/", nil) cachedResp, err := app.Test(cachedReq) utils.AssertEqual(t, nil, err) @@ -342,25 +342,25 @@ func Test_Cache_Get(t *testing.T) { return c.SendString(c.Query("cache")) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodPost, "/?cache=123", nil)) + resp, err := app.Test(httptest.NewRequest("POST", "/?cache=123", nil)) utils.AssertEqual(t, nil, err) body, err := io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "123", string(body)) - resp, err = app.Test(httptest.NewRequest(fiber.MethodPost, "/?cache=12345", nil)) + resp, err = app.Test(httptest.NewRequest("POST", "/?cache=12345", nil)) utils.AssertEqual(t, nil, err) body, err = io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "12345", string(body)) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/get?cache=123", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/get?cache=123", nil)) utils.AssertEqual(t, nil, err) body, err = io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "123", string(body)) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/get?cache=12345", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/get?cache=12345", nil)) utils.AssertEqual(t, nil, err) body, err = io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) @@ -384,25 +384,25 @@ func Test_Cache_Post(t *testing.T) { return c.SendString(c.Query("cache")) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodPost, "/?cache=123", nil)) + resp, err := app.Test(httptest.NewRequest("POST", "/?cache=123", nil)) utils.AssertEqual(t, nil, err) body, err := io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "123", string(body)) - resp, err = app.Test(httptest.NewRequest(fiber.MethodPost, "/?cache=12345", nil)) + resp, err = app.Test(httptest.NewRequest("POST", "/?cache=12345", nil)) utils.AssertEqual(t, nil, err) body, err = io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "123", string(body)) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/get?cache=123", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/get?cache=123", nil)) utils.AssertEqual(t, nil, err) body, err = io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "123", string(body)) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/get?cache=12345", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/get?cache=12345", nil)) utils.AssertEqual(t, nil, err) body, err = io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) @@ -420,14 +420,14 @@ func Test_Cache_NothingToCache(t *testing.T) { return c.SendString(time.Now().String()) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) body, err := io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) time.Sleep(500 * time.Millisecond) - respCached, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + respCached, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) bodyCached, err := io.ReadAll(respCached.Body) utils.AssertEqual(t, nil, err) @@ -457,22 +457,22 @@ func Test_Cache_CustomNext(t *testing.T) { return c.Status(fiber.StatusInternalServerError).SendString(time.Now().String()) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) body, err := io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) - respCached, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + respCached, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) bodyCached, err := io.ReadAll(respCached.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, true, bytes.Equal(body, bodyCached)) utils.AssertEqual(t, true, respCached.Header.Get(fiber.HeaderCacheControl) != "") - _, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/error", nil)) + _, err = app.Test(httptest.NewRequest("GET", "/error", nil)) utils.AssertEqual(t, nil, err) - errRespCached, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/error", nil)) + errRespCached, err := app.Test(httptest.NewRequest("GET", "/error", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, true, errRespCached.Header.Get(fiber.HeaderCacheControl) == "") } @@ -491,7 +491,7 @@ func Test_CustomKey(t *testing.T) { return c.SendString("hi") }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) _, err := app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, true, called) @@ -505,9 +505,7 @@ func Test_CustomExpiration(t *testing.T) { var newCacheTime int app.Use(New(Config{ExpirationGenerator: func(c *fiber.Ctx, cfg *Config) time.Duration { called = true - var err error - newCacheTime, err = strconv.Atoi(c.GetRespHeader("Cache-Time", "600")) - utils.AssertEqual(t, nil, err) + newCacheTime, _ = strconv.Atoi(c.GetRespHeader("Cache-Time", "600")) return time.Second * time.Duration(newCacheTime) }})) @@ -517,7 +515,7 @@ func Test_CustomExpiration(t *testing.T) { return c.SendString(now) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, true, called) utils.AssertEqual(t, 1, newCacheTime) @@ -525,7 +523,7 @@ func Test_CustomExpiration(t *testing.T) { // Sleep until the cache is expired time.Sleep(1 * time.Second) - cachedResp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + cachedResp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) body, err := io.ReadAll(resp.Body) @@ -538,7 +536,7 @@ func Test_CustomExpiration(t *testing.T) { } // Next response should be cached - cachedRespNextRound, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + cachedRespNextRound, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) cachedBodyNextRound, err := io.ReadAll(cachedRespNextRound.Body) utils.AssertEqual(t, nil, err) @@ -561,12 +559,12 @@ func Test_AdditionalE2EResponseHeaders(t *testing.T) { return c.SendString("hi") }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "foobar", resp.Header.Get("X-Foobar")) - req = httptest.NewRequest(fiber.MethodGet, "/", nil) + req = httptest.NewRequest("GET", "/", nil) resp, err = app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "foobar", resp.Header.Get("X-Foobar")) @@ -596,19 +594,19 @@ func Test_CacheHeader(t *testing.T) { return c.Status(fiber.StatusInternalServerError).SendString(time.Now().String()) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheMiss, resp.Header.Get("X-Cache")) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheHit, resp.Header.Get("X-Cache")) - resp, err = app.Test(httptest.NewRequest(fiber.MethodPost, "/?cache=12345", nil)) + resp, err = app.Test(httptest.NewRequest("POST", "/?cache=12345", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheUnreachable, resp.Header.Get("X-Cache")) - errRespCached, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/error", nil)) + errRespCached, err := app.Test(httptest.NewRequest("GET", "/error", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheUnreachable, errRespCached.Header.Get("X-Cache")) } @@ -624,12 +622,12 @@ func Test_Cache_WithHead(t *testing.T) { return c.SendString(now) }) - req := httptest.NewRequest(fiber.MethodHead, "/", nil) + req := httptest.NewRequest("HEAD", "/", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheMiss, resp.Header.Get("X-Cache")) - cachedReq := httptest.NewRequest(fiber.MethodHead, "/", nil) + cachedReq := httptest.NewRequest("HEAD", "/", nil) cachedResp, err := app.Test(cachedReq) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheHit, cachedResp.Header.Get("X-Cache")) @@ -651,28 +649,28 @@ func Test_Cache_WithHeadThenGet(t *testing.T) { return c.SendString(c.Query("cache")) }) - headResp, err := app.Test(httptest.NewRequest(fiber.MethodHead, "/?cache=123", nil)) + headResp, err := app.Test(httptest.NewRequest("HEAD", "/?cache=123", nil)) utils.AssertEqual(t, nil, err) headBody, err := io.ReadAll(headResp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "", string(headBody)) utils.AssertEqual(t, cacheMiss, headResp.Header.Get("X-Cache")) - headResp, err = app.Test(httptest.NewRequest(fiber.MethodHead, "/?cache=123", nil)) + headResp, err = app.Test(httptest.NewRequest("HEAD", "/?cache=123", nil)) utils.AssertEqual(t, nil, err) headBody, err = io.ReadAll(headResp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "", string(headBody)) utils.AssertEqual(t, cacheHit, headResp.Header.Get("X-Cache")) - getResp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/?cache=123", nil)) + getResp, err := app.Test(httptest.NewRequest("GET", "/?cache=123", nil)) utils.AssertEqual(t, nil, err) getBody, err := io.ReadAll(getResp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "123", string(getBody)) utils.AssertEqual(t, cacheMiss, getResp.Header.Get("X-Cache")) - getResp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/?cache=123", nil)) + getResp, err = app.Test(httptest.NewRequest("GET", "/?cache=123", nil)) utils.AssertEqual(t, nil, err) getBody, err = io.ReadAll(getResp.Body) utils.AssertEqual(t, nil, err) @@ -693,7 +691,7 @@ func Test_CustomCacheHeader(t *testing.T) { return c.SendString("Hello, World!") }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, cacheMiss, resp.Header.Get("Cache-Status")) } @@ -704,7 +702,7 @@ func Test_CustomCacheHeader(t *testing.T) { func stableAscendingExpiration() func(c1 *fiber.Ctx, c2 *Config) time.Duration { i := 0 return func(c1 *fiber.Ctx, c2 *Config) time.Duration { - i++ + i += 1 return time.Hour * time.Duration(i) } } @@ -740,7 +738,7 @@ func Test_Cache_MaxBytesOrder(t *testing.T) { } for idx, tcase := range cases { - rsp, err := app.Test(httptest.NewRequest(fiber.MethodGet, tcase[0], nil)) + rsp, err := app.Test(httptest.NewRequest("GET", tcase[0], nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, tcase[1], rsp.Header.Get("X-Cache"), fmt.Sprintf("Case %v", idx)) } @@ -758,8 +756,7 @@ func Test_Cache_MaxBytesSizes(t *testing.T) { app.Get("/*", func(c *fiber.Ctx) error { path := c.Context().URI().LastPathSegment() - size, err := strconv.Atoi(string(path)) - utils.AssertEqual(t, nil, err) + size, _ := strconv.Atoi(string(path)) return c.Send(make([]byte, size)) }) @@ -775,7 +772,7 @@ func Test_Cache_MaxBytesSizes(t *testing.T) { } for idx, tcase := range cases { - rsp, err := app.Test(httptest.NewRequest(fiber.MethodGet, tcase[0], nil)) + rsp, err := app.Test(httptest.NewRequest("GET", tcase[0], nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, tcase[1], rsp.Header.Get("X-Cache"), fmt.Sprintf("Case %v", idx)) } @@ -788,14 +785,14 @@ func Benchmark_Cache(b *testing.B) { app.Use(New()) app.Get("/demo", func(c *fiber.Ctx) error { - data, _ := os.ReadFile("../../.github/README.md") //nolint:errcheck // We're inside a benchmark + data, _ := os.ReadFile("../../.github/README.md") return c.Status(fiber.StatusTeapot).Send(data) }) h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/demo") b.ReportAllocs() @@ -818,14 +815,14 @@ func Benchmark_Cache_Storage(b *testing.B) { })) app.Get("/demo", func(c *fiber.Ctx) error { - data, _ := os.ReadFile("../../.github/README.md") //nolint:errcheck // We're inside a benchmark + data, _ := os.ReadFile("../../.github/README.md") return c.Status(fiber.StatusTeapot).Send(data) }) h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/demo") b.ReportAllocs() @@ -853,7 +850,7 @@ func Benchmark_Cache_AdditionalHeaders(b *testing.B) { h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/demo") b.ReportAllocs() @@ -885,7 +882,7 @@ func Benchmark_Cache_MaxSize(b *testing.B) { h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") b.ReportAllocs() b.ResetTimer() diff --git a/middleware/cache/config.go b/middleware/cache/config.go index 9c2d2e104d..12f81e2ae8 100644 --- a/middleware/cache/config.go +++ b/middleware/cache/config.go @@ -1,7 +1,7 @@ package cache import ( - "log" + "fmt" "time" "github.com/gofiber/fiber/v2" @@ -49,10 +49,10 @@ type Config struct { // Default: an in memory store for this process only Storage fiber.Storage - // Deprecated: Use Storage instead + // Deprecated, use Storage instead Store fiber.Storage - // Deprecated: Use KeyGenerator instead + // Deprecated, use KeyGenerator instead Key func(*fiber.Ctx) string // allows you to store additional headers generated by next middlewares & handler @@ -75,8 +75,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, Expiration: 1 * time.Minute, @@ -104,11 +102,11 @@ func configDefault(config ...Config) Config { // Set default values if cfg.Store != nil { - log.Printf("[CACHE] Store is deprecated, please use Storage\n") + fmt.Println("[CACHE] Store is deprecated, please use Storage") cfg.Storage = cfg.Store } if cfg.Key != nil { - log.Printf("[CACHE] Key is deprecated, please use KeyGenerator\n") + fmt.Println("[CACHE] Key is deprecated, please use KeyGenerator") cfg.KeyGenerator = cfg.Key } if cfg.Next == nil { diff --git a/middleware/cache/heap.go b/middleware/cache/heap.go index fcd8356749..70271b84b8 100644 --- a/middleware/cache/heap.go +++ b/middleware/cache/heap.go @@ -41,7 +41,7 @@ func (h indexedHeap) Swap(i, j int) { } func (h *indexedHeap) Push(x interface{}) { - h.pushInternal(x.(heapEntry)) //nolint:forcetypeassert // Forced type assertion required to implement the heap.Interface interface + h.pushInternal(x.(heapEntry)) } func (h *indexedHeap) Pop() interface{} { @@ -65,7 +65,7 @@ func (h *indexedHeap) put(key string, exp uint64, bytes uint) int { idx = h.entries[:n+1][n].idx } else { idx = h.maxidx - h.maxidx++ + h.maxidx += 1 h.indices = append(h.indices, idx) } // Push manually to avoid allocation @@ -77,7 +77,7 @@ func (h *indexedHeap) put(key string, exp uint64, bytes uint) int { } func (h *indexedHeap) removeInternal(realIdx int) (string, uint) { - x := heap.Remove(h, realIdx).(heapEntry) //nolint:forcetypeassert,errcheck // Forced type assertion required to implement the heap.Interface interface + x := heap.Remove(h, realIdx).(heapEntry) return x.key, x.bytes } diff --git a/middleware/cache/manager.go b/middleware/cache/manager.go index 78660072e2..6b9256fd23 100644 --- a/middleware/cache/manager.go +++ b/middleware/cache/manager.go @@ -51,7 +51,7 @@ func newManager(storage fiber.Storage) *manager { // acquire returns an *entry from the sync.Pool func (m *manager) acquire() *item { - return m.pool.Get().(*item) //nolint:forcetypeassert // We store nothing else in the pool + return m.pool.Get().(*item) } // release and reset *entry to sync.Pool @@ -69,47 +69,38 @@ func (m *manager) release(e *item) { } // get data from storage or memory -func (m *manager) get(key string) *item { - var it *item +func (m *manager) get(key string) (it *item) { if m.storage != nil { it = m.acquire() - raw, err := m.storage.Get(key) - if err != nil { - return it - } - if raw != nil { + if raw, _ := m.storage.Get(key); raw != nil { if _, err := it.UnmarshalMsg(raw); err != nil { - return it + return } } - return it + return } - if it, _ = m.memory.Get(key).(*item); it == nil { //nolint:errcheck // We store nothing else in the pool + if it, _ = m.memory.Get(key).(*item); it == nil { it = m.acquire() - return it } - return it + return } // get raw data from storage or memory -func (m *manager) getRaw(key string) []byte { - var raw []byte +func (m *manager) getRaw(key string) (raw []byte) { if m.storage != nil { - raw, _ = m.storage.Get(key) //nolint:errcheck // TODO: Handle error here + raw, _ = m.storage.Get(key) } else { - raw, _ = m.memory.Get(key).([]byte) //nolint:errcheck // TODO: Handle error here + raw, _ = m.memory.Get(key).([]byte) } - return raw + return } // set data to storage or memory func (m *manager) set(key string, it *item, exp time.Duration) { if m.storage != nil { if raw, err := it.MarshalMsg(nil); err == nil { - _ = m.storage.Set(key, raw, exp) //nolint:errcheck // TODO: Handle error here + _ = m.storage.Set(key, raw, exp) } - // we can release data because it's serialized to database - m.release(it) } else { m.memory.Set(key, it, exp) } @@ -118,16 +109,16 @@ func (m *manager) set(key string, it *item, exp time.Duration) { // set data to storage or memory func (m *manager) setRaw(key string, raw []byte, exp time.Duration) { if m.storage != nil { - _ = m.storage.Set(key, raw, exp) //nolint:errcheck // TODO: Handle error here + _ = m.storage.Set(key, raw, exp) } else { m.memory.Set(key, raw, exp) } } // delete data from storage or memory -func (m *manager) del(key string) { +func (m *manager) delete(key string) { if m.storage != nil { - _ = m.storage.Delete(key) //nolint:errcheck // TODO: Handle error here + _ = m.storage.Delete(key) } else { m.memory.Delete(key) } diff --git a/middleware/compress/compress.go b/middleware/compress/compress.go index 626faf4348..e65d78558b 100644 --- a/middleware/compress/compress.go +++ b/middleware/compress/compress.go @@ -2,7 +2,6 @@ package compress import ( "github.com/gofiber/fiber/v2" - "github.com/valyala/fasthttp" ) diff --git a/middleware/compress/compress_test.go b/middleware/compress/compress_test.go index 28dd3f2a2f..371a755976 100644 --- a/middleware/compress/compress_test.go +++ b/middleware/compress/compress_test.go @@ -12,10 +12,8 @@ import ( "github.com/gofiber/fiber/v2/utils" ) -//nolint:gochecknoglobals // Using a global var is fine here var filedata []byte -//nolint:gochecknoinits // init() is used to populate a global var from a README file func init() { dat, err := os.ReadFile("../../.github/README.md") if err != nil { @@ -36,7 +34,7 @@ func Test_Compress_Gzip(t *testing.T) { return c.Send(filedata) }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Accept-Encoding", "gzip") resp, err := app.Test(req) @@ -66,7 +64,7 @@ func Test_Compress_Different_Level(t *testing.T) { return c.Send(filedata) }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Accept-Encoding", "gzip") resp, err := app.Test(req) @@ -92,7 +90,7 @@ func Test_Compress_Deflate(t *testing.T) { return c.Send(filedata) }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Accept-Encoding", "deflate") resp, err := app.Test(req) @@ -116,7 +114,7 @@ func Test_Compress_Brotli(t *testing.T) { return c.Send(filedata) }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Accept-Encoding", "br") resp, err := app.Test(req, 10000) @@ -140,7 +138,7 @@ func Test_Compress_Disabled(t *testing.T) { return c.Send(filedata) }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Accept-Encoding", "br") resp, err := app.Test(req) @@ -164,7 +162,7 @@ func Test_Compress_Next_Error(t *testing.T) { return errors.New("next error") }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Accept-Encoding", "gzip") resp, err := app.Test(req) @@ -187,7 +185,7 @@ func Test_Compress_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } diff --git a/middleware/compress/config.go b/middleware/compress/config.go index fb176c6083..5495ad4c42 100644 --- a/middleware/compress/config.go +++ b/middleware/compress/config.go @@ -33,8 +33,6 @@ const ( ) // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, Level: LevelDefault, diff --git a/middleware/cors/cors.go b/middleware/cors/cors.go index 78dcae2dd3..5640cc3f2d 100644 --- a/middleware/cors/cors.go +++ b/middleware/cors/cors.go @@ -1,6 +1,7 @@ package cors import ( + "net/http" "strconv" "strings" @@ -53,8 +54,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, AllowOrigins: "*", @@ -129,7 +128,7 @@ func New(config ...Config) fiber.Handler { } // Simple request - if c.Method() != fiber.MethodOptions { + if c.Method() != http.MethodOptions { c.Vary(fiber.HeaderOrigin) c.Set(fiber.HeaderAccessControlAllowOrigin, allowOrigin) diff --git a/middleware/cors/cors_test.go b/middleware/cors/cors_test.go index 3600282331..7d42c3c318 100644 --- a/middleware/cors/cors_test.go +++ b/middleware/cors/cors_test.go @@ -6,7 +6,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -238,7 +237,7 @@ func Test_CORS_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } diff --git a/middleware/cors/utils.go b/middleware/cors/utils.go index 8b6114bdab..fee658ef93 100644 --- a/middleware/cors/utils.go +++ b/middleware/cors/utils.go @@ -1,8 +1,6 @@ package cors -import ( - "strings" -) +import "strings" func matchScheme(domain, pattern string) bool { didx := strings.Index(domain, ":") @@ -22,20 +20,18 @@ func matchSubdomain(domain, pattern string) bool { } domAuth := domain[didx+3:] // to avoid long loop by invalid long domain - const maxDomainLen = 253 - if len(domAuth) > maxDomainLen { + if len(domAuth) > 253 { return false } patAuth := pattern[pidx+3:] domComp := strings.Split(domAuth, ".") patComp := strings.Split(patAuth, ".") - const divHalf = 2 - for i := len(domComp)/divHalf - 1; i >= 0; i-- { + for i := len(domComp)/2 - 1; i >= 0; i-- { opp := len(domComp) - 1 - i domComp[i], domComp[opp] = domComp[opp], domComp[i] } - for i := len(patComp)/divHalf - 1; i >= 0; i-- { + for i := len(patComp)/2 - 1; i >= 0; i-- { opp := len(patComp) - 1 - i patComp[i], patComp[opp] = patComp[opp], patComp[i] } diff --git a/middleware/csrf/config.go b/middleware/csrf/config.go index 7482b60a8f..94c5287b65 100644 --- a/middleware/csrf/config.go +++ b/middleware/csrf/config.go @@ -1,7 +1,7 @@ package csrf import ( - "log" + "fmt" "net/textproto" "strings" "time" @@ -80,13 +80,13 @@ type Config struct { // Optional. Default: utils.UUID KeyGenerator func() string - // Deprecated: Please use Expiration + // Deprecated, please use Expiration CookieExpires time.Duration - // Deprecated: Please use Cookie* related fields + // Deprecated, please use Cookie* related fields Cookie *fiber.Cookie - // Deprecated: Please use KeyLookup + // Deprecated, please use KeyLookup TokenLookup string // ErrorHandler is executed when an error is returned from fiber.Handler. @@ -105,8 +105,6 @@ type Config struct { const HeaderName = "X-Csrf-Token" // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ KeyLookup: "header:" + HeaderName, CookieName: "csrf_", @@ -118,7 +116,7 @@ var ConfigDefault = Config{ } // default ErrorHandler that process return error from fiber.Handler -func defaultErrorHandler(_ *fiber.Ctx, _ error) error { +var defaultErrorHandler = func(c *fiber.Ctx, err error) error { return fiber.ErrForbidden } @@ -134,15 +132,15 @@ func configDefault(config ...Config) Config { // Set default values if cfg.TokenLookup != "" { - log.Printf("[CSRF] TokenLookup is deprecated, please use KeyLookup\n") + fmt.Println("[CSRF] TokenLookup is deprecated, please use KeyLookup") cfg.KeyLookup = cfg.TokenLookup } if int(cfg.CookieExpires.Seconds()) > 0 { - log.Printf("[CSRF] CookieExpires is deprecated, please use Expiration\n") + fmt.Println("[CSRF] CookieExpires is deprecated, please use Expiration") cfg.Expiration = cfg.CookieExpires } if cfg.Cookie != nil { - log.Printf("[CSRF] Cookie is deprecated, please use Cookie* related fields\n") + fmt.Println("[CSRF] Cookie is deprecated, please use Cookie* related fields") if cfg.Cookie.Name != "" { cfg.CookieName = cfg.Cookie.Name } @@ -180,8 +178,7 @@ func configDefault(config ...Config) Config { // Generate the correct extractor to get the token from the correct location selectors := strings.Split(cfg.KeyLookup, ":") - const numParts = 2 - if len(selectors) != numParts { + if len(selectors) != 2 { panic("[CSRF] KeyLookup must in the form of :") } diff --git a/middleware/csrf/csrf.go b/middleware/csrf/csrf.go index 22123441d1..e7ad4f2a72 100644 --- a/middleware/csrf/csrf.go +++ b/middleware/csrf/csrf.go @@ -7,7 +7,9 @@ import ( "github.com/gofiber/fiber/v2" ) -var errTokenNotFound = errors.New("csrf token not found") +var ( + errTokenNotFound = errors.New("csrf token not found") +) // New creates a new middleware handler func New(config ...Config) fiber.Handler { @@ -20,7 +22,7 @@ func New(config ...Config) fiber.Handler { dummyValue := []byte{'+'} // Return new handler - return func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) (err error) { // Don't execute middleware if Next returns true if cfg.Next != nil && cfg.Next(c) { return c.Next() @@ -37,7 +39,7 @@ func New(config ...Config) fiber.Handler { // Assume that anything not defined as 'safe' by RFC7231 needs protection // Extract token from client request i.e. header, query, param, form or cookie - token, err := cfg.Extractor(c) + token, err = cfg.Extractor(c) if err != nil { return cfg.ErrorHandler(c, err) } diff --git a/middleware/csrf/csrf_test.go b/middleware/csrf/csrf_test.go index 446ae2f72d..ffa6af3e9f 100644 --- a/middleware/csrf/csrf_test.go +++ b/middleware/csrf/csrf_test.go @@ -7,7 +7,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -24,7 +23,7 @@ func Test_CSRF(t *testing.T) { h := app.Handler() ctx := &fasthttp.RequestCtx{} - methods := [4]string{fiber.MethodGet, fiber.MethodHead, fiber.MethodOptions, fiber.MethodTrace} + methods := [4]string{"GET", "HEAD", "OPTIONS", "TRACE"} for _, method := range methods { // Generate CSRF token @@ -34,14 +33,14 @@ func Test_CSRF(t *testing.T) { // Without CSRF cookie ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") h(ctx) utils.AssertEqual(t, 403, ctx.Response.StatusCode()) // Empty/invalid CSRF token ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(HeaderName, "johndoe") h(ctx) utils.AssertEqual(t, 403, ctx.Response.StatusCode()) @@ -56,7 +55,7 @@ func Test_CSRF(t *testing.T) { ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(HeaderName, token) h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) @@ -73,7 +72,7 @@ func Test_CSRF_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -93,7 +92,7 @@ func Test_CSRF_Invalid_KeyLookup(t *testing.T) { h := app.Handler() ctx := &fasthttp.RequestCtx{} - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") h(ctx) } @@ -111,7 +110,7 @@ func Test_CSRF_From_Form(t *testing.T) { ctx := &fasthttp.RequestCtx{} // Invalid CSRF token - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(fiber.HeaderContentType, fiber.MIMEApplicationForm) h(ctx) utils.AssertEqual(t, 403, ctx.Response.StatusCode()) @@ -119,12 +118,12 @@ func Test_CSRF_From_Form(t *testing.T) { // Generate CSRF token ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") h(ctx) token := string(ctx.Response.Header.Peek(fiber.HeaderSetCookie)) token = strings.Split(strings.Split(token, ";")[0], "=")[1] - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(fiber.HeaderContentType, fiber.MIMEApplicationForm) ctx.Request.SetBodyString("_csrf=" + token) h(ctx) @@ -145,7 +144,7 @@ func Test_CSRF_From_Query(t *testing.T) { ctx := &fasthttp.RequestCtx{} // Invalid CSRF token - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.SetRequestURI("/?_csrf=" + utils.UUID()) h(ctx) utils.AssertEqual(t, 403, ctx.Response.StatusCode()) @@ -153,7 +152,7 @@ func Test_CSRF_From_Query(t *testing.T) { // Generate CSRF token ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") ctx.Request.SetRequestURI("/") h(ctx) token := string(ctx.Response.Header.Peek(fiber.HeaderSetCookie)) @@ -162,7 +161,7 @@ func Test_CSRF_From_Query(t *testing.T) { ctx.Request.Reset() ctx.Response.Reset() ctx.Request.SetRequestURI("/?_csrf=" + token) - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) utils.AssertEqual(t, "OK", string(ctx.Response.Body())) @@ -182,7 +181,7 @@ func Test_CSRF_From_Param(t *testing.T) { ctx := &fasthttp.RequestCtx{} // Invalid CSRF token - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.SetRequestURI("/" + utils.UUID()) h(ctx) utils.AssertEqual(t, 403, ctx.Response.StatusCode()) @@ -190,7 +189,7 @@ func Test_CSRF_From_Param(t *testing.T) { // Generate CSRF token ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") ctx.Request.SetRequestURI("/" + utils.UUID()) h(ctx) token := string(ctx.Response.Header.Peek(fiber.HeaderSetCookie)) @@ -199,7 +198,7 @@ func Test_CSRF_From_Param(t *testing.T) { ctx.Request.Reset() ctx.Response.Reset() ctx.Request.SetRequestURI("/" + token) - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) utils.AssertEqual(t, "OK", string(ctx.Response.Body())) @@ -219,7 +218,7 @@ func Test_CSRF_From_Cookie(t *testing.T) { ctx := &fasthttp.RequestCtx{} // Invalid CSRF token - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.SetRequestURI("/") ctx.Request.Header.Set(fiber.HeaderCookie, "csrf="+utils.UUID()+";") h(ctx) @@ -228,7 +227,7 @@ func Test_CSRF_From_Cookie(t *testing.T) { // Generate CSRF token ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") ctx.Request.SetRequestURI("/") h(ctx) token := string(ctx.Response.Header.Peek(fiber.HeaderSetCookie)) @@ -236,7 +235,7 @@ func Test_CSRF_From_Cookie(t *testing.T) { ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(fiber.HeaderCookie, "csrf="+token+";") ctx.Request.SetRequestURI("/") h(ctx) @@ -269,7 +268,7 @@ func Test_CSRF_From_Custom(t *testing.T) { ctx := &fasthttp.RequestCtx{} // Invalid CSRF token - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(fiber.HeaderContentType, fiber.MIMETextPlain) h(ctx) utils.AssertEqual(t, 403, ctx.Response.StatusCode()) @@ -277,12 +276,12 @@ func Test_CSRF_From_Custom(t *testing.T) { // Generate CSRF token ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") h(ctx) token := string(ctx.Response.Header.Peek(fiber.HeaderSetCookie)) token = strings.Split(strings.Split(token, ";")[0], "=")[1] - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(fiber.HeaderContentType, fiber.MIMETextPlain) ctx.Request.SetBodyString("_csrf=" + token) h(ctx) @@ -308,13 +307,13 @@ func Test_CSRF_ErrorHandler_InvalidToken(t *testing.T) { ctx := &fasthttp.RequestCtx{} // Generate CSRF token - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") h(ctx) // invalid CSRF token ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(HeaderName, "johndoe") h(ctx) utils.AssertEqual(t, 419, ctx.Response.StatusCode()) @@ -340,69 +339,69 @@ func Test_CSRF_ErrorHandler_EmptyToken(t *testing.T) { ctx := &fasthttp.RequestCtx{} // Generate CSRF token - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") h(ctx) // empty CSRF token ctx.Request.Reset() ctx.Response.Reset() - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") h(ctx) utils.AssertEqual(t, 419, ctx.Response.StatusCode()) utils.AssertEqual(t, "empty CSRF token", string(ctx.Response.Body())) } // TODO: use this test case and make the unsafe header value bug from https://github.com/gofiber/fiber/issues/2045 reproducible and permanently fixed/tested by this testcase -// func Test_CSRF_UnsafeHeaderValue(t *testing.T) { +//func Test_CSRF_UnsafeHeaderValue(t *testing.T) { // t.Parallel() -// app := fiber.New() - -// app.Use(New()) -// app.Get("/", func(c *fiber.Ctx) error { -// return c.SendStatus(fiber.StatusOK) -// }) -// app.Get("/test", func(c *fiber.Ctx) error { -// return c.SendStatus(fiber.StatusOK) -// }) -// app.Post("/", func(c *fiber.Ctx) error { -// return c.SendStatus(fiber.StatusOK) -// }) - -// resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) -// utils.AssertEqual(t, nil, err) -// utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) - -// var token string -// for _, c := range resp.Cookies() { -// if c.Name != ConfigDefault.CookieName { -// continue -// } -// token = c.Value -// break -// } - -// fmt.Println("token", token) - -// getReq := httptest.NewRequest(fiber.MethodGet, "/", nil) -// getReq.Header.Set(HeaderName, token) -// resp, err = app.Test(getReq) - -// getReq = httptest.NewRequest(fiber.MethodGet, "/test", nil) -// getReq.Header.Set("X-Requested-With", "XMLHttpRequest") -// getReq.Header.Set(fiber.HeaderCacheControl, "no") -// getReq.Header.Set(HeaderName, token) - -// resp, err = app.Test(getReq) - -// getReq.Header.Set(fiber.HeaderAccept, "*/*") -// getReq.Header.Del(HeaderName) -// resp, err = app.Test(getReq) - -// postReq := httptest.NewRequest(fiber.MethodPost, "/", nil) -// postReq.Header.Set("X-Requested-With", "XMLHttpRequest") -// postReq.Header.Set(HeaderName, token) -// resp, err = app.Test(postReq) -// } +// app := fiber.New() +// +// app.Use(New()) +// app.Get("/", func(c *fiber.Ctx) error { +// return c.SendStatus(fiber.StatusOK) +// }) +// app.Get("/test", func(c *fiber.Ctx) error { +// return c.SendStatus(fiber.StatusOK) +// }) +// app.Post("/", func(c *fiber.Ctx) error { +// return c.SendStatus(fiber.StatusOK) +// }) +// +// resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/", nil)) +// utils.AssertEqual(t, nil, err) +// utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) +// +// var token string +// for _, c := range resp.Cookies() { +// if c.Name != ConfigDefault.CookieName { +// continue +// } +// token = c.Value +// break +// } +// +// fmt.Println("token", token) +// +// getReq := httptest.NewRequest(http.MethodGet, "/", nil) +// getReq.Header.Set(HeaderName, token) +// resp, err = app.Test(getReq) +// +// getReq = httptest.NewRequest(http.MethodGet, "/test", nil) +// getReq.Header.Set("X-Requested-With", "XMLHttpRequest") +// getReq.Header.Set(fiber.HeaderCacheControl, "no") +// getReq.Header.Set(HeaderName, token) +// +// resp, err = app.Test(getReq) +// +// getReq.Header.Set(fiber.HeaderAccept, "*/*") +// getReq.Header.Del(HeaderName) +// resp, err = app.Test(getReq) +// +// postReq := httptest.NewRequest(http.MethodPost, "/", nil) +// postReq.Header.Set("X-Requested-With", "XMLHttpRequest") +// postReq.Header.Set(HeaderName, token) +// resp, err = app.Test(postReq) +//} // go test -v -run=^$ -bench=Benchmark_Middleware_CSRF_Check -benchmem -count=4 func Benchmark_Middleware_CSRF_Check(b *testing.B) { @@ -418,12 +417,12 @@ func Benchmark_Middleware_CSRF_Check(b *testing.B) { ctx := &fasthttp.RequestCtx{} // Generate CSRF token - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") h(ctx) token := string(ctx.Response.Header.Peek(fiber.HeaderSetCookie)) token = strings.Split(strings.Split(token, ";")[0], "=")[1] - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") ctx.Request.Header.Set(HeaderName, token) b.ReportAllocs() @@ -450,7 +449,7 @@ func Benchmark_Middleware_CSRF_GenerateToken(b *testing.B) { ctx := &fasthttp.RequestCtx{} // Generate CSRF token - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") b.ReportAllocs() b.ResetTimer() diff --git a/middleware/csrf/manager.go b/middleware/csrf/manager.go index a16f3a213a..13f0ccb657 100644 --- a/middleware/csrf/manager.go +++ b/middleware/csrf/manager.go @@ -41,23 +41,74 @@ func newManager(storage fiber.Storage) *manager { return manager } +// acquire returns an *entry from the sync.Pool +func (m *manager) acquire() *item { + return m.pool.Get().(*item) +} + +// release and reset *entry to sync.Pool +func (m *manager) release(e *item) { + // don't release item if we using memory storage + if m.storage != nil { + return + } + m.pool.Put(e) +} + +// get data from storage or memory +func (m *manager) get(key string) (it *item) { + if m.storage != nil { + it = m.acquire() + if raw, _ := m.storage.Get(key); raw != nil { + if _, err := it.UnmarshalMsg(raw); err != nil { + return + } + } + return + } + if it, _ = m.memory.Get(key).(*item); it == nil { + it = m.acquire() + } + return +} + // get raw data from storage or memory -func (m *manager) getRaw(key string) []byte { - var raw []byte +func (m *manager) getRaw(key string) (raw []byte) { if m.storage != nil { - raw, _ = m.storage.Get(key) //nolint:errcheck // TODO: Do not ignore error + raw, _ = m.storage.Get(key) } else { - raw, _ = m.memory.Get(key).([]byte) //nolint:errcheck // TODO: Do not ignore error + raw, _ = m.memory.Get(key).([]byte) + } + return +} + +// set data to storage or memory +func (m *manager) set(key string, it *item, exp time.Duration) { + if m.storage != nil { + if raw, err := it.MarshalMsg(nil); err == nil { + _ = m.storage.Set(key, raw, exp) + } + } else { + // the key is crucial in crsf and sometimes a reference to another value which can be reused later(pool/unsafe values concept), so a copy is made here + m.memory.Set(utils.CopyString(key), it, exp) } - return raw } // set data to storage or memory func (m *manager) setRaw(key string, raw []byte, exp time.Duration) { if m.storage != nil { - _ = m.storage.Set(key, raw, exp) //nolint:errcheck // TODO: Do not ignore error + _ = m.storage.Set(key, raw, exp) } else { // the key is crucial in crsf and sometimes a reference to another value which can be reused later(pool/unsafe values concept), so a copy is made here m.memory.Set(utils.CopyString(key), raw, exp) } } + +// delete data from storage or memory +func (m *manager) delete(key string) { + if m.storage != nil { + _ = m.storage.Delete(key) + } else { + m.memory.Delete(key) + } +} diff --git a/middleware/encryptcookie/config.go b/middleware/encryptcookie/config.go index d8e4ba21da..735c2f2d28 100644 --- a/middleware/encryptcookie/config.go +++ b/middleware/encryptcookie/config.go @@ -1,8 +1,6 @@ package encryptcookie -import ( - "github.com/gofiber/fiber/v2" -) +import "github.com/gofiber/fiber/v2" // Config defines the config for middleware. type Config struct { @@ -34,8 +32,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, Except: []string{"csrf_"}, diff --git a/middleware/encryptcookie/encryptcookie.go b/middleware/encryptcookie/encryptcookie.go index 9e323ce0e1..1ba4779f56 100644 --- a/middleware/encryptcookie/encryptcookie.go +++ b/middleware/encryptcookie/encryptcookie.go @@ -2,7 +2,6 @@ package encryptcookie import ( "github.com/gofiber/fiber/v2" - "github.com/valyala/fasthttp" ) diff --git a/middleware/encryptcookie/encryptcookie_test.go b/middleware/encryptcookie/encryptcookie_test.go index aed45d6903..8241d6133c 100644 --- a/middleware/encryptcookie/encryptcookie_test.go +++ b/middleware/encryptcookie/encryptcookie_test.go @@ -7,11 +7,9 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) -//nolint:gochecknoglobals // Using a global var is fine here var testKey = GenerateKey() func Test_Middleware_Encrypt_Cookie(t *testing.T) { @@ -37,14 +35,14 @@ func Test_Middleware_Encrypt_Cookie(t *testing.T) { // Test empty cookie ctx := &fasthttp.RequestCtx{} - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) utils.AssertEqual(t, "value=", string(ctx.Response.Body())) // Test invalid cookie ctx = &fasthttp.RequestCtx{} - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") ctx.Request.Header.SetCookie("test", "Invalid") h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) @@ -56,19 +54,18 @@ func Test_Middleware_Encrypt_Cookie(t *testing.T) { // Test valid cookie ctx = &fasthttp.RequestCtx{} - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) encryptedCookie := fasthttp.Cookie{} encryptedCookie.SetKey("test") utils.AssertEqual(t, true, ctx.Response.Header.Cookie(&encryptedCookie), "Get cookie value") - decryptedCookieValue, err := DecryptCookie(string(encryptedCookie.Value()), testKey) - utils.AssertEqual(t, nil, err) + decryptedCookieValue, _ := DecryptCookie(string(encryptedCookie.Value()), testKey) utils.AssertEqual(t, "SomeThing", decryptedCookieValue) ctx = &fasthttp.RequestCtx{} - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") ctx.Request.Header.SetCookie("test", string(encryptedCookie.Value())) h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) @@ -94,7 +91,7 @@ func Test_Encrypt_Cookie_Next(t *testing.T) { return nil }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "SomeThing", resp.Cookies()[0].Value) } @@ -126,7 +123,7 @@ func Test_Encrypt_Cookie_Except(t *testing.T) { h := app.Handler() ctx := &fasthttp.RequestCtx{} - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) @@ -138,8 +135,7 @@ func Test_Encrypt_Cookie_Except(t *testing.T) { encryptedCookie := fasthttp.Cookie{} encryptedCookie.SetKey("test2") utils.AssertEqual(t, true, ctx.Response.Header.Cookie(&encryptedCookie), "Get cookie value") - decryptedCookieValue, err := DecryptCookie(string(encryptedCookie.Value()), testKey) - utils.AssertEqual(t, nil, err) + decryptedCookieValue, _ := DecryptCookie(string(encryptedCookie.Value()), testKey) utils.AssertEqual(t, "SomeThing", decryptedCookieValue) } @@ -173,19 +169,18 @@ func Test_Encrypt_Cookie_Custom_Encryptor(t *testing.T) { h := app.Handler() ctx := &fasthttp.RequestCtx{} - ctx.Request.Header.SetMethod(fiber.MethodPost) + ctx.Request.Header.SetMethod("POST") h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) encryptedCookie := fasthttp.Cookie{} encryptedCookie.SetKey("test") utils.AssertEqual(t, true, ctx.Response.Header.Cookie(&encryptedCookie), "Get cookie value") - decodedBytes, err := base64.StdEncoding.DecodeString(string(encryptedCookie.Value())) - utils.AssertEqual(t, nil, err) + decodedBytes, _ := base64.StdEncoding.DecodeString(string(encryptedCookie.Value())) utils.AssertEqual(t, "SomeThing", string(decodedBytes)) ctx = &fasthttp.RequestCtx{} - ctx.Request.Header.SetMethod(fiber.MethodGet) + ctx.Request.Header.SetMethod("GET") ctx.Request.Header.SetCookie("test", string(encryptedCookie.Value())) h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) diff --git a/middleware/encryptcookie/utils.go b/middleware/encryptcookie/utils.go index c35064d954..542d160c17 100644 --- a/middleware/encryptcookie/utils.go +++ b/middleware/encryptcookie/utils.go @@ -6,56 +6,47 @@ import ( "crypto/rand" "encoding/base64" "errors" - "fmt" "io" ) // EncryptCookie Encrypts a cookie value with specific encryption key func EncryptCookie(value, key string) (string, error) { - keyDecoded, err := base64.StdEncoding.DecodeString(key) - if err != nil { - return "", fmt.Errorf("failed to base64-decode key: %w", err) - } + keyDecoded, _ := base64.StdEncoding.DecodeString(key) + plaintext := []byte(value) block, err := aes.NewCipher(keyDecoded) if err != nil { - return "", fmt.Errorf("failed to create AES cipher: %w", err) + return "", err } gcm, err := cipher.NewGCM(block) if err != nil { - return "", fmt.Errorf("failed to create GCM mode: %w", err) + return "", err } nonce := make([]byte, gcm.NonceSize()) if _, err = io.ReadFull(rand.Reader, nonce); err != nil { - return "", fmt.Errorf("failed to read: %w", err) + return "", err } - ciphertext := gcm.Seal(nonce, nonce, []byte(value), nil) + ciphertext := gcm.Seal(nonce, nonce, plaintext, nil) return base64.StdEncoding.EncodeToString(ciphertext), nil } // DecryptCookie Decrypts a cookie value with specific encryption key func DecryptCookie(value, key string) (string, error) { - keyDecoded, err := base64.StdEncoding.DecodeString(key) - if err != nil { - return "", fmt.Errorf("failed to base64-decode key: %w", err) - } - enc, err := base64.StdEncoding.DecodeString(value) - if err != nil { - return "", fmt.Errorf("failed to base64-decode value: %w", err) - } + keyDecoded, _ := base64.StdEncoding.DecodeString(key) + enc, _ := base64.StdEncoding.DecodeString(value) block, err := aes.NewCipher(keyDecoded) if err != nil { - return "", fmt.Errorf("failed to create AES cipher: %w", err) + return "", err } gcm, err := cipher.NewGCM(block) if err != nil { - return "", fmt.Errorf("failed to create GCM mode: %w", err) + return "", err } nonceSize := gcm.NonceSize() @@ -68,7 +59,7 @@ func DecryptCookie(value, key string) (string, error) { plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) if err != nil { - return "", fmt.Errorf("failed to decrypt ciphertext: %w", err) + return "", err } return string(plaintext), nil @@ -76,8 +67,7 @@ func DecryptCookie(value, key string) (string, error) { // GenerateKey Generates an encryption key func GenerateKey() string { - const keyLen = 32 - ret := make([]byte, keyLen) + ret := make([]byte, 32) if _, err := rand.Read(ret); err != nil { panic(err) diff --git a/middleware/envvar/envvar.go b/middleware/envvar/envvar.go index debfc1bbb5..c8ed80de3d 100644 --- a/middleware/envvar/envvar.go +++ b/middleware/envvar/envvar.go @@ -23,8 +23,10 @@ func (envVar *EnvVar) set(key, val string) { envVar.Vars[key] = val } +var defaultConfig = Config{} + func New(config ...Config) fiber.Handler { - var cfg Config + var cfg = defaultConfig if len(config) > 0 { cfg = config[0] } @@ -55,9 +57,8 @@ func newEnvVar(cfg Config) *EnvVar { } } } else { - const numElems = 2 for _, envVal := range os.Environ() { - keyVal := strings.SplitN(envVal, "=", numElems) + keyVal := strings.SplitN(envVal, "=", 2) if _, exists := cfg.ExcludeVars[keyVal[0]]; !exists { vars.set(keyVal[0], keyVal[1]) } diff --git a/middleware/envvar/envvar_test.go b/middleware/envvar/envvar_test.go index 83101a4761..34d8a05074 100644 --- a/middleware/envvar/envvar_test.go +++ b/middleware/envvar/envvar_test.go @@ -1,8 +1,6 @@ -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package envvar import ( - "context" "encoding/json" "io" "net/http" @@ -14,25 +12,16 @@ import ( ) func TestEnvVarStructWithExportVarsExcludeVars(t *testing.T) { - err := os.Setenv("testKey", "testEnvValue") - utils.AssertEqual(t, nil, err) - err = os.Setenv("anotherEnvKey", "anotherEnvVal") - utils.AssertEqual(t, nil, err) - err = os.Setenv("excludeKey", "excludeEnvValue") - utils.AssertEqual(t, nil, err) - defer func() { - err := os.Unsetenv("testKey") - utils.AssertEqual(t, nil, err) - err = os.Unsetenv("anotherEnvKey") - utils.AssertEqual(t, nil, err) - err = os.Unsetenv("excludeKey") - utils.AssertEqual(t, nil, err) - }() + os.Setenv("testKey", "testEnvValue") + os.Setenv("anotherEnvKey", "anotherEnvVal") + os.Setenv("excludeKey", "excludeEnvValue") + defer os.Unsetenv("testKey") + defer os.Unsetenv("anotherEnvKey") + defer os.Unsetenv("excludeKey") vars := newEnvVar(Config{ ExportVars: map[string]string{"testKey": "", "testDefaultKey": "testDefaultVal"}, - ExcludeVars: map[string]string{"excludeKey": ""}, - }) + ExcludeVars: map[string]string{"excludeKey": ""}}) utils.AssertEqual(t, vars.Vars["testKey"], "testEnvValue") utils.AssertEqual(t, vars.Vars["testDefaultKey"], "testDefaultVal") @@ -41,28 +30,21 @@ func TestEnvVarStructWithExportVarsExcludeVars(t *testing.T) { } func TestEnvVarHandler(t *testing.T) { - err := os.Setenv("testKey", "testVal") - utils.AssertEqual(t, nil, err) - defer func() { - err := os.Unsetenv("testKey") - utils.AssertEqual(t, nil, err) - }() + os.Setenv("testKey", "testVal") + defer os.Unsetenv("testKey") - expectedEnvVarResponse, err := json.Marshal( + expectedEnvVarResponse, _ := json.Marshal( struct { Vars map[string]string `json:"vars"` }{ map[string]string{"testKey": "testVal"}, }) - utils.AssertEqual(t, nil, err) app := fiber.New() app.Use("/envvars", New(Config{ - ExportVars: map[string]string{"testKey": ""}, - })) + ExportVars: map[string]string{"testKey": ""}})) - req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "http://localhost/envvars", nil) - utils.AssertEqual(t, nil, err) + req, _ := http.NewRequest("GET", "http://localhost/envvars", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) @@ -75,16 +57,14 @@ func TestEnvVarHandler(t *testing.T) { func TestEnvVarHandlerNotMatched(t *testing.T) { app := fiber.New() app.Use("/envvars", New(Config{ - ExportVars: map[string]string{"testKey": ""}, - })) + ExportVars: map[string]string{"testKey": ""}})) app.Get("/another-path", func(ctx *fiber.Ctx) error { utils.AssertEqual(t, nil, ctx.SendString("OK")) return nil }) - req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "http://localhost/another-path", nil) - utils.AssertEqual(t, nil, err) + req, _ := http.NewRequest("GET", "http://localhost/another-path", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) @@ -95,18 +75,13 @@ func TestEnvVarHandlerNotMatched(t *testing.T) { } func TestEnvVarHandlerDefaultConfig(t *testing.T) { - err := os.Setenv("testEnvKey", "testEnvVal") - utils.AssertEqual(t, nil, err) - defer func() { - err := os.Unsetenv("testEnvKey") - utils.AssertEqual(t, nil, err) - }() + os.Setenv("testEnvKey", "testEnvVal") + defer os.Unsetenv("testEnvKey") app := fiber.New() app.Use("/envvars", New()) - req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "http://localhost/envvars", nil) - utils.AssertEqual(t, nil, err) + req, _ := http.NewRequest("GET", "http://localhost/envvars", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) @@ -123,8 +98,7 @@ func TestEnvVarHandlerMethod(t *testing.T) { app := fiber.New() app.Use("/envvars", New()) - req, err := http.NewRequestWithContext(context.Background(), fiber.MethodPost, "http://localhost/envvars", nil) - utils.AssertEqual(t, nil, err) + req, _ := http.NewRequest("POST", "http://localhost/envvars", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusMethodNotAllowed, resp.StatusCode) @@ -133,19 +107,14 @@ func TestEnvVarHandlerMethod(t *testing.T) { func TestEnvVarHandlerSpecialValue(t *testing.T) { testEnvKey := "testEnvKey" fakeBase64 := "testBase64:TQ==" - err := os.Setenv(testEnvKey, fakeBase64) - utils.AssertEqual(t, nil, err) - defer func() { - err := os.Unsetenv(testEnvKey) - utils.AssertEqual(t, nil, err) - }() + os.Setenv(testEnvKey, fakeBase64) + defer os.Unsetenv(testEnvKey) app := fiber.New() app.Use("/envvars", New()) app.Use("/envvars/export", New(Config{ExportVars: map[string]string{testEnvKey: ""}})) - req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "http://localhost/envvars", nil) - utils.AssertEqual(t, nil, err) + req, _ := http.NewRequest("GET", "http://localhost/envvars", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) @@ -157,8 +126,7 @@ func TestEnvVarHandlerSpecialValue(t *testing.T) { val := envVars.Vars[testEnvKey] utils.AssertEqual(t, fakeBase64, val) - req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "http://localhost/envvars/export", nil) - utils.AssertEqual(t, nil, err) + req, _ = http.NewRequest("GET", "http://localhost/envvars/export", nil) resp, err = app.Test(req) utils.AssertEqual(t, nil, err) diff --git a/middleware/etag/config.go b/middleware/etag/config.go index efc31d86c5..57a7c787ab 100644 --- a/middleware/etag/config.go +++ b/middleware/etag/config.go @@ -23,8 +23,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Weak: false, Next: nil, diff --git a/middleware/etag/etag.go b/middleware/etag/etag.go index 98955833f8..72ad71ba36 100644 --- a/middleware/etag/etag.go +++ b/middleware/etag/etag.go @@ -5,47 +5,45 @@ import ( "hash/crc32" "github.com/gofiber/fiber/v2" - "github.com/valyala/bytebufferpool" ) +var ( + normalizedHeaderETag = []byte("Etag") + weakPrefix = []byte("W/") +) + // New creates a new middleware handler func New(config ...Config) fiber.Handler { // Set default config cfg := configDefault(config...) - var ( - normalizedHeaderETag = []byte("Etag") - weakPrefix = []byte("W/") - ) - - const crcPol = 0xD5828281 - crc32q := crc32.MakeTable(crcPol) + crc32q := crc32.MakeTable(0xD5828281) // Return new handler - return func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) (err error) { // Don't execute middleware if Next returns true if cfg.Next != nil && cfg.Next(c) { return c.Next() } // Return err if next handler returns one - if err := c.Next(); err != nil { - return err + if err = c.Next(); err != nil { + return } // Don't generate ETags for invalid responses if c.Response().StatusCode() != fiber.StatusOK { - return nil + return } body := c.Response().Body() // Skips ETag if no response body is present if len(body) == 0 { - return nil + return } // Skip ETag if header is already present if c.Response().Header.PeekBytes(normalizedHeaderETag) != nil { - return nil + return } // Generate ETag for response @@ -54,14 +52,14 @@ func New(config ...Config) fiber.Handler { // Enable weak tag if cfg.Weak { - _, _ = bb.Write(weakPrefix) //nolint:errcheck // This will never fail + _, _ = bb.Write(weakPrefix) } - _ = bb.WriteByte('"') //nolint:errcheck // This will never fail + _ = bb.WriteByte('"') bb.B = appendUint(bb.Bytes(), uint32(len(body))) - _ = bb.WriteByte('-') //nolint:errcheck // This will never fail + _ = bb.WriteByte('-') bb.B = appendUint(bb.Bytes(), crc32.Checksum(body, crc32q)) - _ = bb.WriteByte('"') //nolint:errcheck // This will never fail + _ = bb.WriteByte('"') etag := bb.Bytes() @@ -80,7 +78,7 @@ func New(config ...Config) fiber.Handler { // W/1 != W/2 || W/1 != 2 c.Response().Header.SetCanonical(normalizedHeaderETag, etag) - return nil + return } if bytes.Contains(clientEtag, etag) { @@ -92,7 +90,7 @@ func New(config ...Config) fiber.Handler { // 1 != 2 c.Response().Header.SetCanonical(normalizedHeaderETag, etag) - return nil + return } } @@ -104,7 +102,7 @@ func appendUint(dst []byte, n uint32) []byte { var q uint32 for n >= 10 { i-- - q = n / 10 //nolint:gomnd // TODO: Explain why we divide by 10 here + q = n / 10 buf[i] = '0' + byte(n-q*10) n = q } diff --git a/middleware/etag/etag_test.go b/middleware/etag/etag_test.go index ff9833f812..567e1e2e94 100644 --- a/middleware/etag/etag_test.go +++ b/middleware/etag/etag_test.go @@ -8,7 +8,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -22,7 +21,7 @@ func Test_ETag_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -38,7 +37,7 @@ func Test_ETag_SkipError(t *testing.T) { return fiber.ErrForbidden }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusForbidden, resp.StatusCode) } @@ -54,7 +53,7 @@ func Test_ETag_NotStatusOK(t *testing.T) { return c.SendStatus(fiber.StatusCreated) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusCreated, resp.StatusCode) } @@ -70,7 +69,7 @@ func Test_ETag_NoBody(t *testing.T) { return nil }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) } @@ -92,7 +91,7 @@ func Test_ETag_NewEtag(t *testing.T) { }) } -func testETagNewEtag(t *testing.T, headerIfNoneMatch, matched bool) { //nolint:revive // We're in a test, so using bools as a flow-control is fine +func testETagNewEtag(t *testing.T, headerIfNoneMatch, matched bool) { t.Helper() app := fiber.New() @@ -103,7 +102,7 @@ func testETagNewEtag(t *testing.T, headerIfNoneMatch, matched bool) { //nolint:r return c.SendString("Hello, World!") }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) if headerIfNoneMatch { etag := `"non-match"` if matched { @@ -146,7 +145,7 @@ func Test_ETag_WeakEtag(t *testing.T) { }) } -func testETagWeakEtag(t *testing.T, headerIfNoneMatch, matched bool) { //nolint:revive // We're in a test, so using bools as a flow-control is fine +func testETagWeakEtag(t *testing.T, headerIfNoneMatch, matched bool) { t.Helper() app := fiber.New() @@ -157,7 +156,7 @@ func testETagWeakEtag(t *testing.T, headerIfNoneMatch, matched bool) { //nolint: return c.SendString("Hello, World!") }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) if headerIfNoneMatch { etag := `W/"non-match"` if matched { @@ -200,7 +199,7 @@ func Test_ETag_CustomEtag(t *testing.T) { }) } -func testETagCustomEtag(t *testing.T, headerIfNoneMatch, matched bool) { //nolint:revive // We're in a test, so using bools as a flow-control is fine +func testETagCustomEtag(t *testing.T, headerIfNoneMatch, matched bool) { t.Helper() app := fiber.New() @@ -215,7 +214,7 @@ func testETagCustomEtag(t *testing.T, headerIfNoneMatch, matched bool) { //nolin return c.SendString("Hello, World!") }) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) if headerIfNoneMatch { etag := `"non-match"` if matched { @@ -256,7 +255,7 @@ func Test_ETag_CustomEtagPut(t *testing.T) { return c.SendString("Hello, World!") }) - req := httptest.NewRequest(fiber.MethodPut, "/", nil) + req := httptest.NewRequest("PUT", "/", nil) req.Header.Set(fiber.HeaderIfMatch, `"non-match"`) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) @@ -276,7 +275,7 @@ func Benchmark_Etag(b *testing.B) { h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/") b.ReportAllocs() diff --git a/middleware/expvar/config.go b/middleware/expvar/config.go index c31cebcf3d..6691dc1a3a 100644 --- a/middleware/expvar/config.go +++ b/middleware/expvar/config.go @@ -1,8 +1,6 @@ package expvar -import ( - "github.com/gofiber/fiber/v2" -) +import "github.com/gofiber/fiber/v2" // Config defines the config for middleware. type Config struct { @@ -12,7 +10,6 @@ type Config struct { Next func(c *fiber.Ctx) bool } -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, } diff --git a/middleware/expvar/expvar.go b/middleware/expvar/expvar.go index 6436395914..7576401781 100644 --- a/middleware/expvar/expvar.go +++ b/middleware/expvar/expvar.go @@ -4,7 +4,6 @@ import ( "strings" "github.com/gofiber/fiber/v2" - "github.com/valyala/fasthttp/expvarhandler" ) @@ -30,6 +29,6 @@ func New(config ...Config) fiber.Handler { return nil } - return c.Redirect("/debug/vars", fiber.StatusFound) + return c.Redirect("/debug/vars", 302) } } diff --git a/middleware/favicon/favicon.go b/middleware/favicon/favicon.go index e7ef5d4dbb..66b688093c 100644 --- a/middleware/favicon/favicon.go +++ b/middleware/favicon/favicon.go @@ -34,8 +34,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, File: "", diff --git a/middleware/favicon/favicon_test.go b/middleware/favicon/favicon_test.go index 8597b7ec47..f53311e3ae 100644 --- a/middleware/favicon/favicon_test.go +++ b/middleware/favicon/favicon_test.go @@ -1,18 +1,16 @@ -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package favicon import ( - "fmt" "net/http" "net/http/httptest" "os" "strings" "testing" + "github.com/valyala/fasthttp" + "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - - "github.com/valyala/fasthttp" ) // go test -run Test_Middleware_Favicon @@ -27,22 +25,22 @@ func Test_Middleware_Favicon(t *testing.T) { }) // Skip Favicon middleware - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode, "Status code") - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/favicon.ico", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/favicon.ico", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusNoContent, resp.StatusCode, "Status code") - resp, err = app.Test(httptest.NewRequest(fiber.MethodOptions, "/favicon.ico", nil)) + resp, err = app.Test(httptest.NewRequest("OPTIONS", "/favicon.ico", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode, "Status code") - resp, err = app.Test(httptest.NewRequest(fiber.MethodPut, "/favicon.ico", nil)) + resp, err = app.Test(httptest.NewRequest("PUT", "/favicon.ico", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusMethodNotAllowed, resp.StatusCode, "Status code") - utils.AssertEqual(t, strings.Join([]string{fiber.MethodGet, fiber.MethodHead, fiber.MethodOptions}, ", "), resp.Header.Get(fiber.HeaderAllow)) + utils.AssertEqual(t, "GET, HEAD, OPTIONS", resp.Header.Get(fiber.HeaderAllow)) } // go test -run Test_Middleware_Favicon_Not_Found @@ -72,7 +70,8 @@ func Test_Middleware_Favicon_Found(t *testing.T) { return nil }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/favicon.ico", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/favicon.ico", nil)) + utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode, "Status code") utils.AssertEqual(t, "image/x-icon", resp.Header.Get(fiber.HeaderContentType)) @@ -84,15 +83,15 @@ func Test_Middleware_Favicon_Found(t *testing.T) { // TODO use os.Dir if fiber upgrades to 1.16 type mockFS struct{} -func (mockFS) Open(name string) (http.File, error) { +func (m mockFS) Open(name string) (http.File, error) { if name == "/" { name = "." } else { name = strings.TrimPrefix(name, "/") } - file, err := os.Open(name) //nolint:gosec // We're in a test func, so this is fine + file, err := os.Open(name) if err != nil { - return nil, fmt.Errorf("failed to open: %w", err) + return nil, err } return file, nil } @@ -107,7 +106,7 @@ func Test_Middleware_Favicon_FileSystem(t *testing.T) { FileSystem: mockFS{}, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/favicon.ico", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/favicon.ico", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode, "Status code") utils.AssertEqual(t, "image/x-icon", resp.Header.Get(fiber.HeaderContentType)) @@ -124,7 +123,7 @@ func Test_Middleware_Favicon_CacheControl(t *testing.T) { File: "../../.github/testdata/favicon.ico", })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/favicon.ico", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/favicon.ico", nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode, "Status code") utils.AssertEqual(t, "image/x-icon", resp.Header.Get(fiber.HeaderContentType)) @@ -160,7 +159,7 @@ func Test_Favicon_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } diff --git a/middleware/filesystem/filesystem.go b/middleware/filesystem/filesystem.go index 1913ef59e5..890fdf9824 100644 --- a/middleware/filesystem/filesystem.go +++ b/middleware/filesystem/filesystem.go @@ -1,7 +1,6 @@ package filesystem import ( - "fmt" "net/http" "os" "strconv" @@ -56,8 +55,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, Root: nil, @@ -105,7 +102,7 @@ func New(config ...Config) fiber.Handler { cacheControlStr := "public, max-age=" + strconv.Itoa(cfg.MaxAge) // Return new handler - return func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) (err error) { // Don't execute middleware if Next returns true if cfg.Next != nil && cfg.Next(c) { return c.Next() @@ -134,23 +131,28 @@ func New(config ...Config) fiber.Handler { path = cfg.PathPrefix + path } + var ( + file http.File + stat os.FileInfo + ) + if len(path) > 1 { path = utils.TrimRight(path, '/') } - file, err := cfg.Root.Open(path) + file, err = cfg.Root.Open(path) if err != nil && os.IsNotExist(err) && cfg.NotFoundFile != "" { file, err = cfg.Root.Open(cfg.NotFoundFile) } + if err != nil { if os.IsNotExist(err) { return c.Status(fiber.StatusNotFound).Next() } - return fmt.Errorf("failed to open: %w", err) + return } - stat, err := file.Stat() - if err != nil { - return fmt.Errorf("failed to stat: %w", err) + if stat, err = file.Stat(); err != nil { + return } // Serve index if path is directory @@ -198,7 +200,7 @@ func New(config ...Config) fiber.Handler { c.Response().SkipBody = true c.Response().Header.SetContentLength(contentLength) if err := file.Close(); err != nil { - return fmt.Errorf("failed to close: %w", err) + return err } return nil } @@ -208,18 +210,22 @@ func New(config ...Config) fiber.Handler { } // SendFile ... -func SendFile(c *fiber.Ctx, fs http.FileSystem, path string) error { - file, err := fs.Open(path) +func SendFile(c *fiber.Ctx, fs http.FileSystem, path string) (err error) { + var ( + file http.File + stat os.FileInfo + ) + + file, err = fs.Open(path) if err != nil { if os.IsNotExist(err) { return fiber.ErrNotFound } - return fmt.Errorf("failed to open: %w", err) + return err } - stat, err := file.Stat() - if err != nil { - return fmt.Errorf("failed to stat: %w", err) + if stat, err = file.Stat(); err != nil { + return err } // Serve index if path is directory @@ -262,7 +268,7 @@ func SendFile(c *fiber.Ctx, fs http.FileSystem, path string) error { c.Response().SkipBody = true c.Response().Header.SetContentLength(contentLength) if err := file.Close(); err != nil { - return fmt.Errorf("failed to close: %w", err) + return err } return nil } diff --git a/middleware/filesystem/filesystem_test.go b/middleware/filesystem/filesystem_test.go index 56c113e0c5..dcbfcace75 100644 --- a/middleware/filesystem/filesystem_test.go +++ b/middleware/filesystem/filesystem_test.go @@ -1,8 +1,6 @@ -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package filesystem import ( - "context" "net/http" "net/http/httptest" "testing" @@ -121,7 +119,7 @@ func Test_FileSystem(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, tt.url, nil)) + resp, err := app.Test(httptest.NewRequest("GET", tt.url, nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, tt.statusCode, resp.StatusCode) @@ -144,7 +142,7 @@ func Test_FileSystem_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -170,8 +168,7 @@ func Test_FileSystem_Head(t *testing.T) { Root: http.Dir("../../.github/testdata/fs"), })) - req, err := http.NewRequestWithContext(context.Background(), fiber.MethodHead, "/test", nil) - utils.AssertEqual(t, nil, err) + req, _ := http.NewRequest(fiber.MethodHead, "/test", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 200, resp.StatusCode) @@ -185,8 +182,7 @@ func Test_FileSystem_NoRoot(t *testing.T) { app := fiber.New() app.Use(New()) - _, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) - utils.AssertEqual(t, nil, err) + _, _ = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) } func Test_FileSystem_UsingParam(t *testing.T) { @@ -197,8 +193,7 @@ func Test_FileSystem_UsingParam(t *testing.T) { return SendFile(c, http.Dir("../../.github/testdata/fs"), c.Params("path")+".html") }) - req, err := http.NewRequestWithContext(context.Background(), fiber.MethodHead, "/index", nil) - utils.AssertEqual(t, nil, err) + req, _ := http.NewRequest(fiber.MethodHead, "/index", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 200, resp.StatusCode) @@ -212,8 +207,7 @@ func Test_FileSystem_UsingParam_NonFile(t *testing.T) { return SendFile(c, http.Dir("../../.github/testdata/fs"), c.Params("path")+".html") }) - req, err := http.NewRequestWithContext(context.Background(), fiber.MethodHead, "/template", nil) - utils.AssertEqual(t, nil, err) + req, _ := http.NewRequest(fiber.MethodHead, "/template", nil) resp, err := app.Test(req) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 404, resp.StatusCode) diff --git a/middleware/filesystem/utils.go b/middleware/filesystem/utils.go index 4e96db62ac..386c13e389 100644 --- a/middleware/filesystem/utils.go +++ b/middleware/filesystem/utils.go @@ -13,18 +13,18 @@ import ( "github.com/gofiber/fiber/v2/utils" ) -func getFileExtension(p string) string { - n := strings.LastIndexByte(p, '.') +func getFileExtension(path string) string { + n := strings.LastIndexByte(path, '.') if n < 0 { return "" } - return p[n:] + return path[n:] } func dirList(c *fiber.Ctx, f http.File) error { fileinfos, err := f.Readdir(-1) if err != nil { - return fmt.Errorf("failed to read dir: %w", err) + return err } fm := make(map[string]os.FileInfo, len(fileinfos)) @@ -36,13 +36,13 @@ func dirList(c *fiber.Ctx, f http.File) error { } basePathEscaped := html.EscapeString(c.Path()) - _, _ = fmt.Fprintf(c, "%s", basePathEscaped) - _, _ = fmt.Fprintf(c, "

%s

", basePathEscaped) - _, _ = fmt.Fprint(c, "
    ") + fmt.Fprintf(c, "%s", basePathEscaped) + fmt.Fprintf(c, "

    %s

    ", basePathEscaped) + fmt.Fprint(c, "
      ") if len(basePathEscaped) > 1 { parentPathEscaped := html.EscapeString(utils.TrimRight(c.Path(), '/') + "/..") - _, _ = fmt.Fprintf(c, `
    • ..
    • `, parentPathEscaped) + fmt.Fprintf(c, `
    • ..
    • `, parentPathEscaped) } sort.Strings(filenames) @@ -55,10 +55,10 @@ func dirList(c *fiber.Ctx, f http.File) error { auxStr = fmt.Sprintf("file, %d bytes", fi.Size()) className = "file" } - _, _ = fmt.Fprintf(c, `
    • %s, %s, last modified %s
    • `, + fmt.Fprintf(c, `
    • %s, %s, last modified %s
    • `, pathEscaped, className, html.EscapeString(name), auxStr, fi.ModTime()) } - _, _ = fmt.Fprint(c, "
    ") + fmt.Fprint(c, "
") c.Type("html") diff --git a/middleware/idempotency/config.go b/middleware/idempotency/config.go index 21aeb6909c..c8f249a074 100644 --- a/middleware/idempotency/config.go +++ b/middleware/idempotency/config.go @@ -9,7 +9,9 @@ import ( "github.com/gofiber/fiber/v2/internal/storage/memory" ) -var ErrInvalidIdempotencyKey = errors.New("invalid idempotency key") +var ( + ErrInvalidIdempotencyKey = errors.New("invalid idempotency key") +) // Config defines the config for middleware. type Config struct { @@ -49,15 +51,13 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: func(c *fiber.Ctx) bool { // Skip middleware if the request was done using a safe HTTP method return fiber.IsMethodSafe(c.Method()) }, - Lifetime: 30 * time.Minute, //nolint:gomnd // No magic number, just the default config + Lifetime: 30 * time.Minute, KeyHeader: "X-Idempotency-Key", KeyHeaderValidate: func(k string) error { @@ -112,7 +112,7 @@ func configDefault(config ...Config) Config { if cfg.Storage == nil { cfg.Storage = memory.New(memory.Config{ - GCInterval: cfg.Lifetime / 2, //nolint:gomnd // Half the lifetime interval + GCInterval: cfg.Lifetime / 2, }) } diff --git a/middleware/idempotency/idempotency_test.go b/middleware/idempotency/idempotency_test.go index 6612cc6417..e6fdbcd8a3 100644 --- a/middleware/idempotency/idempotency_test.go +++ b/middleware/idempotency/idempotency_test.go @@ -1,4 +1,3 @@ -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package idempotency_test import ( @@ -15,7 +14,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/idempotency" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -174,4 +172,5 @@ func Benchmark_Idempotency(b *testing.B) { h(c) } }) + } diff --git a/middleware/limiter/config.go b/middleware/limiter/config.go index a123ea227b..6da6672b88 100644 --- a/middleware/limiter/config.go +++ b/middleware/limiter/config.go @@ -1,7 +1,7 @@ package limiter import ( - "log" + "fmt" "time" "github.com/gofiber/fiber/v2" @@ -58,21 +58,19 @@ type Config struct { // Default: a new Fixed Window Rate Limiter LimiterMiddleware LimiterHandler - // Deprecated: Use Expiration instead + // DEPRECATED: Use Expiration instead Duration time.Duration - // Deprecated: Use Storage instead + // DEPRECATED, use Storage instead Store fiber.Storage - // Deprecated: Use KeyGenerator instead + // DEPRECATED, use KeyGenerator instead Key func(*fiber.Ctx) string } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ - Max: 5, //nolint:gomnd // No magic number, just the default config + Max: 5, Expiration: 1 * time.Minute, KeyGenerator: func(c *fiber.Ctx) string { return c.IP() @@ -97,15 +95,15 @@ func configDefault(config ...Config) Config { // Set default values if int(cfg.Duration.Seconds()) > 0 { - log.Printf("[LIMITER] Duration is deprecated, please use Expiration\n") + fmt.Println("[LIMITER] Duration is deprecated, please use Expiration") cfg.Expiration = cfg.Duration } if cfg.Key != nil { - log.Printf("[LIMITER] Key is deprecated, please us KeyGenerator\n") + fmt.Println("[LIMITER] Key is deprecated, please us KeyGenerator") cfg.KeyGenerator = cfg.Key } if cfg.Store != nil { - log.Printf("[LIMITER] Store is deprecated, please use Storage\n") + fmt.Println("[LIMITER] Store is deprecated, please use Storage") cfg.Storage = cfg.Store } if cfg.Next == nil { diff --git a/middleware/limiter/limiter_test.go b/middleware/limiter/limiter_test.go index a57ca477f4..847aba354d 100644 --- a/middleware/limiter/limiter_test.go +++ b/middleware/limiter/limiter_test.go @@ -2,6 +2,7 @@ package limiter import ( "io" + "net/http" "net/http/httptest" "sync" "testing" @@ -10,7 +11,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/internal/storage/memory" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -34,7 +34,7 @@ func Test_Limiter_Concurrency_Store(t *testing.T) { var wg sync.WaitGroup singleRequest := func(wg *sync.WaitGroup) { defer wg.Done() - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) @@ -50,13 +50,13 @@ func Test_Limiter_Concurrency_Store(t *testing.T) { wg.Wait() - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 429, resp.StatusCode) time.Sleep(3 * time.Second) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 200, resp.StatusCode) } @@ -80,7 +80,7 @@ func Test_Limiter_Concurrency(t *testing.T) { var wg sync.WaitGroup singleRequest := func(wg *sync.WaitGroup) { defer wg.Done() - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) @@ -96,13 +96,13 @@ func Test_Limiter_Concurrency(t *testing.T) { wg.Wait() - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 429, resp.StatusCode) time.Sleep(3 * time.Second) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 200, resp.StatusCode) } @@ -120,21 +120,21 @@ func Test_Limiter_No_Skip_Choices(t *testing.T) { })) app.Get("/:status", func(c *fiber.Ctx) error { - if c.Params("status") == "fail" { //nolint:goconst // False positive + if c.Params("status") == "fail" { return c.SendStatus(400) } return c.SendStatus(200) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/fail", nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/fail", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 400, resp.StatusCode) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/success", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/success", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 200, resp.StatusCode) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/success", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/success", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 429, resp.StatusCode) } @@ -157,21 +157,21 @@ func Test_Limiter_Skip_Failed_Requests(t *testing.T) { return c.SendStatus(200) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/fail", nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/fail", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 400, resp.StatusCode) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/success", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/success", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 200, resp.StatusCode) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/success", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/success", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 429, resp.StatusCode) time.Sleep(3 * time.Second) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/success", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/success", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 200, resp.StatusCode) } @@ -196,21 +196,21 @@ func Test_Limiter_Skip_Successful_Requests(t *testing.T) { return c.SendStatus(200) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/success", nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/success", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 200, resp.StatusCode) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/fail", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/fail", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 400, resp.StatusCode) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/fail", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/fail", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 429, resp.StatusCode) time.Sleep(3 * time.Second) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/fail", nil)) + resp, err = app.Test(httptest.NewRequest(http.MethodGet, "/fail", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 400, resp.StatusCode) } @@ -232,7 +232,7 @@ func Benchmark_Limiter_Custom_Store(b *testing.B) { h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/") b.ResetTimer() @@ -252,7 +252,7 @@ func Test_Limiter_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -271,7 +271,7 @@ func Test_Limiter_Headers(t *testing.T) { }) fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/") app.Handler()(fctx) @@ -301,7 +301,7 @@ func Benchmark_Limiter(b *testing.B) { h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/") b.ResetTimer() @@ -327,7 +327,7 @@ func Test_Sliding_Window(t *testing.T) { }) singleRequest := func(shouldFail bool) { - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/", nil)) if shouldFail { utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 429, resp.StatusCode) diff --git a/middleware/limiter/manager.go b/middleware/limiter/manager.go index 6b257f4593..68a785a7c2 100644 --- a/middleware/limiter/manager.go +++ b/middleware/limiter/manager.go @@ -46,7 +46,7 @@ func newManager(storage fiber.Storage) *manager { // acquire returns an *entry from the sync.Pool func (m *manager) acquire() *item { - return m.pool.Get().(*item) //nolint:forcetypeassert // We store nothing else in the pool + return m.pool.Get().(*item) } // release and reset *entry to sync.Pool @@ -58,33 +58,37 @@ func (m *manager) release(e *item) { } // get data from storage or memory -func (m *manager) get(key string) *item { - var it *item +func (m *manager) get(key string) (it *item) { if m.storage != nil { it = m.acquire() - raw, err := m.storage.Get(key) - if err != nil { - return it - } - if raw != nil { + if raw, _ := m.storage.Get(key); raw != nil { if _, err := it.UnmarshalMsg(raw); err != nil { - return it + return } } - return it + return } - if it, _ = m.memory.Get(key).(*item); it == nil { //nolint:errcheck // We store nothing else in the pool + if it, _ = m.memory.Get(key).(*item); it == nil { it = m.acquire() - return it } - return it + return +} + +// get raw data from storage or memory +func (m *manager) getRaw(key string) (raw []byte) { + if m.storage != nil { + raw, _ = m.storage.Get(key) + } else { + raw, _ = m.memory.Get(key).([]byte) + } + return } // set data to storage or memory func (m *manager) set(key string, it *item, exp time.Duration) { if m.storage != nil { if raw, err := it.MarshalMsg(nil); err == nil { - _ = m.storage.Set(key, raw, exp) //nolint:errcheck // TODO: Handle error here + _ = m.storage.Set(key, raw, exp) } // we can release data because it's serialized to database m.release(it) @@ -92,3 +96,21 @@ func (m *manager) set(key string, it *item, exp time.Duration) { m.memory.Set(key, it, exp) } } + +// set data to storage or memory +func (m *manager) setRaw(key string, raw []byte, exp time.Duration) { + if m.storage != nil { + _ = m.storage.Set(key, raw, exp) + } else { + m.memory.Set(key, raw, exp) + } +} + +// delete data from storage or memory +func (m *manager) delete(key string) { + if m.storage != nil { + _ = m.storage.Delete(key) + } else { + m.memory.Delete(key) + } +} diff --git a/middleware/logger/README.md b/middleware/logger/README.md index 652f375fe5..60bb2eca68 100644 --- a/middleware/logger/README.md +++ b/middleware/logger/README.md @@ -95,7 +95,7 @@ app.Use(logger.New(logger.Config{ TimeZone: "Asia/Shanghai", Done: func(c *fiber.Ctx, logString []byte) { if c.Response().StatusCode() != fiber.StatusOK { - reporter.SendToSlack(logString) + reporter.SendToSlack(logString) } }, })) @@ -189,7 +189,7 @@ const ( TagBytesReceived = "bytesReceived" TagRoute = "route" TagError = "error" - // Deprecated: Use TagReqHeader instead + // DEPRECATED: Use TagReqHeader instead TagHeader = "header:" // request header TagReqHeader = "reqHeader:" // request header TagRespHeader = "respHeader:" // response header diff --git a/middleware/logger/config.go b/middleware/logger/config.go index 0d45468230..21f34aad7c 100644 --- a/middleware/logger/config.go +++ b/middleware/logger/config.go @@ -79,15 +79,13 @@ type Buffer interface { type LogFunc func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, Done: nil, Format: "[${time}] ${status} - ${latency} ${method} ${path}\n", TimeFormat: "15:04:05", TimeZone: "Local", - TimeInterval: 500 * time.Millisecond, //nolint:gomnd // No magic number, just the default config + TimeInterval: 500 * time.Millisecond, Output: os.Stdout, enableColors: true, } diff --git a/middleware/logger/data.go b/middleware/logger/data.go index 912d016a4b..611a0aeee2 100644 --- a/middleware/logger/data.go +++ b/middleware/logger/data.go @@ -1,10 +1,13 @@ package logger import ( + "sync" "sync/atomic" "time" ) +var DataPool = sync.Pool{New: func() interface{} { return new(Data) }} + // Data is a struct to define some variables to use in custom logger function. type Data struct { Pid string diff --git a/middleware/logger/logger.go b/middleware/logger/logger.go index daa97063f9..1fa07439b4 100644 --- a/middleware/logger/logger.go +++ b/middleware/logger/logger.go @@ -11,7 +11,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/mattn/go-colorable" "github.com/mattn/go-isatty" "github.com/valyala/bytebufferpool" @@ -56,8 +55,6 @@ func New(config ...Config) fiber.Handler { once sync.Once mu sync.Mutex errHandler fiber.ErrorHandler - - dataPool = sync.Pool{New: func() interface{} { return new(Data) }} ) // If colors are enabled, check terminal compatibility @@ -78,7 +75,7 @@ func New(config ...Config) fiber.Handler { } // Return new handler - return func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) (err error) { // Don't execute middleware if Next returns true if cfg.Next != nil && cfg.Next(c) { return c.Next() @@ -104,13 +101,13 @@ func New(config ...Config) fiber.Handler { }) // Logger data - data := dataPool.Get().(*Data) //nolint:forcetypeassert,errcheck // We store nothing else in the pool + data := DataPool.Get().(*Data) // no need for a reset, as long as we always override everything data.Pid = pid data.ErrPaddingStr = errPaddingStr data.Timestamp = timestamp // put data back in the pool - defer dataPool.Put(data) + defer DataPool.Put(data) // Set latency start time if cfg.enableLatency { @@ -124,7 +121,7 @@ func New(config ...Config) fiber.Handler { // Manually call error handler if chainErr != nil { if err := errHandler(c, chainErr); err != nil { - _ = c.SendStatus(fiber.StatusInternalServerError) //nolint:errcheck // TODO: Explain why we ignore the error here + _ = c.SendStatus(fiber.StatusInternalServerError) } } @@ -145,20 +142,18 @@ func New(config ...Config) fiber.Handler { } // Format log to buffer - _, _ = buf.WriteString( //nolint:errcheck // This will never fail - fmt.Sprintf("%s |%s %3d %s| %7v | %15s |%s %-7s %s| %-"+errPaddingStr+"s %s\n", - timestamp.Load().(string), - statusColor(c.Response().StatusCode(), colors), c.Response().StatusCode(), colors.Reset, - data.Stop.Sub(data.Start).Round(time.Millisecond), - c.IP(), - methodColor(c.Method(), colors), c.Method(), colors.Reset, - c.Path(), - formatErr, - ), - ) + _, _ = buf.WriteString(fmt.Sprintf("%s |%s %3d %s| %7v | %15s |%s %-7s %s| %-"+errPaddingStr+"s %s\n", + timestamp.Load().(string), + statusColor(c.Response().StatusCode(), colors), c.Response().StatusCode(), colors.Reset, + data.Stop.Sub(data.Start).Round(time.Millisecond), + c.IP(), + methodColor(c.Method(), colors), c.Method(), colors.Reset, + c.Path(), + formatErr, + )) // Write buffer to output - _, _ = cfg.Output.Write(buf.Bytes()) //nolint:errcheck // This will never fail + _, _ = cfg.Output.Write(buf.Bytes()) if cfg.Done != nil { cfg.Done(c, buf.Bytes()) @@ -174,7 +169,7 @@ func New(config ...Config) fiber.Handler { // Loop over template parts execute dynamic parts and add fixed parts to the buffer for i, logFunc := range logFunChain { if logFunc == nil { - _, _ = buf.Write(templateChain[i]) //nolint:errcheck // This will never fail + _, _ = buf.Write(templateChain[i]) } else if templateChain[i] == nil { _, err = logFunc(buf, c, data, "") } else { @@ -187,7 +182,7 @@ func New(config ...Config) fiber.Handler { // Also write errors to the buffer if err != nil { - _, _ = buf.WriteString(err.Error()) //nolint:errcheck // This will never fail + _, _ = buf.WriteString(err.Error()) } mu.Lock() // Write buffer to output @@ -195,7 +190,7 @@ func New(config ...Config) fiber.Handler { // Write error to output if _, err := cfg.Output.Write([]byte(err.Error())); err != nil { // There is something wrong with the given io.Writer - _, _ = fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) + fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) } } mu.Unlock() diff --git a/middleware/logger/logger_test.go b/middleware/logger/logger_test.go index fb81875223..2295e8a4f5 100644 --- a/middleware/logger/logger_test.go +++ b/middleware/logger/logger_test.go @@ -1,4 +1,3 @@ -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package logger import ( @@ -17,7 +16,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/requestid" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/bytebufferpool" "github.com/valyala/fasthttp" ) @@ -39,7 +37,7 @@ func Test_Logger(t *testing.T) { return errors.New("some random error") }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusInternalServerError, resp.StatusCode) utils.AssertEqual(t, "some random error", buf.String()) @@ -72,21 +70,21 @@ func Test_Logger_locals(t *testing.T) { return c.SendStatus(fiber.StatusOK) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, "johndoe", buf.String()) buf.Reset() - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/int", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/int", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, "55", buf.String()) buf.Reset() - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/empty", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/empty", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, "", buf.String()) @@ -102,7 +100,7 @@ func Test_Logger_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -115,15 +113,15 @@ func Test_Logger_Done(t *testing.T) { app.Use(New(Config{ Done: func(c *fiber.Ctx, logString []byte) { if c.Response().StatusCode() == fiber.StatusOK { - _, err := buf.Write(logString) - utils.AssertEqual(t, nil, err) + buf.Write(logString) } }, })).Get("/logging", func(ctx *fiber.Ctx) error { return ctx.SendStatus(fiber.StatusOK) }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/logging", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/logging", nil)) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, true, buf.Len() > 0) @@ -137,7 +135,7 @@ func Test_Logger_ErrorTimeZone(t *testing.T) { TimeZone: "invalid", })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -158,7 +156,7 @@ func Test_Logger_ErrorOutput(t *testing.T) { Output: o, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) @@ -180,7 +178,7 @@ func Test_Logger_All(t *testing.T) { // Alias colors colors := app.Config().ColorScheme - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/?foo=bar", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/?foo=bar", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) @@ -200,7 +198,7 @@ func Test_Query_Params(t *testing.T) { Output: buf, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/?foo=bar&baz=moz", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/?foo=bar&baz=moz", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) @@ -228,7 +226,7 @@ func Test_Response_Body(t *testing.T) { return c.Send([]byte("Post in test")) }) - _, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + _, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) expectedGetResponse := "Sample response body" @@ -236,7 +234,7 @@ func Test_Response_Body(t *testing.T) { buf.Reset() // Reset buffer to test POST - _, err = app.Test(httptest.NewRequest(fiber.MethodPost, "/test", nil)) + _, err = app.Test(httptest.NewRequest("POST", "/test", nil)) utils.AssertEqual(t, nil, err) expectedPostResponse := "Post in test" @@ -260,7 +258,7 @@ func Test_Logger_AppendUint(t *testing.T) { return c.SendString("hello") }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, "0 5 200", buf.String()) @@ -287,11 +285,12 @@ func Test_Logger_Data_Race(t *testing.T) { wg := &sync.WaitGroup{} wg.Add(1) go func() { - resp1, err1 = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp1, err1 = app.Test(httptest.NewRequest("GET", "/", nil)) wg.Done() }() - resp2, err2 = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp2, err2 = app.Test(httptest.NewRequest("GET", "/", nil)) wg.Wait() + utils.AssertEqual(t, nil, err1) utils.AssertEqual(t, fiber.StatusOK, resp1.StatusCode) utils.AssertEqual(t, nil, err2) @@ -300,23 +299,21 @@ func Test_Logger_Data_Race(t *testing.T) { // go test -v -run=^$ -bench=Benchmark_Logger -benchmem -count=4 func Benchmark_Logger(b *testing.B) { - benchSetup := func(b *testing.B, app *fiber.App) { - b.Helper() - + benchSetup := func(bb *testing.B, app *fiber.App) { h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/") - b.ReportAllocs() - b.ResetTimer() + bb.ReportAllocs() + bb.ResetTimer() - for n := 0; n < b.N; n++ { + for n := 0; n < bb.N; n++ { h(fctx) } - utils.AssertEqual(b, 200, fctx.Response.Header.StatusCode()) + utils.AssertEqual(bb, 200, fctx.Response.Header.StatusCode()) } b.Run("Base", func(bb *testing.B) { @@ -378,7 +375,8 @@ func Test_Response_Header(t *testing.T) { return c.SendString("Hello fiber!") }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, "Hello fiber!", buf.String()) @@ -398,10 +396,10 @@ func Test_Req_Header(t *testing.T) { app.Get("/", func(c *fiber.Ctx) error { return c.SendString("Hello fiber!") }) - headerReq := httptest.NewRequest(fiber.MethodGet, "/", nil) + headerReq := httptest.NewRequest("GET", "/", nil) headerReq.Header.Add("test", "Hello fiber!") - resp, err := app.Test(headerReq) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, "Hello fiber!", buf.String()) @@ -421,10 +419,10 @@ func Test_ReqHeader_Header(t *testing.T) { app.Get("/", func(c *fiber.Ctx) error { return c.SendString("Hello fiber!") }) - reqHeaderReq := httptest.NewRequest(fiber.MethodGet, "/", nil) + reqHeaderReq := httptest.NewRequest("GET", "/", nil) reqHeaderReq.Header.Add("test", "Hello fiber!") - resp, err := app.Test(reqHeaderReq) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, "Hello fiber!", buf.String()) @@ -451,10 +449,10 @@ func Test_CustomTags(t *testing.T) { app.Get("/", func(c *fiber.Ctx) error { return c.SendString("Hello fiber!") }) - reqHeaderReq := httptest.NewRequest(fiber.MethodGet, "/", nil) + reqHeaderReq := httptest.NewRequest("GET", "/", nil) reqHeaderReq.Header.Add("test", "Hello fiber!") - resp, err := app.Test(reqHeaderReq) + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, customTag, buf.String()) @@ -494,7 +492,7 @@ func Test_Logger_ByteSent_Streaming(t *testing.T) { return nil }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, "0 0 200", buf.String()) diff --git a/middleware/logger/tags.go b/middleware/logger/tags.go index 2f746ddd4e..7eb67582bc 100644 --- a/middleware/logger/tags.go +++ b/middleware/logger/tags.go @@ -31,7 +31,7 @@ const ( TagBytesReceived = "bytesReceived" TagRoute = "route" TagError = "error" - // Deprecated: Use TagReqHeader instead + // DEPRECATED: Use TagReqHeader instead TagHeader = "header:" TagReqHeader = "reqHeader:" TagRespHeader = "respHeader:" @@ -195,7 +195,7 @@ func createTagMap(cfg *Config) map[string]LogFunc { return output.WriteString(fmt.Sprintf("%7v", latency)) }, TagTime: func(output Buffer, c *fiber.Ctx, data *Data, extraParam string) (int, error) { - return output.WriteString(data.Timestamp.Load().(string)) //nolint:forcetypeassert // We always store a string in here + return output.WriteString(data.Timestamp.Load().(string)) }, } // merge with custom tags from user diff --git a/middleware/logger/template_chain.go b/middleware/logger/template_chain.go index 1a5dd448f6..ceb31a3356 100644 --- a/middleware/logger/template_chain.go +++ b/middleware/logger/template_chain.go @@ -14,16 +14,13 @@ import ( // funcChain contains for the parts which exist the functions for the dynamic parts // funcChain and fixParts always have the same length and contain nil for the parts where no data is required in the chain, // if a function exists for the part, a parameter for it can also exist in the fixParts slice -func buildLogFuncChain(cfg *Config, tagFunctions map[string]LogFunc) ([][]byte, []LogFunc, error) { +func buildLogFuncChain(cfg *Config, tagFunctions map[string]LogFunc) (fixParts [][]byte, funcChain []LogFunc, err error) { // process flow is copied from the fasttemplate flow https://github.com/valyala/fasttemplate/blob/2a2d1afadadf9715bfa19683cdaeac8347e5d9f9/template.go#L23-L62 templateB := utils.UnsafeBytes(cfg.Format) startTagB := utils.UnsafeBytes(startTag) endTagB := utils.UnsafeBytes(endTag) paramSeparatorB := utils.UnsafeBytes(paramSeparator) - var fixParts [][]byte - var funcChain []LogFunc - for { currentPos := bytes.Index(templateB, startTagB) if currentPos < 0 { @@ -45,13 +42,13 @@ func buildLogFuncChain(cfg *Config, tagFunctions map[string]LogFunc) ([][]byte, // ## function block ## // first check for tags with parameters if index := bytes.Index(templateB[:currentPos], paramSeparatorB); index != -1 { - logFunc, ok := tagFunctions[utils.UnsafeString(templateB[:index+1])] - if !ok { + if logFunc, ok := tagFunctions[utils.UnsafeString(templateB[:index+1])]; ok { + funcChain = append(funcChain, logFunc) + // add param to the fixParts + fixParts = append(fixParts, templateB[index+1:currentPos]) + } else { return nil, nil, errors.New("No parameter found in \"" + utils.UnsafeString(templateB[:currentPos]) + "\"") } - funcChain = append(funcChain, logFunc) - // add param to the fixParts - fixParts = append(fixParts, templateB[index+1:currentPos]) } else if logFunc, ok := tagFunctions[utils.UnsafeString(templateB[:currentPos])]; ok { // add functions without parameter funcChain = append(funcChain, logFunc) @@ -66,5 +63,5 @@ func buildLogFuncChain(cfg *Config, tagFunctions map[string]LogFunc) ([][]byte, funcChain = append(funcChain, nil) fixParts = append(fixParts, templateB) - return fixParts, funcChain, nil + return } diff --git a/middleware/monitor/config.go b/middleware/monitor/config.go index 10889707f9..559dd405ef 100644 --- a/middleware/monitor/config.go +++ b/middleware/monitor/config.go @@ -41,48 +41,36 @@ type Config struct { // ChartJsURL for specify ChartJS library path or URL . also you can use relative path // // Optional. Default: https://cdn.jsdelivr.net/npm/chart.js@2.9/dist/Chart.bundle.min.js - ChartJSURL string + ChartJsURL string index string } -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Title: defaultTitle, Refresh: defaultRefresh, FontURL: defaultFontURL, - ChartJSURL: defaultChartJSURL, + ChartJsURL: defaultChartJsURL, CustomHead: defaultCustomHead, APIOnly: false, Next: nil, - index: newIndex(viewBag{ - defaultTitle, - defaultRefresh, - defaultFontURL, - defaultChartJSURL, - defaultCustomHead, - }), + index: newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJsURL, + defaultCustomHead}), } func configDefault(config ...Config) Config { // Users can change ConfigDefault.Title/Refresh which then // become incompatible with ConfigDefault.index - if ConfigDefault.Title != defaultTitle || - ConfigDefault.Refresh != defaultRefresh || - ConfigDefault.FontURL != defaultFontURL || - ConfigDefault.ChartJSURL != defaultChartJSURL || + if ConfigDefault.Title != defaultTitle || ConfigDefault.Refresh != defaultRefresh || + ConfigDefault.FontURL != defaultFontURL || ConfigDefault.ChartJsURL != defaultChartJsURL || ConfigDefault.CustomHead != defaultCustomHead { + if ConfigDefault.Refresh < minRefresh { ConfigDefault.Refresh = minRefresh } // update default index with new default title/refresh - ConfigDefault.index = newIndex(viewBag{ - ConfigDefault.Title, - ConfigDefault.Refresh, - ConfigDefault.FontURL, - ConfigDefault.ChartJSURL, - ConfigDefault.CustomHead, - }) + ConfigDefault.index = newIndex(viewBag{ConfigDefault.Title, + ConfigDefault.Refresh, ConfigDefault.FontURL, ConfigDefault.ChartJsURL, ConfigDefault.CustomHead}) } // Return default config if nothing provided @@ -105,8 +93,8 @@ func configDefault(config ...Config) Config { cfg.FontURL = defaultFontURL } - if cfg.ChartJSURL == "" { - cfg.ChartJSURL = defaultChartJSURL + if cfg.ChartJsURL == "" { + cfg.ChartJsURL = defaultChartJsURL } if cfg.Refresh < minRefresh { cfg.Refresh = minRefresh @@ -124,8 +112,8 @@ func configDefault(config ...Config) Config { cfg.index = newIndex(viewBag{ title: cfg.Title, refresh: cfg.Refresh, - fontURL: cfg.FontURL, - chartJSURL: cfg.ChartJSURL, + fontUrl: cfg.FontURL, + chartJsUrl: cfg.ChartJsURL, customHead: cfg.CustomHead, }) diff --git a/middleware/monitor/config_test.go b/middleware/monitor/config_test.go index 60bf09ca70..062d1e4070 100644 --- a/middleware/monitor/config_test.go +++ b/middleware/monitor/config_test.go @@ -18,11 +18,11 @@ func Test_Config_Default(t *testing.T) { utils.AssertEqual(t, defaultTitle, cfg.Title) utils.AssertEqual(t, defaultRefresh, cfg.Refresh) utils.AssertEqual(t, defaultFontURL, cfg.FontURL) - utils.AssertEqual(t, defaultChartJSURL, cfg.ChartJSURL) + utils.AssertEqual(t, defaultChartJsURL, cfg.ChartJsURL) utils.AssertEqual(t, defaultCustomHead, cfg.CustomHead) utils.AssertEqual(t, false, cfg.APIOnly) utils.AssertEqual(t, (func(*fiber.Ctx) bool)(nil), cfg.Next) - utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJSURL, defaultCustomHead}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJsURL, defaultCustomHead}), cfg.index) }) t.Run("set title", func(t *testing.T) { @@ -35,11 +35,11 @@ func Test_Config_Default(t *testing.T) { utils.AssertEqual(t, title, cfg.Title) utils.AssertEqual(t, defaultRefresh, cfg.Refresh) utils.AssertEqual(t, defaultFontURL, cfg.FontURL) - utils.AssertEqual(t, defaultChartJSURL, cfg.ChartJSURL) + utils.AssertEqual(t, defaultChartJsURL, cfg.ChartJsURL) utils.AssertEqual(t, defaultCustomHead, cfg.CustomHead) utils.AssertEqual(t, false, cfg.APIOnly) utils.AssertEqual(t, (func(*fiber.Ctx) bool)(nil), cfg.Next) - utils.AssertEqual(t, newIndex(viewBag{title, defaultRefresh, defaultFontURL, defaultChartJSURL, defaultCustomHead}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{title, defaultRefresh, defaultFontURL, defaultChartJsURL, defaultCustomHead}), cfg.index) }) t.Run("set refresh less than default", func(t *testing.T) { @@ -51,11 +51,11 @@ func Test_Config_Default(t *testing.T) { utils.AssertEqual(t, defaultTitle, cfg.Title) utils.AssertEqual(t, minRefresh, cfg.Refresh) utils.AssertEqual(t, defaultFontURL, cfg.FontURL) - utils.AssertEqual(t, defaultChartJSURL, cfg.ChartJSURL) + utils.AssertEqual(t, defaultChartJsURL, cfg.ChartJsURL) utils.AssertEqual(t, defaultCustomHead, cfg.CustomHead) utils.AssertEqual(t, false, cfg.APIOnly) utils.AssertEqual(t, (func(*fiber.Ctx) bool)(nil), cfg.Next) - utils.AssertEqual(t, newIndex(viewBag{defaultTitle, minRefresh, defaultFontURL, defaultChartJSURL, defaultCustomHead}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{defaultTitle, minRefresh, defaultFontURL, defaultChartJsURL, defaultCustomHead}), cfg.index) }) t.Run("set refresh", func(t *testing.T) { @@ -68,45 +68,45 @@ func Test_Config_Default(t *testing.T) { utils.AssertEqual(t, defaultTitle, cfg.Title) utils.AssertEqual(t, refresh, cfg.Refresh) utils.AssertEqual(t, defaultFontURL, cfg.FontURL) - utils.AssertEqual(t, defaultChartJSURL, cfg.ChartJSURL) + utils.AssertEqual(t, defaultChartJsURL, cfg.ChartJsURL) utils.AssertEqual(t, defaultCustomHead, cfg.CustomHead) utils.AssertEqual(t, false, cfg.APIOnly) utils.AssertEqual(t, (func(*fiber.Ctx) bool)(nil), cfg.Next) - utils.AssertEqual(t, newIndex(viewBag{defaultTitle, refresh, defaultFontURL, defaultChartJSURL, defaultCustomHead}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{defaultTitle, refresh, defaultFontURL, defaultChartJsURL, defaultCustomHead}), cfg.index) }) t.Run("set font url", func(t *testing.T) { t.Parallel() - fontURL := "https://example.com" + fontUrl := "https://example.com" cfg := configDefault(Config{ - FontURL: fontURL, + FontURL: fontUrl, }) utils.AssertEqual(t, defaultTitle, cfg.Title) utils.AssertEqual(t, defaultRefresh, cfg.Refresh) - utils.AssertEqual(t, fontURL, cfg.FontURL) - utils.AssertEqual(t, defaultChartJSURL, cfg.ChartJSURL) + utils.AssertEqual(t, fontUrl, cfg.FontURL) + utils.AssertEqual(t, defaultChartJsURL, cfg.ChartJsURL) utils.AssertEqual(t, defaultCustomHead, cfg.CustomHead) utils.AssertEqual(t, false, cfg.APIOnly) utils.AssertEqual(t, (func(*fiber.Ctx) bool)(nil), cfg.Next) - utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, fontURL, defaultChartJSURL, defaultCustomHead}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, fontUrl, defaultChartJsURL, defaultCustomHead}), cfg.index) }) t.Run("set chart js url", func(t *testing.T) { t.Parallel() - chartURL := "http://example.com" + chartUrl := "http://example.com" cfg := configDefault(Config{ - ChartJSURL: chartURL, + ChartJsURL: chartUrl, }) utils.AssertEqual(t, defaultTitle, cfg.Title) utils.AssertEqual(t, defaultRefresh, cfg.Refresh) utils.AssertEqual(t, defaultFontURL, cfg.FontURL) - utils.AssertEqual(t, chartURL, cfg.ChartJSURL) + utils.AssertEqual(t, chartUrl, cfg.ChartJsURL) utils.AssertEqual(t, defaultCustomHead, cfg.CustomHead) utils.AssertEqual(t, false, cfg.APIOnly) utils.AssertEqual(t, (func(*fiber.Ctx) bool)(nil), cfg.Next) - utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, chartURL, defaultCustomHead}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, chartUrl, defaultCustomHead}), cfg.index) }) t.Run("set custom head", func(t *testing.T) { @@ -119,11 +119,11 @@ func Test_Config_Default(t *testing.T) { utils.AssertEqual(t, defaultTitle, cfg.Title) utils.AssertEqual(t, defaultRefresh, cfg.Refresh) utils.AssertEqual(t, defaultFontURL, cfg.FontURL) - utils.AssertEqual(t, defaultChartJSURL, cfg.ChartJSURL) + utils.AssertEqual(t, defaultChartJsURL, cfg.ChartJsURL) utils.AssertEqual(t, head, cfg.CustomHead) utils.AssertEqual(t, false, cfg.APIOnly) utils.AssertEqual(t, (func(*fiber.Ctx) bool)(nil), cfg.Next) - utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJSURL, head}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJsURL, head}), cfg.index) }) t.Run("set api only", func(t *testing.T) { @@ -135,11 +135,11 @@ func Test_Config_Default(t *testing.T) { utils.AssertEqual(t, defaultTitle, cfg.Title) utils.AssertEqual(t, defaultRefresh, cfg.Refresh) utils.AssertEqual(t, defaultFontURL, cfg.FontURL) - utils.AssertEqual(t, defaultChartJSURL, cfg.ChartJSURL) + utils.AssertEqual(t, defaultChartJsURL, cfg.ChartJsURL) utils.AssertEqual(t, defaultCustomHead, cfg.CustomHead) utils.AssertEqual(t, true, cfg.APIOnly) utils.AssertEqual(t, (func(*fiber.Ctx) bool)(nil), cfg.Next) - utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJSURL, defaultCustomHead}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJsURL, defaultCustomHead}), cfg.index) }) t.Run("set next", func(t *testing.T) { @@ -154,10 +154,10 @@ func Test_Config_Default(t *testing.T) { utils.AssertEqual(t, defaultTitle, cfg.Title) utils.AssertEqual(t, defaultRefresh, cfg.Refresh) utils.AssertEqual(t, defaultFontURL, cfg.FontURL) - utils.AssertEqual(t, defaultChartJSURL, cfg.ChartJSURL) + utils.AssertEqual(t, defaultChartJsURL, cfg.ChartJsURL) utils.AssertEqual(t, defaultCustomHead, cfg.CustomHead) utils.AssertEqual(t, false, cfg.APIOnly) utils.AssertEqual(t, f(nil), cfg.Next(nil)) - utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJSURL, defaultCustomHead}), cfg.index) + utils.AssertEqual(t, newIndex(viewBag{defaultTitle, defaultRefresh, defaultFontURL, defaultChartJsURL, defaultCustomHead}), cfg.index) }) } diff --git a/middleware/monitor/index.go b/middleware/monitor/index.go index c873290c46..b17c95f9e4 100644 --- a/middleware/monitor/index.go +++ b/middleware/monitor/index.go @@ -9,22 +9,23 @@ import ( type viewBag struct { title string refresh time.Duration - fontURL string - chartJSURL string + fontUrl string + chartJsUrl string customHead string } // returns index with new title/refresh func newIndex(dat viewBag) string { + timeout := dat.refresh.Milliseconds() - timeoutDiff if timeout < timeoutDiff { timeout = timeoutDiff } ts := strconv.FormatInt(timeout, 10) replacer := strings.NewReplacer("$TITLE", dat.title, "$TIMEOUT", ts, - "$FONT_URL", dat.fontURL, "$CHART_JS_URL", dat.chartJSURL, "$CUSTOM_HEAD", dat.customHead, + "$FONT_URL", dat.fontUrl, "$CHART_JS_URL", dat.chartJsUrl, "$CUSTOM_HEAD", dat.customHead, ) - return replacer.Replace(indexHTML) + return replacer.Replace(indexHtml) } const ( @@ -34,11 +35,11 @@ const ( timeoutDiff = 200 // timeout will be Refresh (in milliseconds) - timeoutDiff minRefresh = timeoutDiff * time.Millisecond defaultFontURL = `https://fonts.googleapis.com/css2?family=Roboto:wght@400;900&display=swap` - defaultChartJSURL = `https://cdn.jsdelivr.net/npm/chart.js@2.9/dist/Chart.bundle.min.js` + defaultChartJsURL = `https://cdn.jsdelivr.net/npm/chart.js@2.9/dist/Chart.bundle.min.js` defaultCustomHead = `` // parametrized by $TITLE and $TIMEOUT - indexHTML = ` + indexHtml = ` diff --git a/middleware/monitor/monitor.go b/middleware/monitor/monitor.go index e3e39f06fe..729bc00988 100644 --- a/middleware/monitor/monitor.go +++ b/middleware/monitor/monitor.go @@ -33,20 +33,18 @@ type statsOS struct { Conns int `json:"conns"` } -//nolint:gochecknoglobals // TODO: Do not use a global var here var ( - monitPIDCPU atomic.Value - monitPIDRAM atomic.Value - monitPIDConns atomic.Value - - monitOSCPU atomic.Value - monitOSRAM atomic.Value - monitOSTotalRAM atomic.Value - monitOSLoadAvg atomic.Value - monitOSConns atomic.Value + monitPidCpu atomic.Value + monitPidRam atomic.Value + monitPidConns atomic.Value + + monitOsCpu atomic.Value + monitOsRam atomic.Value + monitOsTotalRam atomic.Value + monitOsLoadAvg atomic.Value + monitOsConns atomic.Value ) -//nolint:gochecknoglobals // TODO: Do not use a global var here var ( mutex sync.RWMutex once sync.Once @@ -60,7 +58,7 @@ func New(config ...Config) fiber.Handler { // Start routine to update statistics once.Do(func() { - p, _ := process.NewProcess(int32(os.Getpid())) //nolint:errcheck // TODO: Handle error + p, _ := process.NewProcess(int32(os.Getpid())) updateStatistics(p) @@ -74,7 +72,6 @@ func New(config ...Config) fiber.Handler { }) // Return new handler - //nolint:errcheck // Ignore the type-assertion errors return func(c *fiber.Ctx) error { // Don't execute middleware if Next returns true if cfg.Next != nil && cfg.Next(c) { @@ -86,15 +83,15 @@ func New(config ...Config) fiber.Handler { } if c.Get(fiber.HeaderAccept) == fiber.MIMEApplicationJSON || cfg.APIOnly { mutex.Lock() - data.PID.CPU, _ = monitPIDCPU.Load().(float64) - data.PID.RAM, _ = monitPIDRAM.Load().(uint64) - data.PID.Conns, _ = monitPIDConns.Load().(int) - - data.OS.CPU, _ = monitOSCPU.Load().(float64) - data.OS.RAM, _ = monitOSRAM.Load().(uint64) - data.OS.TotalRAM, _ = monitOSTotalRAM.Load().(uint64) - data.OS.LoadAvg, _ = monitOSLoadAvg.Load().(float64) - data.OS.Conns, _ = monitOSConns.Load().(int) + data.PID.CPU = monitPidCpu.Load().(float64) + data.PID.RAM = monitPidRam.Load().(uint64) + data.PID.Conns = monitPidConns.Load().(int) + + data.OS.CPU = monitOsCpu.Load().(float64) + data.OS.RAM = monitOsRam.Load().(uint64) + data.OS.TotalRAM = monitOsTotalRam.Load().(uint64) + data.OS.LoadAvg = monitOsLoadAvg.Load().(float64) + data.OS.Conns = monitOsConns.Load().(int) mutex.Unlock() return c.Status(fiber.StatusOK).JSON(data) } @@ -104,35 +101,29 @@ func New(config ...Config) fiber.Handler { } func updateStatistics(p *process.Process) { - pidCPU, err := p.CPUPercent() - if err != nil { - monitPIDCPU.Store(pidCPU / 10) //nolint:gomnd // TODO: Explain why we divide by 10 here - } + pidCpu, _ := p.CPUPercent() + monitPidCpu.Store(pidCpu / 10) - if osCPU, err := cpu.Percent(0, false); err != nil && len(osCPU) > 0 { - monitOSCPU.Store(osCPU[0]) + if osCpu, _ := cpu.Percent(0, false); len(osCpu) > 0 { + monitOsCpu.Store(osCpu[0]) } - if pidRAM, err := p.MemoryInfo(); err != nil && pidRAM != nil { - monitPIDRAM.Store(pidRAM.RSS) + if pidMem, _ := p.MemoryInfo(); pidMem != nil { + monitPidRam.Store(pidMem.RSS) } - if osRAM, err := mem.VirtualMemory(); err != nil && osRAM != nil { - monitOSRAM.Store(osRAM.Used) - monitOSTotalRAM.Store(osRAM.Total) + if osMem, _ := mem.VirtualMemory(); osMem != nil { + monitOsRam.Store(osMem.Used) + monitOsTotalRam.Store(osMem.Total) } - if loadAvg, err := load.Avg(); err != nil && loadAvg != nil { - monitOSLoadAvg.Store(loadAvg.Load1) + if loadAvg, _ := load.Avg(); loadAvg != nil { + monitOsLoadAvg.Store(loadAvg.Load1) } - pidConns, err := net.ConnectionsPid("tcp", p.Pid) - if err != nil { - monitPIDConns.Store(len(pidConns)) - } + pidConns, _ := net.ConnectionsPid("tcp", p.Pid) + monitPidConns.Store(len(pidConns)) - osConns, err := net.Connections("tcp") - if err != nil { - monitOSConns.Store(len(osConns)) - } + osConns, _ := net.Connections("tcp") + monitOsConns.Store(len(osConns)) } diff --git a/middleware/monitor/monitor_test.go b/middleware/monitor/monitor_test.go index f6e63fd9d4..d069bba08d 100644 --- a/middleware/monitor/monitor_test.go +++ b/middleware/monitor/monitor_test.go @@ -10,7 +10,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -62,7 +61,6 @@ func Test_Monitor_Html(t *testing.T) { conf.Refresh.Milliseconds()-timeoutDiff) utils.AssertEqual(t, true, bytes.Contains(buf, []byte(timeoutLine))) } - func Test_Monitor_Html_CustomCodes(t *testing.T) { t.Parallel() @@ -84,10 +82,8 @@ func Test_Monitor_Html_CustomCodes(t *testing.T) { utils.AssertEqual(t, true, bytes.Contains(buf, []byte(timeoutLine))) // custom config - conf := Config{ - Title: "New " + defaultTitle, - Refresh: defaultRefresh + time.Second, - ChartJSURL: "https://cdnjs.com/libraries/Chart.js", + conf := Config{Title: "New " + defaultTitle, Refresh: defaultRefresh + time.Second, + ChartJsURL: "https://cdnjs.com/libraries/Chart.js", FontURL: "/public/my-font.css", CustomHead: ``, } @@ -140,7 +136,7 @@ func Benchmark_Monitor(b *testing.B) { h := app.Handler() fctx := &fasthttp.RequestCtx{} - fctx.Request.Header.SetMethod(fiber.MethodGet) + fctx.Request.Header.SetMethod("GET") fctx.Request.SetRequestURI("/") fctx.Request.Header.Set(fiber.HeaderAccept, fiber.MIMEApplicationJSON) diff --git a/middleware/pprof/config.go b/middleware/pprof/config.go index fb3e0978ae..e69ffd7094 100644 --- a/middleware/pprof/config.go +++ b/middleware/pprof/config.go @@ -1,8 +1,6 @@ package pprof -import ( - "github.com/gofiber/fiber/v2" -) +import "github.com/gofiber/fiber/v2" // Config defines the config for middleware. type Config struct { @@ -19,7 +17,6 @@ type Config struct { Prefix string } -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, } diff --git a/middleware/pprof/pprof.go b/middleware/pprof/pprof.go index 6978d325e3..8ad85c9a23 100644 --- a/middleware/pprof/pprof.go +++ b/middleware/pprof/pprof.go @@ -5,30 +5,29 @@ import ( "strings" "github.com/gofiber/fiber/v2" - "github.com/valyala/fasthttp/fasthttpadaptor" ) +// Set pprof adaptors +var ( + pprofIndex = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Index) + pprofCmdline = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Cmdline) + pprofProfile = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Profile) + pprofSymbol = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Symbol) + pprofTrace = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Trace) + pprofAllocs = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("allocs").ServeHTTP) + pprofBlock = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("block").ServeHTTP) + pprofGoroutine = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("goroutine").ServeHTTP) + pprofHeap = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("heap").ServeHTTP) + pprofMutex = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("mutex").ServeHTTP) + pprofThreadcreate = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("threadcreate").ServeHTTP) +) + // New creates a new middleware handler func New(config ...Config) fiber.Handler { // Set default config cfg := configDefault(config...) - // Set pprof adaptors - var ( - pprofIndex = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Index) - pprofCmdline = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Cmdline) - pprofProfile = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Profile) - pprofSymbol = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Symbol) - pprofTrace = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Trace) - pprofAllocs = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("allocs").ServeHTTP) - pprofBlock = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("block").ServeHTTP) - pprofGoroutine = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("goroutine").ServeHTTP) - pprofHeap = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("heap").ServeHTTP) - pprofMutex = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("mutex").ServeHTTP) - pprofThreadcreate = fasthttpadaptor.NewFastHTTPHandlerFunc(pprof.Handler("threadcreate").ServeHTTP) - ) - // Return new handler return func(c *fiber.Ctx) error { // Don't execute middleware if Next returns true diff --git a/middleware/proxy/config.go b/middleware/proxy/config.go index 094b2c32a0..be5e043e51 100644 --- a/middleware/proxy/config.go +++ b/middleware/proxy/config.go @@ -5,7 +5,6 @@ import ( "time" "github.com/gofiber/fiber/v2" - "github.com/valyala/fasthttp" ) @@ -49,7 +48,7 @@ type Config struct { WriteBufferSize int // tls config for the http client. - TlsConfig *tls.Config //nolint:stylecheck,revive // TODO: Rename to "TLSConfig" in v3 + TlsConfig *tls.Config // Client is custom client when client config is complex. // Note that Servers, Timeout, WriteBufferSize, ReadBufferSize and TlsConfig @@ -58,8 +57,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, ModifyRequest: nil, diff --git a/middleware/proxy/proxy.go b/middleware/proxy/proxy.go index 356ebc10cb..a468f41b8b 100644 --- a/middleware/proxy/proxy.go +++ b/middleware/proxy/proxy.go @@ -3,20 +3,19 @@ package proxy import ( "bytes" "crypto/tls" - "log" + "fmt" "net/url" "strings" "sync" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) // New is deprecated func New(config Config) fiber.Handler { - log.Printf("proxy.New is deprecated, please use proxy.Balancer instead\n") + fmt.Println("proxy.New is deprecated, please use proxy.Balancer instead") return Balancer(config) } @@ -26,7 +25,7 @@ func Balancer(config Config) fiber.Handler { cfg := configDefault(config) // Load balanced client - lbc := &fasthttp.LBClient{} + var lbc = &fasthttp.LBClient{} // Note that Servers, Timeout, WriteBufferSize, ReadBufferSize and TlsConfig // will not be used if the client are set. if config.Client == nil { @@ -62,7 +61,7 @@ func Balancer(config Config) fiber.Handler { } // Return new handler - return func(c *fiber.Ctx) error { + return func(c *fiber.Ctx) (err error) { // Don't execute middleware if Next returns true if cfg.Next != nil && cfg.Next(c) { return c.Next() @@ -77,7 +76,7 @@ func Balancer(config Config) fiber.Handler { // Modify request if cfg.ModifyRequest != nil { - if err := cfg.ModifyRequest(c); err != nil { + if err = cfg.ModifyRequest(c); err != nil { return err } } @@ -85,7 +84,7 @@ func Balancer(config Config) fiber.Handler { req.SetRequestURI(utils.UnsafeString(req.RequestURI())) // Forward request - if err := lbc.Do(req, res); err != nil { + if err = lbc.Do(req, res); err != nil { return err } @@ -94,7 +93,7 @@ func Balancer(config Config) fiber.Handler { // Modify response if cfg.ModifyResponse != nil { - if err := cfg.ModifyResponse(c); err != nil { + if err = cfg.ModifyResponse(c); err != nil { return err } } @@ -104,20 +103,16 @@ func Balancer(config Config) fiber.Handler { } } -//nolint:gochecknoglobals // TODO: Do not use a global var here var client = &fasthttp.Client{ NoDefaultUserAgentHeader: true, DisablePathNormalizing: true, } -//nolint:gochecknoglobals // TODO: Do not use a global var here var lock sync.RWMutex // WithTlsConfig update http client with a user specified tls.config // This function should be called before Do and Forward. // Deprecated: use WithClient instead. -// -//nolint:stylecheck,revive // TODO: Rename to "WithTLSConfig" in v3 func WithTlsConfig(tlsConfig *tls.Config) { client.TLSConfig = tlsConfig } diff --git a/middleware/proxy/proxy_test.go b/middleware/proxy/proxy_test.go index d87145514a..d7626da34e 100644 --- a/middleware/proxy/proxy_test.go +++ b/middleware/proxy/proxy_test.go @@ -4,6 +4,7 @@ import ( "crypto/tls" "io" "net" + "net/http" "net/http/httptest" "strings" "testing" @@ -12,11 +13,10 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/internal/tlstest" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) -func createProxyTestServer(t *testing.T, handler fiber.Handler) (*fiber.App, string) { +func createProxyTestServer(handler fiber.Handler, t *testing.T) (*fiber.App, string) { t.Helper() target := fiber.New(fiber.Config{DisableStartupMessage: true}) @@ -60,7 +60,7 @@ func Test_Proxy_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -69,11 +69,11 @@ func Test_Proxy_Next(t *testing.T) { func Test_Proxy(t *testing.T) { t.Parallel() - target, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { - return c.SendStatus(fiber.StatusTeapot) - }) + target, addr := createProxyTestServer( + func(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusTeapot) }, t, + ) - resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2000) + resp, err := target.Test(httptest.NewRequest("GET", "/", nil), 2000) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusTeapot, resp.StatusCode) @@ -81,7 +81,7 @@ func Test_Proxy(t *testing.T) { app.Use(Balancer(Config{Servers: []string{addr}})) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Host = addr resp, err = app.Test(req) utils.AssertEqual(t, nil, err) @@ -107,7 +107,7 @@ func Test_Proxy_Balancer_WithTlsConfig(t *testing.T) { }) addr := ln.Addr().String() - clientTLSConf := &tls.Config{InsecureSkipVerify: true} //nolint:gosec // We're in a test func, so this is fine + clientTLSConf := &tls.Config{InsecureSkipVerify: true} // disable certificate verification in Balancer app.Use(Balancer(Config{ @@ -128,9 +128,9 @@ func Test_Proxy_Balancer_WithTlsConfig(t *testing.T) { func Test_Proxy_Forward_WithTlsConfig_To_Http(t *testing.T) { t.Parallel() - _, targetAddr := createProxyTestServer(t, func(c *fiber.Ctx) error { + _, targetAddr := createProxyTestServer(func(c *fiber.Ctx) error { return c.SendString("hello from target") - }) + }, t) proxyServerTLSConf, _, err := tlstest.GetTLSConfigs() utils.AssertEqual(t, nil, err) @@ -164,13 +164,13 @@ func Test_Proxy_Forward(t *testing.T) { app := fiber.New() - _, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { - return c.SendString("forwarded") - }) + _, addr := createProxyTestServer( + func(c *fiber.Ctx) error { return c.SendString("forwarded") }, t, + ) app.Use(Forward("http://" + addr)) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) @@ -198,7 +198,7 @@ func Test_Proxy_Forward_WithTlsConfig(t *testing.T) { }) addr := ln.Addr().String() - clientTLSConf := &tls.Config{InsecureSkipVerify: true} //nolint:gosec // We're in a test func, so this is fine + clientTLSConf := &tls.Config{InsecureSkipVerify: true} // disable certificate verification WithTlsConfig(clientTLSConf) @@ -217,9 +217,9 @@ func Test_Proxy_Forward_WithTlsConfig(t *testing.T) { func Test_Proxy_Modify_Response(t *testing.T) { t.Parallel() - _, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { + _, addr := createProxyTestServer(func(c *fiber.Ctx) error { return c.Status(500).SendString("not modified") - }) + }, t) app := fiber.New() app.Use(Balancer(Config{ @@ -230,7 +230,7 @@ func Test_Proxy_Modify_Response(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) @@ -243,10 +243,10 @@ func Test_Proxy_Modify_Response(t *testing.T) { func Test_Proxy_Modify_Request(t *testing.T) { t.Parallel() - _, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { + _, addr := createProxyTestServer(func(c *fiber.Ctx) error { b := c.Request().Body() return c.SendString(string(b)) - }) + }, t) app := fiber.New() app.Use(Balancer(Config{ @@ -257,7 +257,7 @@ func Test_Proxy_Modify_Request(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) @@ -270,10 +270,10 @@ func Test_Proxy_Modify_Request(t *testing.T) { func Test_Proxy_Timeout_Slow_Server(t *testing.T) { t.Parallel() - _, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { + _, addr := createProxyTestServer(func(c *fiber.Ctx) error { time.Sleep(2 * time.Second) return c.SendString("fiber is awesome") - }) + }, t) app := fiber.New() app.Use(Balancer(Config{ @@ -281,7 +281,7 @@ func Test_Proxy_Timeout_Slow_Server(t *testing.T) { Timeout: 3 * time.Second, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 5000) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil), 5000) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) @@ -294,10 +294,10 @@ func Test_Proxy_Timeout_Slow_Server(t *testing.T) { func Test_Proxy_With_Timeout(t *testing.T) { t.Parallel() - _, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { + _, addr := createProxyTestServer(func(c *fiber.Ctx) error { time.Sleep(1 * time.Second) return c.SendString("fiber is awesome") - }) + }, t) app := fiber.New() app.Use(Balancer(Config{ @@ -305,7 +305,7 @@ func Test_Proxy_With_Timeout(t *testing.T) { Timeout: 100 * time.Millisecond, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2000) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil), 2000) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusInternalServerError, resp.StatusCode) @@ -318,16 +318,16 @@ func Test_Proxy_With_Timeout(t *testing.T) { func Test_Proxy_Buffer_Size_Response(t *testing.T) { t.Parallel() - _, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { + _, addr := createProxyTestServer(func(c *fiber.Ctx) error { long := strings.Join(make([]string, 5000), "-") c.Set("Very-Long-Header", long) return c.SendString("ok") - }) + }, t) app := fiber.New() app.Use(Balancer(Config{Servers: []string{addr}})) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusInternalServerError, resp.StatusCode) @@ -337,7 +337,7 @@ func Test_Proxy_Buffer_Size_Response(t *testing.T) { ReadBufferSize: 1024 * 8, })) - resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err = app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) } @@ -357,9 +357,9 @@ func Test_Proxy_Do_RestoreOriginalURL(t *testing.T) { utils.AssertEqual(t, originalURL, c.OriginalURL()) return c.SendString("ok") }) - _, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil)) + _, err1 := app.Test(httptest.NewRequest("GET", "/test", nil)) // This test requires multiple requests due to zero allocation used in fiber - _, err2 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil)) + _, err2 := app.Test(httptest.NewRequest("GET", "/test", nil)) utils.AssertEqual(t, nil, err1) utils.AssertEqual(t, nil, err2) @@ -369,9 +369,9 @@ func Test_Proxy_Do_RestoreOriginalURL(t *testing.T) { func Test_Proxy_Do_HTTP_Prefix_URL(t *testing.T) { t.Parallel() - _, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { + _, addr := createProxyTestServer(func(c *fiber.Ctx) error { return c.SendString("hello world") - }) + }, t) app := fiber.New(fiber.Config{DisableStartupMessage: true}) app.Get("/*", func(c *fiber.Ctx) error { @@ -386,7 +386,7 @@ func Test_Proxy_Do_HTTP_Prefix_URL(t *testing.T) { return nil }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/http://"+addr, nil)) + resp, err := app.Test(httptest.NewRequest(http.MethodGet, "/http://"+addr, nil)) utils.AssertEqual(t, nil, err) s, err := io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) @@ -431,8 +431,9 @@ func Test_Proxy_Forward_Local_Client(t *testing.T) { app.Use(Forward("http://"+addr+"/test_local_client", &fasthttp.Client{ NoDefaultUserAgentHeader: true, DisablePathNormalizing: true, - - Dial: fasthttp.Dial, + Dial: func(addr string) (net.Conn, error) { + return fasthttp.Dial(addr) + }, })) go func() { utils.AssertEqual(t, nil, app.Listener(ln)) }() @@ -446,11 +447,11 @@ func Test_Proxy_Forward_Local_Client(t *testing.T) { func Test_ProxyBalancer_Custom_Client(t *testing.T) { t.Parallel() - target, addr := createProxyTestServer(t, func(c *fiber.Ctx) error { - return c.SendStatus(fiber.StatusTeapot) - }) + target, addr := createProxyTestServer( + func(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusTeapot) }, t, + ) - resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2000) + resp, err := target.Test(httptest.NewRequest("GET", "/", nil), 2000) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusTeapot, resp.StatusCode) @@ -467,7 +468,7 @@ func Test_ProxyBalancer_Custom_Client(t *testing.T) { Timeout: time.Second, }})) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Host = addr resp, err = app.Test(req) utils.AssertEqual(t, nil, err) diff --git a/middleware/recover/config.go b/middleware/recover/config.go index 56b805d2e0..8e372a5aec 100644 --- a/middleware/recover/config.go +++ b/middleware/recover/config.go @@ -1,4 +1,4 @@ -package recover //nolint:predeclared // TODO: Rename to some non-builtin +package recover import ( "github.com/gofiber/fiber/v2" @@ -23,8 +23,6 @@ type Config struct { } // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, EnableStackTrace: false, diff --git a/middleware/recover/recover.go b/middleware/recover/recover.go index 252d8be757..5d77d6d082 100644 --- a/middleware/recover/recover.go +++ b/middleware/recover/recover.go @@ -1,4 +1,4 @@ -package recover //nolint:predeclared // TODO: Rename to some non-builtin +package recover import ( "fmt" @@ -9,7 +9,7 @@ import ( ) func defaultStackTraceHandler(_ *fiber.Ctx, e interface{}) { - _, _ = os.Stderr.WriteString(fmt.Sprintf("panic: %v\n%s\n", e, debug.Stack())) //nolint:errcheck // This will never fail + _, _ = os.Stderr.WriteString(fmt.Sprintf("panic: %v\n%s\n", e, debug.Stack())) } // New creates a new middleware handler @@ -18,7 +18,7 @@ func New(config ...Config) fiber.Handler { cfg := configDefault(config...) // Return new handler - return func(c *fiber.Ctx) (err error) { //nolint:nonamedreturns // Uses recover() to overwrite the error + return func(c *fiber.Ctx) (err error) { // Don't execute middleware if Next returns true if cfg.Next != nil && cfg.Next(c) { return c.Next() diff --git a/middleware/recover/recover_test.go b/middleware/recover/recover_test.go index 82e34b63ef..16bf164c12 100644 --- a/middleware/recover/recover_test.go +++ b/middleware/recover/recover_test.go @@ -1,4 +1,4 @@ -package recover //nolint:predeclared // TODO: Rename to some non-builtin +package recover import ( "net/http/httptest" @@ -24,7 +24,7 @@ func Test_Recover(t *testing.T) { panic("Hi, I'm an error!") }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/panic", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/panic", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusTeapot, resp.StatusCode) } @@ -39,7 +39,7 @@ func Test_Recover_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) } @@ -55,7 +55,7 @@ func Test_Recover_EnableStackTrace(t *testing.T) { panic("Hi, I'm an error!") }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/panic", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/panic", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusInternalServerError, resp.StatusCode) } diff --git a/middleware/requestid/config.go b/middleware/requestid/config.go index ca27b47f75..b3b605e590 100644 --- a/middleware/requestid/config.go +++ b/middleware/requestid/config.go @@ -33,8 +33,6 @@ type Config struct { // It uses a fast UUID generator which will expose the number of // requests made to the server. To conceal this value for better // privacy, use the "utils.UUIDv4" generator. -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ Next: nil, Header: fiber.HeaderXRequestID, diff --git a/middleware/requestid/requestid_test.go b/middleware/requestid/requestid_test.go index 451e96b4b2..eddafff01b 100644 --- a/middleware/requestid/requestid_test.go +++ b/middleware/requestid/requestid_test.go @@ -19,14 +19,14 @@ func Test_RequestID(t *testing.T) { return c.SendString("Hello, World 👋!") }) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) reqid := resp.Header.Get(fiber.HeaderXRequestID) utils.AssertEqual(t, 36, len(reqid)) - req := httptest.NewRequest(fiber.MethodGet, "/", nil) + req := httptest.NewRequest("GET", "/", nil) req.Header.Add(fiber.HeaderXRequestID, reqid) resp, err = app.Test(req) @@ -45,7 +45,7 @@ func Test_RequestID_Next(t *testing.T) { }, })) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, resp.Header.Get(fiber.HeaderXRequestID), "") utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) @@ -54,13 +54,13 @@ func Test_RequestID_Next(t *testing.T) { // go test -run Test_RequestID_Locals func Test_RequestID_Locals(t *testing.T) { t.Parallel() - reqID := "ThisIsARequestId" + reqId := "ThisIsARequestId" ctxKey := "ThisIsAContextKey" app := fiber.New() app.Use(New(Config{ Generator: func() string { - return reqID + return reqId }, ContextKey: ctxKey, })) @@ -68,11 +68,11 @@ func Test_RequestID_Locals(t *testing.T) { var ctxVal string app.Use(func(c *fiber.Ctx) error { - ctxVal = c.Locals(ctxKey).(string) //nolint:forcetypeassert,errcheck // We always store a string in here + ctxVal = c.Locals(ctxKey).(string) return c.Next() }) - _, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + _, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) - utils.AssertEqual(t, reqID, ctxVal) + utils.AssertEqual(t, reqId, ctxVal) } diff --git a/middleware/session/README.md b/middleware/session/README.md index 5e46cb1a6f..32d8c1eda3 100644 --- a/middleware/session/README.md +++ b/middleware/session/README.md @@ -32,7 +32,7 @@ func (s *Session) Save() error func (s *Session) Fresh() bool func (s *Session) ID() string func (s *Session) Keys() []string -func (s *Session) SetExpiry(time.Duration) +func (s *Session) SetExpiry(time.Duration) ``` **⚠ _Storing `interface{}` values are limited to built-ins Go types_** @@ -148,7 +148,7 @@ type Config struct { // Optional. Default value utils.UUID KeyGenerator func() string - // Deprecated: Please use KeyLookup + // Deprecated, please use KeyLookup CookieName string // Source defines where to obtain the session id diff --git a/middleware/session/config.go b/middleware/session/config.go index c7c8662704..ad08c8935e 100644 --- a/middleware/session/config.go +++ b/middleware/session/config.go @@ -2,7 +2,6 @@ package session import ( "fmt" - "log" "strings" "time" @@ -50,7 +49,7 @@ type Config struct { // Optional. Default value utils.UUIDv4 KeyGenerator func() string - // Deprecated: Please use KeyLookup + // Deprecated, please use KeyLookup CookieName string // Source defines where to obtain the session id @@ -69,10 +68,8 @@ const ( ) // ConfigDefault is the default config -// -//nolint:gochecknoglobals // Using a global var is fine here var ConfigDefault = Config{ - Expiration: 24 * time.Hour, //nolint:gomnd // No magic number, just the default config + Expiration: 24 * time.Hour, KeyLookup: "cookie:session_id", KeyGenerator: utils.UUIDv4, source: "cookie", @@ -94,7 +91,7 @@ func configDefault(config ...Config) Config { cfg.Expiration = ConfigDefault.Expiration } if cfg.CookieName != "" { - log.Printf("[session] CookieName is deprecated, please use KeyLookup\n") + fmt.Println("[session] CookieName is deprecated, please use KeyLookup") cfg.KeyLookup = fmt.Sprintf("cookie:%s", cfg.CookieName) } if cfg.KeyLookup == "" { @@ -105,8 +102,7 @@ func configDefault(config ...Config) Config { } selectors := strings.Split(cfg.KeyLookup, ":") - const numSelectors = 2 - if len(selectors) != numSelectors { + if len(selectors) != 2 { panic("[session] KeyLookup must in the form of :") } switch Source(selectors[0]) { diff --git a/middleware/session/data.go b/middleware/session/data.go index f213b252f5..7c8f793103 100644 --- a/middleware/session/data.go +++ b/middleware/session/data.go @@ -13,7 +13,6 @@ type data struct { Data map[string]interface{} } -//nolint:gochecknoglobals // TODO: Do not use a global var here var dataPool = sync.Pool{ New: func() interface{} { d := new(data) @@ -23,7 +22,7 @@ var dataPool = sync.Pool{ } func acquireData() *data { - return dataPool.Get().(*data) //nolint:forcetypeassert // We store nothing else in the pool + return dataPool.Get().(*data) } func (d *data) Reset() { diff --git a/middleware/session/session.go b/middleware/session/session.go index f18abbf8b2..33be2a1a7d 100644 --- a/middleware/session/session.go +++ b/middleware/session/session.go @@ -3,13 +3,11 @@ package session import ( "bytes" "encoding/gob" - "fmt" "sync" "time" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -23,7 +21,6 @@ type Session struct { exp time.Duration // expiration of this session } -//nolint:gochecknoglobals // TODO: Do not use a global var here var sessionPool = sync.Pool{ New: func() interface{} { return new(Session) @@ -31,7 +28,7 @@ var sessionPool = sync.Pool{ } func acquireSession() *Session { - s := sessionPool.Get().(*Session) //nolint:forcetypeassert,errcheck // We store nothing else in the pool + s := sessionPool.Get().(*Session) if s.data == nil { s.data = acquireData() } @@ -156,7 +153,7 @@ func (s *Session) Save() error { encCache := gob.NewEncoder(s.byteBuffer) err := encCache.Encode(&s.data.Data) if err != nil { - return fmt.Errorf("failed to encode data: %w", err) + return err } // copy the data in buffer diff --git a/middleware/session/session_test.go b/middleware/session/session_test.go index 20d683f458..489ea46edf 100644 --- a/middleware/session/session_test.go +++ b/middleware/session/session_test.go @@ -7,7 +7,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/internal/storage/memory" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -95,8 +94,6 @@ func Test_Session(t *testing.T) { } // go test -run Test_Session_Types -// -//nolint:forcetypeassert // TODO: Do not force-type assert func Test_Session_Types(t *testing.T) { t.Parallel() @@ -130,27 +127,25 @@ func Test_Session_Types(t *testing.T) { Name: "John", } // set value - var ( - vbool = true - vstring = "str" - vint = 13 - vint8 int8 = 13 - vint16 int16 = 13 - vint32 int32 = 13 - vint64 int64 = 13 - vuint uint = 13 - vuint8 uint8 = 13 - vuint16 uint16 = 13 - vuint32 uint32 = 13 - vuint64 uint64 = 13 - vuintptr uintptr = 13 - vbyte byte = 'k' - vrune = 'k' - vfloat32 float32 = 13 - vfloat64 float64 = 13 - vcomplex64 complex64 = 13 - vcomplex128 complex128 = 13 - ) + var vbool = true + var vstring = "str" + var vint = 13 + var vint8 int8 = 13 + var vint16 int16 = 13 + var vint32 int32 = 13 + var vint64 int64 = 13 + var vuint uint = 13 + var vuint8 uint8 = 13 + var vuint16 uint16 = 13 + var vuint32 uint32 = 13 + var vuint64 uint64 = 13 + var vuintptr uintptr = 13 + var vbyte byte = 'k' + var vrune rune = 'k' + var vfloat32 float32 = 13 + var vfloat64 float64 = 13 + var vcomplex64 complex64 = 13 + var vcomplex128 complex128 = 13 sess.Set("vuser", vuser) sess.Set("vbool", vbool) sess.Set("vstring", vstring) @@ -217,8 +212,7 @@ func Test_Session_Store_Reset(t *testing.T) { defer app.ReleaseCtx(ctx) // get session - sess, err := store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ := store.Get(ctx) // make sure its new utils.AssertEqual(t, true, sess.Fresh()) // set value & save @@ -230,8 +224,7 @@ func Test_Session_Store_Reset(t *testing.T) { utils.AssertEqual(t, nil, store.Reset()) // make sure the session is recreated - sess, err = store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ = store.Get(ctx) utils.AssertEqual(t, true, sess.Fresh()) utils.AssertEqual(t, nil, sess.Get("hello")) } @@ -249,13 +242,12 @@ func Test_Session_Save(t *testing.T) { ctx := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(ctx) // get session - sess, err := store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ := store.Get(ctx) // set value sess.Set("name", "john") // save session - err = sess.Save() + err := sess.Save() utils.AssertEqual(t, nil, err) }) @@ -270,13 +262,12 @@ func Test_Session_Save(t *testing.T) { ctx := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(ctx) // get session - sess, err := store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ := store.Get(ctx) // set value sess.Set("name", "john") // save session - err = sess.Save() + err := sess.Save() utils.AssertEqual(t, nil, err) utils.AssertEqual(t, store.getSessionID(ctx), string(ctx.Response().Header.Peek(store.sessionName))) utils.AssertEqual(t, store.getSessionID(ctx), string(ctx.Request().Header.Peek(store.sessionName))) @@ -296,8 +287,7 @@ func Test_Session_Save_Expiration(t *testing.T) { ctx := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(ctx) // get session - sess, err := store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ := store.Get(ctx) // set value sess.Set("name", "john") @@ -305,20 +295,18 @@ func Test_Session_Save_Expiration(t *testing.T) { sess.SetExpiry(time.Second * 5) // save session - err = sess.Save() + err := sess.Save() utils.AssertEqual(t, nil, err) // here you need to get the old session yet - sess, err = store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ = store.Get(ctx) utils.AssertEqual(t, "john", sess.Get("name")) // just to make sure the session has been expired time.Sleep(time.Second * 5) // here you should get a new session - sess, err = store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ = store.Get(ctx) utils.AssertEqual(t, nil, sess.Get("name")) }) } @@ -337,8 +325,7 @@ func Test_Session_Reset(t *testing.T) { ctx := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(ctx) // get session - sess, err := store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ := store.Get(ctx) sess.Set("name", "fenny") utils.AssertEqual(t, nil, sess.Destroy()) @@ -358,16 +345,14 @@ func Test_Session_Reset(t *testing.T) { ctx := app.AcquireCtx(&fasthttp.RequestCtx{}) defer app.ReleaseCtx(ctx) // get session - sess, err := store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ := store.Get(ctx) // set value & save sess.Set("name", "fenny") utils.AssertEqual(t, nil, sess.Save()) - sess, err = store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ = store.Get(ctx) - err = sess.Destroy() + err := sess.Destroy() utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "", string(ctx.Response().Header.Peek(store.sessionName))) utils.AssertEqual(t, "", string(ctx.Request().Header.Peek(store.sessionName))) @@ -398,8 +383,7 @@ func Test_Session_Cookie(t *testing.T) { defer app.ReleaseCtx(ctx) // get session - sess, err := store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ := store.Get(ctx) utils.AssertEqual(t, nil, sess.Save()) // cookie should be set on Save ( even if empty data ) @@ -417,14 +401,12 @@ func Test_Session_Cookie_In_Response(t *testing.T) { defer app.ReleaseCtx(ctx) // get session - sess, err := store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ := store.Get(ctx) sess.Set("id", "1") utils.AssertEqual(t, true, sess.Fresh()) utils.AssertEqual(t, nil, sess.Save()) - sess, err = store.Get(ctx) - utils.AssertEqual(t, nil, err) + sess, _ = store.Get(ctx) sess.Set("name", "john") utils.AssertEqual(t, true, sess.Fresh()) @@ -515,7 +497,7 @@ func Benchmark_Session(b *testing.B) { b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { - sess, _ := store.Get(c) //nolint:errcheck // We're inside a benchmark + sess, _ := store.Get(c) sess.Set("john", "doe") err = sess.Save() } @@ -530,7 +512,7 @@ func Benchmark_Session(b *testing.B) { b.ReportAllocs() b.ResetTimer() for n := 0; n < b.N; n++ { - sess, _ := store.Get(c) //nolint:errcheck // We're inside a benchmark + sess, _ := store.Get(c) sess.Set("john", "doe") err = sess.Save() } diff --git a/middleware/session/store.go b/middleware/session/store.go index fd3b08d029..cc8a80a0cf 100644 --- a/middleware/session/store.go +++ b/middleware/session/store.go @@ -2,13 +2,11 @@ package session import ( "encoding/gob" - "fmt" "sync" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/internal/storage/memory" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -16,7 +14,6 @@ type Store struct { Config } -//nolint:gochecknoglobals // TODO: Do not use a global var here var mux sync.Mutex func New(config ...Config) *Store { @@ -34,7 +31,7 @@ func New(config ...Config) *Store { // RegisterType will allow you to encode/decode custom types // into any Storage provider -func (*Store) RegisterType(i interface{}) { +func (s *Store) RegisterType(i interface{}) { gob.Register(i) } @@ -73,11 +70,11 @@ func (s *Store) Get(c *fiber.Ctx) (*Session, error) { if raw != nil && err == nil { mux.Lock() defer mux.Unlock() - _, _ = sess.byteBuffer.Write(raw) //nolint:errcheck // This will never fail + _, _ = sess.byteBuffer.Write(raw) encCache := gob.NewDecoder(sess.byteBuffer) err := encCache.Decode(&sess.data.Data) if err != nil { - return nil, fmt.Errorf("failed to decode session data: %w", err) + return nil, err } } else if err != nil { return nil, err diff --git a/middleware/session/store_test.go b/middleware/session/store_test.go index c7e435f6ae..4c755c3290 100644 --- a/middleware/session/store_test.go +++ b/middleware/session/store_test.go @@ -6,7 +6,6 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) diff --git a/middleware/skip/skip.go b/middleware/skip/skip.go index de64601fda..616baf2dc3 100644 --- a/middleware/skip/skip.go +++ b/middleware/skip/skip.go @@ -1,8 +1,6 @@ package skip -import ( - "github.com/gofiber/fiber/v2" -) +import "github.com/gofiber/fiber/v2" // New creates a middleware handler which skips the wrapped handler // if the exclude predicate returns true. diff --git a/middleware/skip/skip_test.go b/middleware/skip/skip_test.go index 6d0925591a..cfbbec9d8d 100644 --- a/middleware/skip/skip_test.go +++ b/middleware/skip/skip_test.go @@ -17,7 +17,7 @@ func Test_Skip(t *testing.T) { app.Use(skip.New(errTeapotHandler, func(*fiber.Ctx) bool { return true })) app.Get("/", helloWorldHandler) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) } @@ -30,7 +30,7 @@ func Test_SkipFalse(t *testing.T) { app.Use(skip.New(errTeapotHandler, func(*fiber.Ctx) bool { return false })) app.Get("/", helloWorldHandler) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusTeapot, resp.StatusCode) } @@ -43,7 +43,7 @@ func Test_SkipNilFunc(t *testing.T) { app.Use(skip.New(errTeapotHandler, nil)) app.Get("/", helloWorldHandler) - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusTeapot, resp.StatusCode) } diff --git a/middleware/timeout/timeout_test.go b/middleware/timeout/timeout_test.go index 8498cb816d..aa60a3504c 100644 --- a/middleware/timeout/timeout_test.go +++ b/middleware/timeout/timeout_test.go @@ -18,8 +18,7 @@ func Test_Timeout(t *testing.T) { // fiber instance app := fiber.New() h := New(func(c *fiber.Ctx) error { - sleepTime, err := time.ParseDuration(c.Params("sleepTime") + "ms") - utils.AssertEqual(t, nil, err) + sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms") if err := sleepWithContext(c.UserContext(), sleepTime, context.DeadlineExceeded); err != nil { return fmt.Errorf("%w: l2 wrap", fmt.Errorf("%w: l1 wrap ", err)) } @@ -27,12 +26,12 @@ func Test_Timeout(t *testing.T) { }, 100*time.Millisecond) app.Get("/test/:sleepTime", h) testTimeout := func(timeoutStr string) { - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test/"+timeoutStr, nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/test/"+timeoutStr, nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusRequestTimeout, resp.StatusCode, "Status code") } testSucces := func(timeoutStr string) { - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test/"+timeoutStr, nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/test/"+timeoutStr, nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode, "Status code") } @@ -50,8 +49,7 @@ func Test_TimeoutWithCustomError(t *testing.T) { // fiber instance app := fiber.New() h := New(func(c *fiber.Ctx) error { - sleepTime, err := time.ParseDuration(c.Params("sleepTime") + "ms") - utils.AssertEqual(t, nil, err) + sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms") if err := sleepWithContext(c.UserContext(), sleepTime, ErrFooTimeOut); err != nil { return fmt.Errorf("%w: execution error", err) } @@ -59,12 +57,12 @@ func Test_TimeoutWithCustomError(t *testing.T) { }, 100*time.Millisecond, ErrFooTimeOut) app.Get("/test/:sleepTime", h) testTimeout := func(timeoutStr string) { - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test/"+timeoutStr, nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/test/"+timeoutStr, nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusRequestTimeout, resp.StatusCode, "Status code") } testSucces := func(timeoutStr string) { - resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test/"+timeoutStr, nil)) + resp, err := app.Test(httptest.NewRequest("GET", "/test/"+timeoutStr, nil)) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode, "Status code") } diff --git a/mount.go b/mount.go index 2becfef6bd..abb4a73930 100644 --- a/mount.go +++ b/mount.go @@ -120,6 +120,7 @@ func (app *App) appendSubAppLists(appList map[string]*App, parent ...string) { if len(subApp.mountFields.appList) > 1 { app.appendSubAppLists(subApp.mountFields.appList, prefix) } + } } diff --git a/mount_test.go b/mount_test.go index b70be3085c..580366e69d 100644 --- a/mount_test.go +++ b/mount_test.go @@ -2,7 +2,6 @@ // 🤖 Github Repository: https://github.com/gofiber/fiber // 📌 API Documentation: https://docs.gofiber.io -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package fiber import ( @@ -370,6 +369,7 @@ func Test_Ctx_Render_Mount_ParentOrSubHasViews(t *testing.T) { body, err = io.ReadAll(resp.Body) utils.AssertEqual(t, nil, err) utils.AssertEqual(t, "

I'm Bruh

", string(body)) + } func Test_Ctx_Render_MountGroup(t *testing.T) { diff --git a/path.go b/path.go index ba357328e8..2bc041d3d1 100644 --- a/path.go +++ b/path.go @@ -88,14 +88,12 @@ const ( ) // list of possible parameter and segment delimiter -// -//nolint:gochecknoglobals // TODO: Do not use a global var here var ( // slash has a special role, unlike the other parameters it must not be interpreted as a parameter routeDelimiter = []byte{slashDelimiter, '-', '.'} // list of greedy parameters greedyParameters = []byte{wildcardParam, plusParam} - // list of chars for the parameter recognizing + // 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, escapeChar}, routeDelimiter...) @@ -270,7 +268,7 @@ func findNextParamPosition(pattern string) int { } // analyseConstantPart find the end of the constant part and create the route segment -func (*routeParser) analyseConstantPart(pattern string, nextParamPosition int) (string, *routeSegment) { +func (routeParser *routeParser) analyseConstantPart(pattern string, nextParamPosition int) (string, *routeSegment) { // handle the constant part processedPart := pattern if nextParamPosition != -1 { @@ -299,12 +297,11 @@ func (routeParser *routeParser) analyseParameterPart(pattern string) (string, *r parameterConstraintStart := -1 parameterConstraintEnd := -1 // handle wildcard end - switch { - case isWildCard, isPlusParam: + if isWildCard || isPlusParam { parameterEndPosition = 0 - case parameterEndPosition == -1: + } else if parameterEndPosition == -1 { parameterEndPosition = len(pattern) - 1 - case !isInCharset(pattern[parameterEndPosition+1], parameterDelimiterChars): + } else if !isInCharset(pattern[parameterEndPosition+1], parameterDelimiterChars) { parameterEndPosition++ } @@ -341,7 +338,7 @@ func (routeParser *routeParser) analyseParameterPart(pattern string) (string, *r constraint.Data = splitNonEscaped(c[start+1:end], string(parameterConstraintDataSeparatorChars)) if len(constraint.Data) == 1 { constraint.Data[0] = RemoveEscapeChar(constraint.Data[0]) - } else if len(constraint.Data) == 2 { //nolint:gomnd // This is fine, we simply expect two parts + } else if len(constraint.Data) == 2 { constraint.Data[0] = RemoveEscapeChar(constraint.Data[0]) constraint.Data[1] = RemoveEscapeChar(constraint.Data[1]) } @@ -477,7 +474,7 @@ func splitNonEscaped(s, sep string) []string { } // getMatch parses the passed url and tries to match it against the route segments and determine the parameter positions -func (routeParser *routeParser) getMatch(detectionPath, path string, params *[maxParams]string, partialCheck bool) bool { //nolint: revive // Accepting a bool param is fine here +func (routeParser *routeParser) getMatch(detectionPath, path string, params *[maxParams]string, partialCheck bool) bool { var i, paramsIterator, partLen int for _, segment := range routeParser.segs { partLen = len(detectionPath) @@ -641,9 +638,9 @@ func getParamConstraintType(constraintPart string) TypeConstraint { default: return noConstraint } + } -//nolint:errcheck // TODO: Properly check _all_ errors in here, log them & immediately return func (c *Constraint) CheckConstraint(param string) bool { var err error var num int @@ -666,8 +663,6 @@ func (c *Constraint) CheckConstraint(param string) bool { // check constraints switch c.ID { - case noConstraint: - // Nothing to check case intConstraint: _, err = strconv.Atoi(param) case boolConstraint: diff --git a/path_test.go b/path_test.go index 62a421ed3a..656b82e12a 100644 --- a/path_test.go +++ b/path_test.go @@ -1119,6 +1119,7 @@ func Benchmark_Path_matchParams(t *testing.B) { utils.AssertEqual(t, c.params[0:len(c.params)-1], ctxParams[0:len(c.params)-1], fmt.Sprintf("route: '%s', url: '%s'", r, c.url)) } }) + } } benchCase("/api/:param/fixedEnd", []testparams{ @@ -1347,6 +1348,7 @@ func Benchmark_RoutePatternMatch(t *testing.B) { } utils.AssertEqual(t, c.match, matchRes, fmt.Sprintf("route: '%s', url: '%s'", pattern, c.url)) }) + } } benchCase("/api/:param/fixedEnd", []testparams{ diff --git a/prefork.go b/prefork.go index 7eebd50636..b3049abc60 100644 --- a/prefork.go +++ b/prefork.go @@ -2,15 +2,13 @@ package fiber import ( "crypto/tls" - "errors" "fmt" - "log" + "net" "os" "os/exec" "runtime" "strconv" "strings" - "sync/atomic" "time" "github.com/valyala/fasthttp/reuseport" @@ -21,11 +19,8 @@ const ( envPreforkChildVal = "1" ) -//nolint:gochecknoglobals // TODO: Do not use global vars here -var ( - testPreforkMaster = false - testOnPrefork = false -) +var testPreforkMaster = false +var testOnPrefork = false // IsChild determines if the current process is a child of Prefork func IsChild() bool { @@ -33,20 +28,19 @@ func IsChild() bool { } // prefork manages child processes to make use of the OS REUSEPORT or REUSEADDR feature -func (app *App) prefork(network, addr string, tlsConfig *tls.Config) error { +func (app *App) prefork(network, addr string, tlsConfig *tls.Config) (err error) { // 👶 child process 👶 if IsChild() { // use 1 cpu core per child process runtime.GOMAXPROCS(1) + var ln net.Listener // Linux will use SO_REUSEPORT and Windows falls back to SO_REUSEADDR // Only tcp4 or tcp6 is supported when preforking, both are not supported - ln, err := reuseport.Listen(network, addr) - if err != nil { + if ln, err = reuseport.Listen(network, addr); err != nil { if !app.config.DisableStartupMessage { - const sleepDuration = 100 * time.Millisecond - time.Sleep(sleepDuration) // avoid colliding with startup message + time.Sleep(100 * time.Millisecond) // avoid colliding with startup message } - return fmt.Errorf("prefork: %w", err) + return fmt.Errorf("prefork: %v", err) } // wrap a tls config around the listener if provided if tlsConfig != nil { @@ -76,11 +70,7 @@ func (app *App) prefork(network, addr string, tlsConfig *tls.Config) error { // kill child procs when master exits defer func() { for _, proc := range childs { - if err := proc.Process.Kill(); err != nil { - if !errors.Is(err, os.ErrProcessDone) { - log.Printf("prefork: failed to kill child: %v\n", err) - } - } + _ = proc.Process.Kill() } }() @@ -89,7 +79,8 @@ func (app *App) prefork(network, addr string, tlsConfig *tls.Config) error { // launch child procs for i := 0; i < max; i++ { - cmd := exec.Command(os.Args[0], os.Args[1:]...) //nolint:gosec // It's fine to launch the same process again + /* #nosec G204 */ + cmd := exec.Command(os.Args[0], os.Args[1:]...) // #nosec G204 if testPreforkMaster { // When test prefork master, // just start the child process with a dummy cmd, @@ -103,8 +94,8 @@ func (app *App) prefork(network, addr string, tlsConfig *tls.Config) error { 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: %w", err) + if err = cmd.Start(); err != nil { + return fmt.Errorf("failed to start a child prefork process, error: %v", err) } // store child process @@ -143,34 +134,27 @@ func watchMaster() { // and waits for it to exit p, err := os.FindProcess(os.Getppid()) if err == nil { - _, _ = p.Wait() //nolint:errcheck // It is fine to ignore the error here + _, _ = p.Wait() } - os.Exit(1) //nolint:revive // Calling os.Exit is fine here in the prefork + os.Exit(1) } // if it is equal to 1 (init process ID), // it indicates that the master process has exited - const watchInterval = 500 * time.Millisecond - for range time.NewTicker(watchInterval).C { + for range time.NewTicker(time.Millisecond * 500).C { if os.Getppid() == 1 { - os.Exit(1) //nolint:revive // Calling os.Exit is fine here in the prefork + os.Exit(1) } } } -//nolint:gochecknoglobals // TODO: Do not use global vars here -var ( - dummyPid = 1 - dummyChildCmd atomic.Value -) +var dummyChildCmd = "go" // dummyCmd is for internal prefork testing func dummyCmd() *exec.Cmd { - command := "go" - if storeCommand := dummyChildCmd.Load(); storeCommand != nil && storeCommand != "" { - command = storeCommand.(string) //nolint:forcetypeassert,errcheck // We always store a string in here - } if runtime.GOOS == "windows" { - return exec.Command("cmd", "/C", command, "version") + return exec.Command("cmd", "/C", dummyChildCmd, "version") } - return exec.Command(command, "version") + return exec.Command(dummyChildCmd, "version") } + +var dummyPid = 1 diff --git a/prefork_test.go b/prefork_test.go index 506244a263..4842774f26 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -38,7 +38,6 @@ func Test_App_Prefork_Child_Process(t *testing.T) { if err != nil { utils.AssertEqual(t, nil, err) } - //nolint:gosec // We're in a test so using old ciphers is fine config := &tls.Config{Certificates: []tls.Certificate{cer}} go func() { @@ -62,12 +61,10 @@ func Test_App_Prefork_Master_Process(t *testing.T) { utils.AssertEqual(t, nil, app.prefork(NetworkTCP4, ":3000", nil)) - dummyChildCmd.Store("invalid") + dummyChildCmd = "invalid" err := app.prefork(NetworkTCP4, "127.0.0.1:", nil) utils.AssertEqual(t, false, err == nil) - - dummyChildCmd.Store("") } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { diff --git a/router.go b/router.go index ce27583955..84ff606443 100644 --- a/router.go +++ b/router.go @@ -13,7 +13,6 @@ import ( "time" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) @@ -56,15 +55,14 @@ type Route struct { group *Group // Group instance. used for routes in groups // Public fields - Method string `json:"method"` // HTTP method - Name string `json:"name"` // Route's name - //nolint:revive // Having both a Path (uppercase) and a path (lowercase) is fine + Method string `json:"method"` // HTTP method + Name string `json:"name"` // Route's name 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(detectionPath, path string, params *[maxParams]string) bool { +func (r *Route) match(detectionPath, path string, params *[maxParams]string) (match bool) { // root detectionPath check if r.root && detectionPath == "/" { return true @@ -99,7 +97,7 @@ func (r *Route) match(detectionPath, path string, params *[maxParams]string) boo return false } -func (app *App) next(c *Ctx) (bool, error) { +func (app *App) next(c *Ctx) (match bool, err error) { // Get stack length tree, ok := app.treeStack[c.methodINT][c.treePath] if !ok { @@ -116,9 +114,10 @@ func (app *App) next(c *Ctx) (bool, error) { route := tree[c.indexRoute] // Check if it matches the request path - match := route.match(c.detectionPath, c.path, &c.values) + match = route.match(c.detectionPath, c.path, &c.values) + + // No match, next route if !match { - // No match, next route continue } // Pass route reference and param values @@ -131,28 +130,29 @@ func (app *App) next(c *Ctx) (bool, error) { // Execute first handler of route c.indexHandler = 0 - err := route.Handlers[0](c) + err = route.Handlers[0](c) return match, err // Stop scanning the stack } // If c.Next() does not match, return 404 - err := NewError(StatusNotFound, "Cannot "+c.method+" "+c.pathOriginal) + err = NewError(StatusNotFound, "Cannot "+c.method+" "+c.pathOriginal) + + // If no match, scan stack again if other methods match the request + // Moved from app.handler because middleware may break the route chain if !c.matched && app.methodExist(c) { - // If no match, scan stack again if other methods match the request - // Moved from app.handler because middleware may break the route chain err = ErrMethodNotAllowed } - return false, err + return } -func (app *App) handler(rctx *fasthttp.RequestCtx) { //revive:disable-line:confusing-naming // Having both a Handler() (uppercase) and a handler() (lowercase) is fine. TODO: Use nolint:revive directive instead. See https://github.com/golangci/golangci-lint/issues/3476 +func (app *App) handler(rctx *fasthttp.RequestCtx) { // Acquire Ctx with fasthttp request from pool c := app.AcquireCtx(rctx) - defer app.ReleaseCtx(c) // handle invalid http method directly if c.methodINT == -1 { - _ = c.Status(StatusBadRequest).SendString("Invalid http method") //nolint:errcheck // It is fine to ignore the error here + _ = c.Status(StatusBadRequest).SendString("Invalid http method") + app.ReleaseCtx(c) return } @@ -160,14 +160,16 @@ func (app *App) handler(rctx *fasthttp.RequestCtx) { //revive:disable-line:confu match, err := app.next(c) if err != nil { if catch := c.app.ErrorHandler(c, err); catch != nil { - _ = c.SendStatus(StatusInternalServerError) //nolint:errcheck // It is fine to ignore the error here + _ = c.SendStatus(StatusInternalServerError) } - // TODO: Do we need to return here? } // Generate ETag if enabled if match && app.config.ETag { setETag(c, false) } + + // Release Ctx + app.ReleaseCtx(c) } func (app *App) addPrefixToRoute(prefix string, route *Route) *Route { @@ -191,7 +193,7 @@ func (app *App) addPrefixToRoute(prefix string, route *Route) *Route { return route } -func (*App) copyRoute(route *Route) *Route { +func (app *App) copyRoute(route *Route) *Route { return &Route{ // Router booleans use: route.use, @@ -325,7 +327,6 @@ func (app *App) registerStatic(prefix, root string, config ...Static) Router { prefixLen-- prefix = prefix[:prefixLen] } - const cacheDuration = 10 * time.Second // Fileserver settings fs := &fasthttp.FS{ Root: root, @@ -334,7 +335,7 @@ func (app *App) registerStatic(prefix, root string, config ...Static) Router { AcceptByteRange: false, Compress: false, CompressedFileSuffix: app.config.CompressedFileSuffix, - CacheDuration: cacheDuration, + CacheDuration: 10 * time.Second, IndexNames: []string{"index.html"}, PathRewrite: func(fctx *fasthttp.RequestCtx) []byte { path := fctx.Path() diff --git a/router_test.go b/router_test.go index 0fbb7c8f46..26407ce10e 100644 --- a/router_test.go +++ b/router_test.go @@ -2,7 +2,6 @@ // 📃 Github Repository: https://github.com/gofiber/fiber // 📌 API Documentation: https://docs.gofiber.io -//nolint:bodyclose // Much easier to just ignore memory leaks in tests package fiber import ( @@ -16,14 +15,11 @@ import ( "testing" "github.com/gofiber/fiber/v2/utils" - "github.com/valyala/fasthttp" ) -//nolint:gochecknoglobals // TODO: Do not use a global var here -var routesFixture routeJSON +var routesFixture = routeJSON{} -//nolint:gochecknoinits // init() is used to populate a global struct from a JSON file func init() { dat, err := os.ReadFile("./.github/testdata/testRoutes.json") if err != nil { @@ -583,7 +579,7 @@ func Benchmark_Router_Chain(b *testing.B) { c := &fasthttp.RequestCtx{} - c.Request.Header.SetMethod(MethodGet) + c.Request.Header.SetMethod("GET") c.URI().SetPath("/") b.ResetTimer() for n := 0; n < b.N; n++ { @@ -607,7 +603,7 @@ func Benchmark_Router_WithCompression(b *testing.B) { appHandler := app.Handler() c := &fasthttp.RequestCtx{} - c.Request.Header.SetMethod(MethodGet) + c.Request.Header.SetMethod("GET") c.URI().SetPath("/") b.ResetTimer() for n := 0; n < b.N; n++ { @@ -833,6 +829,6 @@ type testRoute struct { } type routeJSON struct { - TestRoutes []testRoute `json:"test_routes"` - GithubAPI []testRoute `json:"github_api"` + TestRoutes []testRoute `json:"testRoutes"` + GithubAPI []testRoute `json:"githubAPI"` } diff --git a/utils/assertions.go b/utils/assertions.go index 2cc4cac21a..ec9a119c0f 100644 --- a/utils/assertions.go +++ b/utils/assertions.go @@ -16,7 +16,7 @@ import ( ) // AssertEqual checks if values are equal -func AssertEqual(tb testing.TB, expected, actual interface{}, description ...string) { //nolint:thelper // TODO: Verify if tb can be nil +func AssertEqual(tb testing.TB, expected, actual interface{}, description ...string) { if tb != nil { tb.Helper() } @@ -43,15 +43,14 @@ func AssertEqual(tb testing.TB, expected, actual interface{}, description ...str _, file, line, _ := runtime.Caller(1) var buf bytes.Buffer - const pad = 5 - w := tabwriter.NewWriter(&buf, 0, 0, pad, ' ', 0) - _, _ = fmt.Fprintf(w, "\nTest:\t%s", testName) - _, _ = fmt.Fprintf(w, "\nTrace:\t%s:%d", filepath.Base(file), line) + 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) if len(description) > 0 { - _, _ = fmt.Fprintf(w, "\nDescription:\t%s", description[0]) + fmt.Fprintf(w, "\nDescription:\t%s", description[0]) } - _, _ = fmt.Fprintf(w, "\nExpect:\t%v\t(%s)", expected, aType) - _, _ = fmt.Fprintf(w, "\nResult:\t%v\t(%s)", actual, bType) + fmt.Fprintf(w, "\nExpect:\t%v\t(%s)", expected, aType) + fmt.Fprintf(w, "\nResult:\t%v\t(%s)", actual, bType) result := "" if err := w.Flush(); err != nil { @@ -63,6 +62,6 @@ func AssertEqual(tb testing.TB, expected, actual interface{}, description ...str if tb != nil { tb.Fatal(result) } else { - log.Fatal(result) //nolint:revive // tb might be nil, so we need a fallback + log.Fatal(result) } } diff --git a/utils/assertions_test.go b/utils/assertions_test.go index d1e7f08732..d2d32dc0cf 100644 --- a/utils/assertions_test.go +++ b/utils/assertions_test.go @@ -4,9 +4,7 @@ package utils -import ( - "testing" -) +import "testing" func Test_AssertEqual(t *testing.T) { t.Parallel() diff --git a/utils/common.go b/utils/common.go index 1789a239b0..b0f4d76625 100644 --- a/utils/common.go +++ b/utils/common.go @@ -31,11 +31,6 @@ const ( // github.com/rogpeppe/fastuuid // All rights reserved. -const ( - emptyUUID = "00000000-0000-0000-0000-000000000000" -) - -//nolint:gochecknoglobals // TODO: Do not use a global var here var ( uuidSeed [24]byte uuidCounter uint64 @@ -44,8 +39,6 @@ var ( ) // UUID generates an universally unique identifier (UUID) -// -//nolint:gomnd // Those are not random numbers, it's the fastuuid algorithm func UUID() string { // Setup seed & counter once uuidSetup.Do(func() { @@ -55,7 +48,7 @@ func UUID() string { uuidCounter = binary.LittleEndian.Uint64(uuidSeed[:8]) }) if atomic.LoadUint64(&uuidCounter) <= 0 { - return emptyUUID + return "00000000-0000-0000-0000-000000000000" } // first 8 bytes differ, taking a slice of the first 16 bytes x := atomic.AddUint64(&uuidCounter, 1) @@ -154,8 +147,7 @@ func ConvertToBytes(humanReadableString string) int { // convert multiplier char to lowercase and check if exists in units slice index := bytes.IndexByte(unitsSlice, toLowerTable[humanReadableString[unitPrefixPos]]) if index != -1 { - const bytesPerKB = 1000 - size *= math.Pow(bytesPerKB, float64(index+1)) + size *= math.Pow(1000, float64(index+1)) } } diff --git a/utils/common_test.go b/utils/common_test.go index 1b0884fc86..b4b2c61cf9 100644 --- a/utils/common_test.go +++ b/utils/common_test.go @@ -24,7 +24,7 @@ func Test_UUID(t *testing.T) { t.Parallel() res := UUID() AssertEqual(t, 36, len(res)) - AssertEqual(t, true, res != emptyUUID) + AssertEqual(t, true, res != "00000000-0000-0000-0000-000000000000") } func Test_UUID_Concurrency(t *testing.T) { @@ -49,7 +49,7 @@ func Test_UUIDv4(t *testing.T) { t.Parallel() res := UUIDv4() AssertEqual(t, 36, len(res)) - AssertEqual(t, true, res != emptyUUID) + AssertEqual(t, true, res != "00000000-0000-0000-0000-000000000000") } func Test_UUIDv4_Concurrency(t *testing.T) { @@ -82,8 +82,7 @@ func Benchmark_UUID(b *testing.B) { }) b.Run("default", func(b *testing.B) { rnd := make([]byte, 16) - _, err := rand.Read(rnd) - AssertEqual(b, nil, err) + _, _ = rand.Read(rnd) for n := 0; n < b.N; n++ { res = fmt.Sprintf("%x-%x-%x-%x-%x", rnd[0:4], rnd[4:6], rnd[6:8], rnd[8:10], rnd[10:]) } diff --git a/utils/convert.go b/utils/convert.go index 4a91ead995..d1d3f52034 100644 --- a/utils/convert.go +++ b/utils/convert.go @@ -15,17 +15,15 @@ import ( const MaxStringLen = 0x7fff0000 // Maximum string length for UnsafeBytes. (decimal: 2147418112) +// #nosec G103 // UnsafeString returns a string pointer without allocation -// -//nolint:gosec // unsafe is used for better performance here func UnsafeString(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } +// #nosec G103 // UnsafeBytes returns a byte pointer without allocation. // String length shouldn't be more than 2147418112. -// -//nolint:gosec // unsafe is used for better performance here func UnsafeBytes(s string) []byte { if s == "" { return nil @@ -49,7 +47,7 @@ func CopyBytes(b []byte) []byte { } const ( - uByte = 1 << (10 * iota) //nolint:gomnd // 1 << 10 == 1024 + uByte = 1 << (10 * iota) uKilobyte uMegabyte uGigabyte @@ -94,7 +92,7 @@ func ByteSize(bytes uint64) string { // ToString Change arg to string func ToString(arg interface{}, timeFormat ...string) string { - tmp := reflect.Indirect(reflect.ValueOf(arg)).Interface() + var tmp = reflect.Indirect(reflect.ValueOf(arg)).Interface() switch v := tmp.(type) { case int: return strconv.Itoa(v) diff --git a/utils/convert_test.go b/utils/convert_test.go index 4bfd6bf079..59ce625e53 100644 --- a/utils/convert_test.go +++ b/utils/convert_test.go @@ -4,9 +4,7 @@ package utils -import ( - "testing" -) +import "testing" func Test_UnsafeString(t *testing.T) { t.Parallel() diff --git a/utils/deprecated.go b/utils/deprecated.go index a436e67a5b..ae6fd34e7b 100644 --- a/utils/deprecated.go +++ b/utils/deprecated.go @@ -1,16 +1,18 @@ package utils -// Deprecated: Please use UnsafeString instead +// #nosec G103 +// DEPRECATED, Please use UnsafeString instead func GetString(b []byte) string { return UnsafeString(b) } -// Deprecated: Please use UnsafeBytes instead +// #nosec G103 +// DEPRECATED, Please use UnsafeBytes instead func GetBytes(s string) []byte { return UnsafeBytes(s) } -// Deprecated: Please use CopyString instead +// DEPRECATED, Please use CopyString instead func ImmutableString(s string) string { return CopyString(s) } diff --git a/utils/http.go b/utils/http.go index 69f25ef193..bdcd834c98 100644 --- a/utils/http.go +++ b/utils/http.go @@ -4,18 +4,15 @@ package utils -import ( - "strings" -) +import "strings" const MIMEOctetStream = "application/octet-stream" // GetMIME returns the content-type of a file extension -func GetMIME(extension string) string { +func GetMIME(extension string) (mime string) { if len(extension) == 0 { - return "" + return mime } - var mime string if extension[0] == '.' { mime = mimeExtensions[extension[1:]] } else { @@ -38,7 +35,6 @@ func ParseVendorSpecificContentType(cType string) string { } var parsableType string - //nolint:revive // Actually not simpler if semiColonIndex := strings.Index(cType, ";"); semiColonIndex == -1 { parsableType = cType[plusIndex+1:] } else if plusIndex < semiColonIndex { @@ -71,8 +67,6 @@ func StatusMessage(status int) string { } // NOTE: Keep this in sync with the status code list -// -//nolint:gochecknoglobals // Using a global var is fine here var statusMessage = []string{ 100: "Continue", // StatusContinue 101: "Switching Protocols", // StatusSwitchingProtocols @@ -146,8 +140,6 @@ var statusMessage = []string{ // MIME types were copied from https://github.com/nginx/nginx/blob/67d2a9541826ecd5db97d604f23460210fd3e517/conf/mime.types with the following updates: // - Use "application/xml" instead of "text/xml" as recommended per https://datatracker.ietf.org/doc/html/rfc7303#section-4.1 // - Use "text/javascript" instead of "application/javascript" as recommended per https://www.rfc-editor.org/rfc/rfc9239#name-text-javascript -// -//nolint:gochecknoglobals // Using a global var is fine here var mimeExtensions = map[string]string{ "html": "text/html", "htm": "text/html", diff --git a/utils/ips.go b/utils/ips.go index adac9d4255..4886c117f7 100644 --- a/utils/ips.go +++ b/utils/ips.go @@ -6,8 +6,6 @@ import ( // IsIPv4 works the same way as net.ParseIP, // but without check for IPv6 case and without returning net.IP slice, whereby IsIPv4 makes no allocations. -// -//nolint:gomnd // Magic numbers used for a faster algorithm than net.ParseIP func IsIPv4(s string) bool { for i := 0; i < net.IPv4len; i++ { if len(s) == 0 { @@ -42,8 +40,6 @@ func IsIPv4(s string) bool { // IsIPv6 works the same way as net.ParseIP, // but without check for IPv4 case and without returning net.IP slice, whereby IsIPv6 makes no allocations. -// -//nolint:gomnd // Magic numbers used for a faster algorithm than net.ParseIP func IsIPv6(s string) bool { ellipsis := -1 // position of ellipsis in ip diff --git a/utils/time.go b/utils/time.go index 93fe88087e..8ea13c2262 100644 --- a/utils/time.go +++ b/utils/time.go @@ -6,7 +6,6 @@ import ( "time" ) -//nolint:gochecknoglobals // TODO: Do not use global vars here var ( timestampTimer sync.Once // Timestamp please start the timer function before you use this value diff --git a/utils/time_test.go b/utils/time_test.go index 0f467f9f85..75c13b1dd8 100644 --- a/utils/time_test.go +++ b/utils/time_test.go @@ -6,12 +6,9 @@ import ( "time" ) -func checkTimeStamp(tb testing.TB, expectedCurrent, actualCurrent uint32) { //nolint:thelper // TODO: Verify if tb can be nil - if tb != nil { - tb.Helper() - } +func checkTimeStamp(t testing.TB, expectedCurrent, actualCurrent uint32) { // test with some buffer in front and back of the expectedCurrent time -> because of the timing on the work machine - AssertEqual(tb, true, actualCurrent >= expectedCurrent-1 || actualCurrent <= expectedCurrent+1) + AssertEqual(t, true, actualCurrent >= expectedCurrent-1 || actualCurrent <= expectedCurrent+1) } func Test_TimeStampUpdater(t *testing.T) { diff --git a/utils/xml_test.go b/utils/xml_test.go index d0e53817f1..bbb11708d6 100644 --- a/utils/xml_test.go +++ b/utils/xml_test.go @@ -16,7 +16,7 @@ type serverXMLStructure struct { Name string `xml:"name"` } -const xmlString = `fiber onefiber two` +var xmlString = `fiber onefiber two` func Test_GolangXMLEncoder(t *testing.T) { t.Parallel()