diff --git a/.github/README_ar_SA.md b/.github/README_ar_SA.md index 7d811fc5..2ab3b33d 100644 --- a/.github/README_ar_SA.md +++ b/.github/README_ar_SA.md @@ -577,16 +577,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares هذه قائمة middlewares التي تم إنشاؤها من قبل المجتمع Fiber , الرجاء إنشاءPR إذا كنت تريد أن ترى ذلك! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 مساهمة diff --git a/.github/README_de.md b/.github/README_de.md index 42b6824d..834f7a91 100644 --- a/.github/README_de.md +++ b/.github/README_de.md @@ -513,16 +513,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares This is a list of middlewares that are created by the Fiber community, please create a PR if you want to see yours! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 Mitwirken diff --git a/.github/README_es.md b/.github/README_es.md index 0a6f429b..a9efea02 100644 --- a/.github/README_es.md +++ b/.github/README_es.md @@ -513,16 +513,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares This is a list of middlewares that are created by the Fiber community, please create a PR if you want to see yours! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 Contribuir diff --git a/.github/README_fr.md b/.github/README_fr.md index 04e1fc6b..78dd95c6 100644 --- a/.github/README_fr.md +++ b/.github/README_fr.md @@ -513,16 +513,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares This is a list of middlewares that are created by the Fiber community, please create a PR if you want to see yours! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 Contribuer diff --git a/.github/README_he.md b/.github/README_he.md index 11e28219..5aa2db6b 100644 --- a/.github/README_he.md +++ b/.github/README_he.md @@ -631,16 +631,17 @@ This is a list of middlewares that are created by the Fiber community, please cr
-- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate)
diff --git a/.github/README_id.md b/.github/README_id.md index 3bdf94be..88454f10 100644 --- a/.github/README_id.md +++ b/.github/README_id.md @@ -515,16 +515,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares This is a list of middlewares that are created by the Fiber community, please create a PR if you want to see yours! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 Berkontribusi diff --git a/.github/README_ja.md b/.github/README_ja.md index 57b9889b..ace64b4e 100644 --- a/.github/README_ja.md +++ b/.github/README_ja.md @@ -516,16 +516,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares This is a list of middlewares that are created by the Fiber community, please create a PR if you want to see yours! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 貢献する diff --git a/.github/README_ko.md b/.github/README_ko.md index 3bc581cd..27d2d68f 100644 --- a/.github/README_ko.md +++ b/.github/README_ko.md @@ -518,16 +518,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares This is a list of middlewares that are created by the Fiber community, please create a PR if you want to see yours! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 기여 diff --git a/.github/README_nl.md b/.github/README_nl.md index 656c46cb..ea7229d4 100644 --- a/.github/README_nl.md +++ b/.github/README_nl.md @@ -517,17 +517,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares This is a list of middlewares that are created by the Fiber community, please create a PR if you want to see yours! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) - +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 Bijdragen Om de actieve ontwikkelingen van `Fiber` te ondersteunen of om een **bedankje** te geven: diff --git a/.github/README_pt.md b/.github/README_pt.md index effdc33d..cfd77a0d 100644 --- a/.github/README_pt.md +++ b/.github/README_pt.md @@ -511,16 +511,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Middlewares Third Party Esta é uma lista de middlewares criados pela comunidade do Fiber, se quiser ter o seu middleware aqui, é só abrir um PR! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 Contribuindo diff --git a/.github/README_ru.md b/.github/README_ru.md index 68b0449d..49a16102 100644 --- a/.github/README_ru.md +++ b/.github/README_ru.md @@ -516,16 +516,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( Это список middlewares, созданных сообществом Fiber. Пожалуйста, [создайте PR](https://github.com/gofiber/fiber/pulls), если хотите добавить в этот список свой или известный вам middleware для веб фреймворка Fiber! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 Помощь проекту diff --git a/.github/README_tr.md b/.github/README_tr.md index 99da4997..76cb8424 100644 --- a/.github/README_tr.md +++ b/.github/README_tr.md @@ -510,16 +510,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 Third Party Middlewares This is a list of middlewares that are created by the Fiber community, please create a PR if you want to see yours! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 Destek diff --git a/.github/README_zh-CN.md b/.github/README_zh-CN.md index 0dc3d718..58c03363 100644 --- a/.github/README_zh-CN.md +++ b/.github/README_zh-CN.md @@ -515,16 +515,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( ## 🌱 第三方中间件 这是由`Fiber`社区创建的中间件列表,如果您想看到自己的中间件,请创建`PR`。 -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 贡献 diff --git a/.github/README_zh-TW.md b/.github/README_zh-TW.md index 7f805603..78c6d7e1 100644 --- a/.github/README_zh-TW.md +++ b/.github/README_zh-TW.md @@ -514,16 +514,17 @@ List of externally hosted middleware modules and maintained by the [Fiber team]( 由社群建立的中介器列表,要新增請發PR! -- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/fiber-casbin](https://github.com/arsmn/fiber-casbin) - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) -- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) -- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) -- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/fiber-swagger](https://github.com/arsmn/fiber-swagger) - [arsmn/gqlgen](https://github.com/arsmn/gqlgen) -- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) -- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [codemicro/fiber-cache](https://github.com/codemicro/fiber-cache) - [itsursujit/fiber-boilerplate](https://github.com/itsursujit/fiber-boilerplate) +- [juandiii/go-jwk-security](https://github.com/juandiii/go-jwk-security) +- [kiyonlin/fiber_limiter](https://github.com/kiyonlin/fiber_limiter) +- [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) ## 👍 貢獻 diff --git a/app.go b/app.go index 478208f7..2e1daa11 100644 --- a/app.go +++ b/app.go @@ -706,9 +706,9 @@ func (app *App) startupMessage(addr string, tls bool, pids string) { addr = "https://" + host + ":" + port } - isPrefork := "disabled" + isPrefork := "Disabled" if app.config.Prefork { - isPrefork = "enabled" + isPrefork = "Enabled" } out := colorable.NewColorableStdout() diff --git a/app_test.go b/app_test.go index 853c92fe..4150bd33 100644 --- a/app_test.go +++ b/app_test.go @@ -433,15 +433,29 @@ func Test_App_New(t *testing.T) { appConfig.Get("/", testEmptyHandler) } -func Test_App_Shutdown(t *testing.T) { +func Test_App_Config(t *testing.T) { app := New(Config{ DisableStartupMessage: true, }) - if err := app.Shutdown(); err != nil { - if err.Error() != "shutdown: server is not running" { - t.Fatal() + utils.AssertEqual(t, true, app.Config().DisableStartupMessage) +} + +func Test_App_Shutdown(t *testing.T) { + t.Run("success", func(t *testing.T) { + app := New(Config{ + DisableStartupMessage: true, + }) + utils.AssertEqual(t, true, app.Shutdown() == nil) + }) + + t.Run("no server", func(t *testing.T) { + app := &App{} + if err := app.Shutdown(); err != nil { + if err.Error() != "shutdown: server is not running" { + t.Fatal() + } } - } + }) } // go test -run Test_App_Static_Index_Default @@ -750,7 +764,9 @@ func Test_App_Next_Method(t *testing.T) { // go test -run Test_App_Listen func Test_App_Listen(t *testing.T) { - app := New() + app := New(Config{DisableStartupMessage: true}) + + utils.AssertEqual(t, false, app.Listen(":99999") == nil) go func() { time.Sleep(1000 * time.Millisecond) @@ -758,13 +774,6 @@ func Test_App_Listen(t *testing.T) { }() utils.AssertEqual(t, nil, app.Listen(":4003")) - - go func() { - time.Sleep(1000 * time.Millisecond) - utils.AssertEqual(t, nil, app.Shutdown()) - }() - - utils.AssertEqual(t, nil, app.Listen(":4010")) } // go test -run Test_App_Listener @@ -990,3 +999,8 @@ func Test_App_SmallReadBuffer(t *testing.T) { utils.AssertEqual(t, nil, app.Listen(":4006")) } + +func Test_App_Master_Process_Show_Startup_Message(t *testing.T) { + New(Config{Prefork: true}). + startupMessage(":3000", true, "") +} diff --git a/helpers_test.go b/helpers_test.go index d965e70d..87d2a9d9 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -5,7 +5,9 @@ package fiber import ( + "crypto/tls" "fmt" + "net" "testing" "time" @@ -300,3 +302,45 @@ func Benchmark_Utils_IsNoCache(b *testing.B) { } utils.AssertEqual(b, true, ok) } + +func Test_Utils_lnMetadata(t *testing.T) { + t.Run("closed listen", func(t *testing.T) { + ln, err := net.Listen("tcp", ":0") + utils.AssertEqual(t, nil, err) + + utils.AssertEqual(t, nil, ln.Close()) + + addr, config := lnMetadata(ln) + + utils.AssertEqual(t, ln.Addr().String(), addr) + utils.AssertEqual(t, true, config == nil) + }) + + t.Run("non tls", func(t *testing.T) { + ln, err := net.Listen("tcp", ":0") + + utils.AssertEqual(t, nil, err) + + addr, config := lnMetadata(ln) + + utils.AssertEqual(t, ln.Addr().String(), addr) + utils.AssertEqual(t, true, config == nil) + }) + + t.Run("tls", func(t *testing.T) { + cer, err := tls.LoadX509KeyPair("./.github/testdata/ssl.pem", "./.github/testdata/ssl.key") + utils.AssertEqual(t, nil, err) + + config := &tls.Config{Certificates: []tls.Certificate{cer}} + + ln, err := net.Listen("tcp4", ":0") + utils.AssertEqual(t, nil, err) + + ln = tls.NewListener(ln, config) + + addr, config := lnMetadata(ln) + + utils.AssertEqual(t, ln.Addr().String(), addr) + utils.AssertEqual(t, true, config != nil) + }) +} diff --git a/middleware/basicauth/basicauth_test.go b/middleware/basicauth/basicauth_test.go index 2becceae..00c00567 100644 --- a/middleware/basicauth/basicauth_test.go +++ b/middleware/basicauth/basicauth_test.go @@ -12,6 +12,22 @@ import ( "github.com/gofiber/fiber/v2/utils" ) +// go test -run Test_BasicAuth_Next +func Test_BasicAuth_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) +} + func Test_Middleware_BasicAuth(t *testing.T) { app := fiber.New() diff --git a/middleware/compress/compress.go b/middleware/compress/compress.go index 05f7d21e..c9553d3a 100644 --- a/middleware/compress/compress.go +++ b/middleware/compress/compress.go @@ -46,9 +46,6 @@ func New(config ...Config) fiber.Handler { cfg = config[0] // Set default values - if cfg.Next == nil { - cfg.Next = ConfigDefault.Next - } if cfg.Level < -1 || cfg.Level > 2 { cfg.Level = ConfigDefault.Level } @@ -62,13 +59,13 @@ func New(config ...Config) fiber.Handler { // Setup compression algorithm switch cfg.Level { - case 0: + case LevelDefault: // LevelDefault compressor = fasthttp.CompressHandlerBrotliLevel(fctx, fasthttp.CompressBrotliDefaultCompression, fasthttp.CompressDefaultCompression) - case 1: + case LevelBestSpeed: // LevelBestSpeed compressor = fasthttp.CompressHandlerBrotliLevel(fctx, fasthttp.CompressBrotliBestSpeed, fasthttp.CompressBestSpeed) - case 2: + case LevelBestCompression: // LevelBestCompression compressor = fasthttp.CompressHandlerBrotliLevel(fctx, fasthttp.CompressBrotliBestCompression, fasthttp.CompressBestCompression) default: diff --git a/middleware/compress/compress_test.go b/middleware/compress/compress_test.go index 66aa64f5..6e3032fc 100644 --- a/middleware/compress/compress_test.go +++ b/middleware/compress/compress_test.go @@ -1,6 +1,8 @@ package compress import ( + "errors" + "fmt" "io/ioutil" "net/http/httptest" "testing" @@ -19,7 +21,7 @@ func init() { filedata = dat } -// go test -run Test_Compress +// go test -run Test_Compress_Gzip func Test_Compress_Gzip(t *testing.T) { app := fiber.New() @@ -40,12 +42,33 @@ func Test_Compress_Gzip(t *testing.T) { // Validate the file size is shrinked body, err := ioutil.ReadAll(resp.Body) - if err != nil { - utils.AssertEqual(t, nil, err) - } + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, true, len(body) < len(filedata)) } +// go test -run Test_Compress_Different_Level +func Test_Compress_Different_Level(t *testing.T) { + levels := []int{LevelBestSpeed, LevelBestCompression, 10} + for _, level := range levels { + t.Run(fmt.Sprintf("level %d", level), func(t *testing.T) { + app := fiber.New() + + app.Use(New(Config{Level: level})) + + app.Get("/", func(c *fiber.Ctx) error { + c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8) + return c.Send(filedata) + }) + + req := httptest.NewRequest("GET", "/", nil) + + resp, err := app.Test(req) + utils.AssertEqual(t, nil, err, "app.Test(req)") + utils.AssertEqual(t, 200, resp.StatusCode, "Status code") + }) + } +} + func Test_Compress_Deflate(t *testing.T) { app := fiber.New() @@ -65,9 +88,7 @@ func Test_Compress_Deflate(t *testing.T) { // Validate the file size is shrinked body, err := ioutil.ReadAll(resp.Body) - if err != nil { - utils.AssertEqual(t, nil, err) - } + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, true, len(body) < len(filedata)) } @@ -83,15 +104,74 @@ func Test_Compress_Brotli(t *testing.T) { req := httptest.NewRequest("GET", "/", nil) req.Header.Set("Accept-Encoding", "br") - resp, err := app.Test(req) + resp, err := app.Test(req, 10000) utils.AssertEqual(t, nil, err, "app.Test(req)") utils.AssertEqual(t, 200, resp.StatusCode, "Status code") utils.AssertEqual(t, "br", resp.Header.Get(fiber.HeaderContentEncoding)) // Validate the file size is shrinked body, err := ioutil.ReadAll(resp.Body) - if err != nil { - utils.AssertEqual(t, nil, err) - } + utils.AssertEqual(t, nil, err) utils.AssertEqual(t, true, len(body) < len(filedata)) } + +func Test_Compress_Disabled(t *testing.T) { + app := fiber.New() + + app.Use(New(Config{Level: LevelDisabled})) + + app.Get("/", func(c *fiber.Ctx) error { + return c.Send(filedata) + }) + + req := httptest.NewRequest("GET", "/", nil) + req.Header.Set("Accept-Encoding", "br") + + resp, err := app.Test(req) + utils.AssertEqual(t, nil, err, "app.Test(req)") + utils.AssertEqual(t, 200, resp.StatusCode, "Status code") + utils.AssertEqual(t, "", resp.Header.Get(fiber.HeaderContentEncoding)) + + // Validate the file size is not shrinked + body, err := ioutil.ReadAll(resp.Body) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, true, len(body) == len(filedata)) +} + +func Test_Compress_Next_Error(t *testing.T) { + app := fiber.New() + + app.Use(New()) + + app.Get("/", func(c *fiber.Ctx) error { + return errors.New("next error") + }) + + req := httptest.NewRequest("GET", "/", nil) + req.Header.Set("Accept-Encoding", "gzip") + + resp, err := app.Test(req) + utils.AssertEqual(t, nil, err, "app.Test(req)") + utils.AssertEqual(t, 500, resp.StatusCode, "Status code") + utils.AssertEqual(t, "", resp.Header.Get(fiber.HeaderContentEncoding)) + + body, err := ioutil.ReadAll(resp.Body) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, "next error", string(body)) +} + +// go test -run Test_Compress_Next +func Test_Compress_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + 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/cors.go b/middleware/cors/cors.go index cb69fd55..60a93fa4 100644 --- a/middleware/cors/cors.go +++ b/middleware/cors/cors.go @@ -81,15 +81,12 @@ func New(config ...Config) fiber.Handler { cfg = config[0] // Set default values - if cfg.Next == nil { - cfg.Next = ConfigDefault.Next + if cfg.AllowMethods == "" { + cfg.AllowMethods = ConfigDefault.AllowMethods } if cfg.AllowOrigins == "" { cfg.AllowOrigins = ConfigDefault.AllowOrigins } - if cfg.AllowMethods == "" { - cfg.AllowMethods = ConfigDefault.AllowMethods - } } // Convert string to slice diff --git a/middleware/cors/cors_test.go b/middleware/cors/cors_test.go index 1f7081b1..2b57a5ff 100644 --- a/middleware/cors/cors_test.go +++ b/middleware/cors/cors_test.go @@ -1,6 +1,7 @@ package cors import ( + "net/http/httptest" "testing" "github.com/gofiber/fiber/v2" @@ -12,6 +13,17 @@ func Test_CORS_Defaults(t *testing.T) { app := fiber.New() app.Use(New()) + testDefaultOrEmptyConfig(t, app) +} + +func Test_CORS_Empty_Config(t *testing.T) { + app := fiber.New() + app.Use(New(Config{})) + + testDefaultOrEmptyConfig(t, app) +} + +func testDefaultOrEmptyConfig(t *testing.T, app *fiber.App) { h := app.Handler() // Test default GET response headers @@ -41,7 +53,13 @@ func Test_CORS_Wildcard(t *testing.T) { handler := app.Handler() // OPTIONS (preflight) response headers when AllowOrigins is * - app.Use(New(Config{AllowOrigins: "*", AllowCredentials: true, MaxAge: 3600})) + app.Use(New(Config{ + AllowOrigins: "*", + AllowCredentials: true, + MaxAge: 3600, + ExposeHeaders: "X-Request-ID", + AllowHeaders: "Authentication", + })) // Make request ctx := &fasthttp.RequestCtx{} @@ -56,6 +74,16 @@ func Test_CORS_Wildcard(t *testing.T) { utils.AssertEqual(t, "localhost", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowOrigin))) utils.AssertEqual(t, "true", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowCredentials))) utils.AssertEqual(t, "3600", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlMaxAge))) + utils.AssertEqual(t, "Authentication", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowHeaders))) + + // Test non OPTIONS (preflight) response headers + ctx = &fasthttp.RequestCtx{} + ctx.Request.Header.SetMethod(fiber.MethodGet) + handler(ctx) + + utils.AssertEqual(t, "true", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlAllowCredentials))) + utils.AssertEqual(t, "X-Request-ID", string(ctx.Response.Header.Peek(fiber.HeaderAccessControlExposeHeaders))) + } // go test -run -v Test_CORS_Subdomain @@ -193,3 +221,19 @@ func Test_CORS_AllowOriginScheme(t *testing.T) { } } } + +// go test -run Test_CORS_Next +func Test_CORS_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) +} diff --git a/middleware/csrf/csrf.go b/middleware/csrf/csrf.go index ad03ef46..9c822b10 100644 --- a/middleware/csrf/csrf.go +++ b/middleware/csrf/csrf.go @@ -85,6 +85,10 @@ func New(config ...Config) fiber.Handler { // Generate the correct extractor to get the token from the correct location selectors := strings.Split(cfg.TokenLookup, ":") + if len(selectors) != 2 { + panic("csrf: Token lookup must in the form of :") + } + // By default we extract from a header extractor := csrfFromHeader(selectors[1]) @@ -169,7 +173,7 @@ func csrfFromHeader(param string) func(c *fiber.Ctx) (string, error) { } } -// csrfcsrfFromQuery returns a function that extracts token from the query string. +// csrfFromQuery returns a function that extracts token from the query string. func csrfFromQuery(param string) func(c *fiber.Ctx) (string, error) { return func(c *fiber.Ctx) (string, error) { token := c.Query(param) diff --git a/middleware/csrf/csrf_test.go b/middleware/csrf/csrf_test.go index 79b6a085..6a4739a8 100644 --- a/middleware/csrf/csrf_test.go +++ b/middleware/csrf/csrf_test.go @@ -1,6 +1,7 @@ package csrf import ( + "net/http/httptest" "strings" "testing" @@ -51,3 +52,114 @@ func Test_CSRF(t *testing.T) { h(ctx) utils.AssertEqual(t, 200, ctx.Response.StatusCode()) } + +// go test -run Test_CSRF_Next +func Test_CSRF_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) +} + +func Test_CSRF_Invalid_TokenLookup(t *testing.T) { + defer func() { + utils.AssertEqual(t, "csrf: Token lookup must in the form of :", recover()) + }() + app := fiber.New() + + app.Use(New(Config{TokenLookup: "I:am:invalid"})) + + app.Post("/", func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) + }) + + h := app.Handler() + ctx := &fasthttp.RequestCtx{} + ctx.Request.Header.SetMethod("GET") + h(ctx) +} + +func Test_CSRF_From_Form(t *testing.T) { + app := fiber.New() + + app.Use(New(Config{TokenLookup: "form:_csrf"})) + + app.Post("/", func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) + }) + + h := app.Handler() + ctx := &fasthttp.RequestCtx{} + + // Valid CSRF token + token := utils.UUID() + ctx.Request.Header.SetMethod("POST") + ctx.Request.Header.Set(fiber.HeaderCookie, "_csrf="+token) + ctx.Request.Header.Set(fiber.HeaderContentType, fiber.MIMEApplicationForm) + h(ctx) + utils.AssertEqual(t, 403, ctx.Response.StatusCode()) + + ctx.Request.Reset() + ctx.Request.Header.SetMethod("POST") + ctx.Request.Header.Set(fiber.HeaderCookie, "_csrf="+token) + ctx.Request.Header.Set(fiber.HeaderContentType, fiber.MIMEApplicationForm) + ctx.Request.SetBodyString("_csrf=" + token) + h(ctx) + utils.AssertEqual(t, 200, ctx.Response.StatusCode()) +} + +func Test_CSRF_From_Query(t *testing.T) { + app := fiber.New() + + app.Use(New(Config{TokenLookup: "query:_csrf"})) + + app.Post("/", func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) + }) + + h := app.Handler() + ctx := &fasthttp.RequestCtx{} + + // Valid CSRF token + token := utils.UUID() + ctx.Request.Header.SetMethod("POST") + ctx.Request.Header.Set(fiber.HeaderCookie, "_csrf="+token) + ctx.Request.SetRequestURI("/?_csrf=" + token) + h(ctx) + utils.AssertEqual(t, 200, ctx.Response.StatusCode()) + + ctx.Request.SetRequestURI("/") + ctx.Response.Reset() + h(ctx) + utils.AssertEqual(t, 403, ctx.Response.StatusCode()) + utils.AssertEqual(t, "Forbidden", string(ctx.Response.Body())) +} + +func Test_CSRF_From_Param(t *testing.T) { + app := fiber.New() + + csrfGroup := app.Group("/:csrf", New(Config{TokenLookup: "param:csrf"})) + + csrfGroup.Post("/", func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) + }) + + h := app.Handler() + ctx := &fasthttp.RequestCtx{} + + // Valid CSRF token + token := utils.UUID() + ctx.Request.Header.SetMethod("POST") + ctx.Request.Header.Set(fiber.HeaderCookie, "_csrf="+token) + ctx.Request.SetRequestURI("/" + token) + h(ctx) + utils.AssertEqual(t, 200, ctx.Response.StatusCode()) +} diff --git a/middleware/favicon/favicon_test.go b/middleware/favicon/favicon_test.go index 78cf63a4..6803593c 100644 --- a/middleware/favicon/favicon_test.go +++ b/middleware/favicon/favicon_test.go @@ -88,3 +88,19 @@ func Benchmark_Middleware_Favicon(b *testing.B) { handler(c) } } + +// go test -run Test_Favicon_Next +func Test_Favicon_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + 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 f4f3f435..3c1414d6 100644 --- a/middleware/filesystem/filesystem.go +++ b/middleware/filesystem/filesystem.go @@ -1,7 +1,6 @@ package filesystem import ( - "log" "net/http" "os" "strings" @@ -62,8 +61,11 @@ func New(config Config) fiber.Handler { if !strings.HasPrefix(cfg.Index, "/") { cfg.Index = "/" + cfg.Index } + if cfg.NotFoundFile != "" && !strings.HasPrefix(cfg.NotFoundFile, "/") { + cfg.NotFoundFile = "/" + cfg.NotFoundFile + } if cfg.Root == nil { - log.Fatal("filesystem: Root cannot be nil") + panic("filesystem: Root cannot be nil") } var once sync.Once diff --git a/middleware/filesystem/filesystem_test.go b/middleware/filesystem/filesystem_test.go index 7c0661a4..bda939a1 100644 --- a/middleware/filesystem/filesystem_test.go +++ b/middleware/filesystem/filesystem_test.go @@ -2,6 +2,7 @@ package filesystem import ( "net/http" + "net/http/httptest" "testing" "github.com/gofiber/fiber/v2" @@ -110,3 +111,20 @@ func Test_FileSystem(t *testing.T) { }) } } + +// go test -run Test_FileSystem_Next +func Test_FileSystem_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Root: http.Dir("../../.github/testdata/fs"), + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) +} diff --git a/middleware/limiter/limiter_test.go b/middleware/limiter/limiter_test.go index fe336aa3..ebb2fe35 100644 --- a/middleware/limiter/limiter_test.go +++ b/middleware/limiter/limiter_test.go @@ -88,3 +88,19 @@ func Benchmark_Limiter(b *testing.B) { utils.AssertEqual(b, "100", string(fctx.Response.Header.Peek("X-RateLimit-Limit"))) } + +// go test -run Test_Limiter_Next +func Test_Limiter_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) +} diff --git a/middleware/logger/logger__test.go b/middleware/logger/logger__test.go index 1bb797c8..7c3052f7 100644 --- a/middleware/logger/logger__test.go +++ b/middleware/logger/logger__test.go @@ -31,3 +31,19 @@ func Test_Logger(t *testing.T) { utils.AssertEqual(t, fiber.StatusInternalServerError, resp.StatusCode) utils.AssertEqual(t, "some random error", buf.String()) } + +// go test -run Test_Logger_Next +func Test_Logger_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) +} diff --git a/middleware/pprof/pprof.go b/middleware/pprof/pprof.go index f122b73e..63446a3c 100644 --- a/middleware/pprof/pprof.go +++ b/middleware/pprof/pprof.go @@ -35,7 +35,6 @@ func New() fiber.Handler { // Switch to original path without stripped slashes switch path { case "/debug/pprof/": - c.Context().SetContentType(fiber.MIMETextHTML) pprofIndex(c.Context()) case "/debug/pprof/cmdline": pprofCmdline(c.Context()) diff --git a/middleware/pprof/pprof_test.go b/middleware/pprof/pprof_test.go new file mode 100644 index 00000000..2b22159f --- /dev/null +++ b/middleware/pprof/pprof_test.go @@ -0,0 +1,88 @@ +package pprof + +import ( + "bytes" + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/utils" + "io/ioutil" + "net/http/httptest" + "testing" +) + +func Test_Non_Pprof_Path(t *testing.T) { + app := fiber.New(fiber.Config{DisableStartupMessage: true}) + + app.Use(New()) + + app.Get("/", func(c *fiber.Ctx) error { + return c.SendString("escaped") + }) + + resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, 200, resp.StatusCode) + + b, err := ioutil.ReadAll(resp.Body) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, "escaped", string(b)) +} + +func Test_Pprof_Index(t *testing.T) { + app := fiber.New(fiber.Config{DisableStartupMessage: true}) + + app.Use(New()) + + app.Get("/", func(c *fiber.Ctx) error { + return c.SendString("escaped") + }) + + resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/debug/pprof/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, 200, resp.StatusCode) + utils.AssertEqual(t, fiber.MIMETextHTMLCharsetUTF8, resp.Header.Get(fiber.HeaderContentType)) + + b, err := ioutil.ReadAll(resp.Body) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, true, bytes.Contains(b, []byte("/debug/pprof/"))) +} + +func Test_Pprof_Subs(t *testing.T) { + app := fiber.New(fiber.Config{DisableStartupMessage: true}) + + app.Use(New()) + + app.Get("/", func(c *fiber.Ctx) error { + return c.SendString("escaped") + }) + + subs := []string{ + "cmdline", "profile", "symbol", "trace", "allocs", "block", + "goroutine", "heap", "mutex", "threadcreate", + } + + for _, sub := range subs { + t.Run(sub, func(t *testing.T) { + target := "/debug/pprof/" + sub + if sub == "profile" { + target += "?seconds=1" + } + resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, target, nil), 5000) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, 200, resp.StatusCode) + }) + } +} + +func Test_Pprof_Other(t *testing.T) { + app := fiber.New(fiber.Config{DisableStartupMessage: true}) + + app.Use(New()) + + app.Get("/", func(c *fiber.Ctx) error { + return c.SendString("escaped") + }) + + resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/debug/pprof/302", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, 302, resp.StatusCode) +} diff --git a/middleware/recover/recover.go b/middleware/recover/recover.go index fe3ea5e2..8ee4b30f 100644 --- a/middleware/recover/recover.go +++ b/middleware/recover/recover.go @@ -27,11 +27,6 @@ func New(config ...Config) fiber.Handler { // Override config if provided if len(config) > 0 { cfg = config[0] - - // Set default values - if cfg.Next == nil { - cfg.Next = ConfigDefault.Next - } } // Return new handler diff --git a/middleware/recover/recover_test.go b/middleware/recover/recover_test.go index 05e7c34a..dd76573a 100644 --- a/middleware/recover/recover_test.go +++ b/middleware/recover/recover_test.go @@ -27,3 +27,19 @@ func Test_Recover(t *testing.T) { utils.AssertEqual(t, nil, err) utils.AssertEqual(t, fiber.StatusTeapot, resp.StatusCode) } + +// go test -run Test_Recover_Next +func Test_Recover_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) +} diff --git a/middleware/requestid/requestid.go b/middleware/requestid/requestid.go index 68f6faff..fbee5203 100644 --- a/middleware/requestid/requestid.go +++ b/middleware/requestid/requestid.go @@ -44,9 +44,6 @@ func New(config ...Config) fiber.Handler { cfg = config[0] // Set default values - if cfg.Next == nil { - cfg.Next = ConfigDefault.Next - } if cfg.Header == "" { cfg.Header = ConfigDefault.Header } diff --git a/middleware/requestid/requestid_test.go b/middleware/requestid/requestid_test.go index 84db2d19..a01c161f 100644 --- a/middleware/requestid/requestid_test.go +++ b/middleware/requestid/requestid_test.go @@ -33,3 +33,19 @@ func Test_RequestID(t *testing.T) { utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode) utils.AssertEqual(t, reqid, resp.Header.Get(fiber.HeaderXRequestID)) } + +// go test -run Test_RequestID_Next +func Test_RequestID_Next(t *testing.T) { + app := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) + app.Use(New(Config{ + Next: func(_ *fiber.Ctx) bool { + return true + }, + })) + + resp, err := app.Test(httptest.NewRequest("GET", "/", nil)) + utils.AssertEqual(t, nil, err) + utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode) +} diff --git a/prefork_test.go b/prefork_test.go index 0f162f2b..74bb3f74 100644 --- a/prefork_test.go +++ b/prefork_test.go @@ -14,8 +14,8 @@ func Test_App_Prefork_Child_Process(t *testing.T) { // Reset test var testPreforkMaster = true - utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) - defer os.Setenv(envPreforkChildKey, "") + setupIsChild(t) + defer teardownIsChild(t) app := New() @@ -64,8 +64,8 @@ func Test_App_Prefork_Master_Process(t *testing.T) { } func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { - utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) - defer os.Setenv(envPreforkChildKey, "") + setupIsChild(t) + defer teardownIsChild(t) rescueStdout := os.Stdout defer func() { os.Stdout = rescueStdout }() @@ -83,3 +83,11 @@ func Test_App_Prefork_Child_Process_Never_Show_Startup_Message(t *testing.T) { utils.AssertEqual(t, nil, err) utils.AssertEqual(t, 0, len(out)) } + +func setupIsChild(t *testing.T) { + utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, envPreforkChildVal)) +} + +func teardownIsChild(t *testing.T) { + utils.AssertEqual(t, nil, os.Setenv(envPreforkChildKey, "")) +} diff --git a/utils/common.go b/utils/common.go index fabf4786..e045870b 100644 --- a/utils/common.go +++ b/utils/common.go @@ -10,6 +10,7 @@ import ( "encoding/hex" "reflect" "runtime" + "sync" "sync/atomic" ) @@ -22,14 +23,18 @@ const toUpperTable = "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11 var uuidSeed [24]byte var uuidCounter uint64 +var uuidSetup sync.Once func UUID() string { // Setup seed & counter once - if uuidCounter <= 0 { + uuidSetup.Do(func() { if _, err := rand.Read(uuidSeed[:]); err != nil { - return "00000000-0000-0000-0000-000000000000" + return } uuidCounter = binary.LittleEndian.Uint64(uuidSeed[:8]) + }) + if atomic.LoadUint64(&uuidCounter) <= 0 { + return "00000000-0000-0000-0000-000000000000" } // first 8 bytes differ, taking a slice of the first 16 bytes x := atomic.AddUint64(&uuidCounter, 1) diff --git a/utils/common_test.go b/utils/common_test.go index f31652d8..740ae439 100644 --- a/utils/common_test.go +++ b/utils/common_test.go @@ -24,6 +24,25 @@ func Test_Utils_UUID(t *testing.T) { t.Parallel() res := UUID() AssertEqual(t, 36, len(res)) + AssertEqual(t, true, res != "00000000-0000-0000-0000-000000000000") +} + +func Test_Utils_UUID_Concurrency(t *testing.T) { + t.Parallel() + iterations := 10000 + var res string + ch := make(chan string, iterations) + results := make(map[string]string) + for i := 0; i < iterations; i++ { + go func() { + ch <- UUID() + }() + } + for i := 0; i < iterations; i++ { + res = <-ch + results[res] = res + } + AssertEqual(t, iterations, len(results)) } // go test -v -run=^$ -bench=Benchmark_UUID -benchmem -count=2