From 8ea25a79b9cd8dd4810abc5ee6df48667f9eadd7 Mon Sep 17 00:00:00 2001 From: Fenny <25108519+Fenny@users.noreply.github.com> Date: Thu, 7 May 2020 19:28:21 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=A5=20v1.9.4=20(#341)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update router.go Co-authored-by: Fenny --- .github/README.md | 16 +- .github/README_de.md | 14 +- .github/README_es.md | 14 +- .github/README_fr.md | 14 +- .github/README_he.md | 30 +- .github/README_id.md | 14 +- .github/README_ja.md | 14 +- .github/README_ko.md | 14 +- .github/README_nl.md | 14 +- .github/README_pt.md | 14 +- .github/README_ru.md | 14 +- .github/README_tr.md | 14 +- .github/README_zh-CN.md | 14 +- app.go | 36 +-- app_test.go | 39 ++- ctx.go | 23 +- ctx_test.go | 9 +- params.go | 161 +++++++++++ params_test.go | 246 ++++++++++++++++ router.go | 247 ++++++++-------- router_test.go | 619 ++++++++++++++++++++++++++++++++++++++++ utils.go | 462 ++++++++++++------------------ 22 files changed, 1584 insertions(+), 458 deletions(-) create mode 100644 params.go create mode 100644 params_test.go create mode 100644 router_test.go diff --git a/.github/README.md b/.github/README.md index 660811c5..fa07e5a8 100644 --- a/.github/README.md +++ b/.github/README.md @@ -469,7 +469,7 @@ func main() { ``` -## 🧬 Available Middlewares +## 🧬 Official Middlewares For _easier_ and _more clear_ work, we've put [middleware](https://docs.gofiber.io/middleware) into separate repositories: @@ -490,6 +490,15 @@ For _easier_ and _more clear_ work, we've put [middleware](https://docs.gofiber. - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ Media - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -519,9 +528,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_de.md b/.github/README_de.md index 374ec2c5..1d22281e 100644 --- a/.github/README_de.md +++ b/.github/README_de.md @@ -489,6 +489,15 @@ FΓΌr _eine leichtere_ und _ΓΌbersichtlichere_ arbeit haben wir die [middleware]( - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ Medien - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -518,9 +527,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_es.md b/.github/README_es.md index 2d923605..867ef729 100644 --- a/.github/README_es.md +++ b/.github/README_es.md @@ -486,6 +486,15 @@ Para un trabajo _mΓ‘s claro_ y _sencillo_, hemos puesto cada [middleware](https: - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ Medios - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -515,9 +524,12 @@ Fiber es un proyecto open source que se mantiene a travΓ©s de donaciones para pa | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_fr.md b/.github/README_fr.md index 0d3eb8ba..21f3f239 100644 --- a/.github/README_fr.md +++ b/.github/README_fr.md @@ -486,6 +486,15 @@ For _easier_ and _more clear_ work, we've put [middleware](https://docs.gofiber. - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ Media - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -515,9 +524,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_he.md b/.github/README_he.md index 81a07269..2b4b7148 100644 --- a/.github/README_he.md +++ b/.github/README_he.md @@ -597,6 +597,15 @@ func main() { - [CORS](https://github.com/gofiber/cors) - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) + +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter
@@ -648,15 +657,18 @@ Fiber היא Χ€Χ¨Χ•Χ™Χ§Χ˜ Χ§Χ•Χ“ Χ€ΧͺΧ•Χ— Χ©ΧͺΧ©ΧœΧ•Χ Χ—Χ©Χ•Χ‘Χ•Χ ΧͺΧ™Χ• מבΧͺ | | משΧͺמש | ΧͺΧ¨Χ•ΧžΧ” | | :---------------------------------------------------------- | :---------------------------------------------- | :---- | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | -| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | -| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | -| ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | -| ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | -| ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | -| ![](https://avatars.githubusercontent.com/u/31921460?s=25 ) | [@toishy](https://github.com/toishy) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/31921460?s=25 ) | [@toishy](https://github.com/toishy) | β˜• x 1 |
diff --git a/.github/README_id.md b/.github/README_id.md index 4de674b6..35d1c153 100644 --- a/.github/README_id.md +++ b/.github/README_id.md @@ -488,6 +488,15 @@ For _easier_ and _more clear_ work, we've put [middleware](https://docs.gofiber. - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ Media - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -517,9 +526,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_ja.md b/.github/README_ja.md index bea9f86b..c938f9da 100644 --- a/.github/README_ja.md +++ b/.github/README_ja.md @@ -490,6 +490,15 @@ For _easier_ and _more clear_ work, we've put [middleware](https://docs.gofiber. - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ パディを - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -519,9 +528,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_ko.md b/.github/README_ko.md index 00957ed8..0ad74316 100644 --- a/.github/README_ko.md +++ b/.github/README_ko.md @@ -490,6 +490,15 @@ For _easier_ and _more clear_ work, we've put [middleware](https://docs.gofiber. - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ λ―Έλ””μ–΄ - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -519,9 +528,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_nl.md b/.github/README_nl.md index 4b774697..c825af13 100644 --- a/.github/README_nl.md +++ b/.github/README_nl.md @@ -490,6 +490,15 @@ Voor _eenvoudiger_ en _duidelijker_ werk hebben we de beschikbare [middleware](h - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ Media - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -519,9 +528,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_pt.md b/.github/README_pt.md index 4060b22f..2f88a32c 100644 --- a/.github/README_pt.md +++ b/.github/README_pt.md @@ -486,6 +486,15 @@ For _easier_ and _more clear_ work, we've put [middleware](https://docs.gofiber. - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ MΓ­dia - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -515,9 +524,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_ru.md b/.github/README_ru.md index a7b9a6af..88e309c2 100644 --- a/.github/README_ru.md +++ b/.github/README_ru.md @@ -488,6 +488,15 @@ func main() { - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ МСдиа - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -517,9 +526,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_tr.md b/.github/README_tr.md index 463f88c2..ce2dd9ae 100644 --- a/.github/README_tr.md +++ b/.github/README_tr.md @@ -484,6 +484,15 @@ _Kolay_ ve _daha temiz_ Γ§alışma iΓ§in [ara katmanlarΔ±mΔ±zΔ±](https://docs.go - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ Medya - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Şubat 2020_ @@ -512,9 +521,12 @@ Fiber, alan adΔ±, gitbook, netlify, serverless yer sağlayΔ±cΔ±sΔ± giderleri ve | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/.github/README_zh-CN.md b/.github/README_zh-CN.md index 09edc370..48195192 100644 --- a/.github/README_zh-CN.md +++ b/.github/README_zh-CN.md @@ -489,6 +489,15 @@ For _easier_ and _more clear_ work, we've put [middleware](https://docs.gofiber. - [CSRF](https://github.com/gofiber/csrf) - [JWT](https://github.com/gofiber/jwt) +## 🌱 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! +- https://github.com/arsmn/fiber-swagger +- https://github.com/arsmn/fiber-casbin +- https://github.com/arsmn/fiber-introspect +- https://github.com/shareed2k/fiber_tracing +- https://github.com/shareed2k/fiber_limiter + ## πŸ’¬ εͺ’体 - [Welcome to Fiber β€” an Express.js styled web framework written in Go with ❀️](https://dev.to/koddr/welcome-to-fiber-an-express-js-styled-fastest-web-framework-written-with-on-golang-497) β€” _03 Feb 2020_ @@ -518,9 +527,12 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | :---------------------------------------------------------- | :---------------------------------------------- | :------- | | ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | [@thomasvvugt](https://github.com/thomasvvugt) | β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/1094221?s=25 ) | [@ekaputra07](https://github.com/ekaputra07) | β˜• x 5 | +| ![](https://avatars.githubusercontent.com/u/186637?s=25 ) | [@candidosales](https://github.com/candidosales)| β˜• x 5 | | ![](https://avatars.githubusercontent.com/u/635852?s=25 ) | [@bihe](https://github.com/bihe) | β˜• x 3 | -| ![](https://avatars.githubusercontent.com/u/59947262?s=25 ) | @justdave | β˜• x 3 | +| ![](https://avatars.githubusercontent.com/u/307334?s=25 ) | [@justdave](https://github.com/justdave) | β˜• x 3 | | ![](https://avatars.githubusercontent.com/u/11155743?s=25 ) | [@koddr](https://github.com/koddr) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/2978730?s=25 ) | [@diegowifi](https://github.com/diegowifi) | β˜• x 1 | +| ![](https://avatars.githubusercontent.com/u/44171355?s=25 ) | [@ssimk0](https://github.com/ssimk0) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/5638101?s=25 ) | [@raymayemir](https://github.com/raymayemir) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/619996?s=25 ) | [@melkorm](https://github.com/melkorm) | β˜• x 1 | | ![](https://avatars.githubusercontent.com/u/31022056?s=25 ) | [@marvinjwendt](https://github.com/thomasvvugt) | β˜• x 1 | diff --git a/app.go b/app.go index d235c0dc..6b5eb0cd 100644 --- a/app.go +++ b/app.go @@ -1,6 +1,6 @@ -// πŸš€ Fiber is an Express inspired web framework written in Go with πŸ’– -// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ // πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io package fiber @@ -24,7 +24,7 @@ import ( ) // Version of current package -const Version = "1.9.3" +const Version = "1.9.4" // Map is a shortcut for map[string]interface{} type Map map[string]interface{} @@ -32,7 +32,7 @@ type Map map[string]interface{} // App denotes the Fiber application. type App struct { server *fasthttp.Server // FastHTTP server - routes []*Route // Route stack + routes [][]*Route // Route stack Settings *Settings // Fiber settings } @@ -112,6 +112,8 @@ func New(settings ...*Settings) *App { schemaDecoderQuery.IgnoreUnknownKeys(true) // Create app app := new(App) + // Create route stack + app.routes = make([][]*Route, len(methodINT), len(methodINT)) // Create settings app.Settings = new(Settings) // Set default settings @@ -236,7 +238,7 @@ func (app *App) All(path string, handlers ...func(*Ctx)) *App { // Group is used for Routes with common prefix to define a new sub-router with optional middleware. func (grp *Group) Group(prefix string, handlers ...func(*Ctx)) *Group { - prefix = groupPaths(grp.prefix, prefix) + prefix = getGroupPath(grp.prefix, prefix) if len(handlers) > 0 { grp.app.registerMethod("USE", prefix, handlers...) } @@ -248,7 +250,7 @@ func (grp *Group) Group(prefix string, handlers ...func(*Ctx)) *Group { // Static : https://fiber.wiki/application#static func (grp *Group) Static(prefix, root string, config ...Static) *Group { - prefix = groupPaths(grp.prefix, prefix) + prefix = getGroupPath(grp.prefix, prefix) grp.app.registerStatic(prefix, root, config...) return grp } @@ -269,67 +271,67 @@ func (grp *Group) Use(args ...interface{}) *Group { log.Fatalf("Invalid Use() arguments, must be (prefix, handler) or (handler)") } } - grp.app.registerMethod("USE", groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod("USE", getGroupPath(grp.prefix, path), handlers...) return grp } // Connect : https://fiber.wiki/application#http-methods func (grp *Group) Connect(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodConnect, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodConnect, getGroupPath(grp.prefix, path), handlers...) return grp } // Put : https://fiber.wiki/application#http-methods func (grp *Group) Put(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodPut, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodPut, getGroupPath(grp.prefix, path), handlers...) return grp } // Post : https://fiber.wiki/application#http-methods func (grp *Group) Post(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodPost, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodPost, getGroupPath(grp.prefix, path), handlers...) return grp } // Delete : https://fiber.wiki/application#http-methods func (grp *Group) Delete(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodDelete, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodDelete, getGroupPath(grp.prefix, path), handlers...) return grp } // Head : https://fiber.wiki/application#http-methods func (grp *Group) Head(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodHead, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodHead, getGroupPath(grp.prefix, path), handlers...) return grp } // Patch : https://fiber.wiki/application#http-methods func (grp *Group) Patch(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodPatch, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodPatch, getGroupPath(grp.prefix, path), handlers...) return grp } // Options : https://fiber.wiki/application#http-methods func (grp *Group) Options(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodOptions, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodOptions, getGroupPath(grp.prefix, path), handlers...) return grp } // Trace : https://fiber.wiki/application#http-methods func (grp *Group) Trace(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodTrace, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodTrace, getGroupPath(grp.prefix, path), handlers...) return grp } // Get : https://fiber.wiki/application#http-methods func (grp *Group) Get(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod(MethodGet, groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod(MethodGet, getGroupPath(grp.prefix, path), handlers...) return grp } // All matches all HTTP methods and complete paths func (grp *Group) All(path string, handlers ...func(*Ctx)) *Group { - grp.app.registerMethod("ALL", groupPaths(grp.prefix, path), handlers...) + grp.app.registerMethod("ALL", getGroupPath(grp.prefix, path), handlers...) return grp } diff --git a/app_test.go b/app_test.go index d88c9089..f71ae6ec 100644 --- a/app_test.go +++ b/app_test.go @@ -1,6 +1,6 @@ -// πŸš€ Fiber is an Express inspired web framework written in Go with πŸ’– -// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ // πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io // go test -v -coverprofile cover.out . // go tool cover -html=cover.out -o cover.html @@ -9,8 +9,10 @@ package fiber import ( + "io/ioutil" "net" "net/http" + "net/http/httptest" "testing" "time" ) @@ -32,6 +34,39 @@ func is200(t *testing.T, app *App, url string, m ...string) { t.Fatalf("%s - %s - %v", method, url, resp.StatusCode) } } + +func Test_Order(t *testing.T) { + app := New(&Settings{ + DisableStartupMessage: true, + }) + app.Get("/", func(c *Ctx) { + c.Write("1") + c.Next() + }) + app.All("/", func(c *Ctx) { + c.Write("2") + c.Next() + }) + app.Use(func(c *Ctx) { + c.Write("3") + c.Next() + }) + req := httptest.NewRequest("GET", "/", nil) + resp, err := app.Test(req) + if err != nil { + t.Fatalf(`%s: %s`, t.Name(), err) + } + if resp.StatusCode != 200 { + t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode) + } + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatalf(`%s: Error %s`, t.Name(), err) + } + if string(body) != "123" { + t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), "123", string(body)) + } +} func Test_Methods(t *testing.T) { app := New(&Settings{ DisableStartupMessage: true, diff --git a/ctx.go b/ctx.go index 1aff0e34..8f57c68e 100644 --- a/ctx.go +++ b/ctx.go @@ -1,6 +1,6 @@ -// πŸš€ Fiber is an Express inspired web framework written in Go with πŸ’– -// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ // πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io package fiber @@ -30,14 +30,17 @@ import ( // Ctx represents the Context which hold the HTTP request and response. // It has methods for the request query string, parameters, body, HTTP headers and so on. type Ctx struct { - app *App // Reference to *App - route *Route // Reference to *Route - index int // Index of the current stack - method string // HTTP method - path string // HTTP path - values []string // Route parameter values + // Internal fields + app *App // Reference to *App + route *Route // Reference to *Route + index int // Index of the current handler in the stack + method string // HTTP method + path string // HTTP path + values []string // Route parameter values + err error // Contains error if caught + + // External fields Fasthttp *fasthttp.RequestCtx // Reference to *fasthttp.RequestCtx - err error // Contains error if caught } // Range struct @@ -801,7 +804,7 @@ func (ctx *Ctx) SendStatus(status int) { ctx.Fasthttp.Response.SetStatusCode(status) // Only set status body when there is no response body if len(ctx.Fasthttp.Response.Body()) == 0 { - ctx.Fasthttp.Response.SetBodyString(statusMessages[status]) + ctx.Fasthttp.Response.SetBodyString(statusMessage[status]) } } diff --git a/ctx_test.go b/ctx_test.go index 1fa9beec..67fd7f14 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -1,6 +1,6 @@ -// πŸš€ Fiber is an Express inspired web framework written in Go with πŸ’– -// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ // πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io package fiber @@ -549,7 +549,7 @@ func Test_Params(t *testing.T) { t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result) } }) - req, _ := http.NewRequest("GET", "/test/john", nil) + req := httptest.NewRequest("GET", "/test/john", nil) resp, err := app.Test(req) if err != nil { t.Fatalf(`%s: %s`, t.Name(), err) @@ -557,7 +557,8 @@ func Test_Params(t *testing.T) { if resp.StatusCode != 200 { t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode) } - req, _ = http.NewRequest("GET", "/test2/im/a/cookie", nil) + req = httptest.NewRequest("GET", "/test2/im/a/cookie", nil) + t.Log(req.URL) resp, err = app.Test(req) if err != nil { t.Fatalf(`%s: %s`, t.Name(), err) diff --git a/params.go b/params.go new file mode 100644 index 00000000..a3239035 --- /dev/null +++ b/params.go @@ -0,0 +1,161 @@ +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ +// πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚠️ This path parser was based on urlpath by @ucarion (MIT License). +// πŸ’– Modified for the Fiber router by @renanbastos93 & @renewerner87 +// πŸ€– ucarion/urlpath - renanbastos93/fastpath - renewerner87/fastpath + +package fiber + +import ( + "strings" +) + +// paramsParser holds the path segments and param names +type parsedParams struct { + Segs []paramSeg + Keys []string +} + +// paramsSeg holds the segment metadata +type paramSeg struct { + Param string + Const string + IsParam bool + IsOptional bool + IsLast bool +} + +var paramsDummy = make([]string, 100, 100) + +// New ... +func parseParams(pattern string) (p parsedParams) { + var patternCount int + aPattern := []string{""} + if pattern != "" { + aPattern = strings.Split(pattern, "/")[1:] // every route starts with an "/" + } + patternCount = len(aPattern) + + var out = make([]paramSeg, patternCount) + var params []string + var segIndex int + for i := 0; i < patternCount; i++ { + partLen := len(aPattern[i]) + if partLen == 0 { // skip empty parts + continue + } + // is parameter ? + if aPattern[i][0] == '*' || aPattern[i][0] == ':' { + out[segIndex] = paramSeg{ + Param: paramTrimmer(aPattern[i]), + IsParam: true, + IsOptional: aPattern[i] == "*" || aPattern[i][partLen-1] == '?', + } + params = append(params, out[segIndex].Param) + } else { + // combine const segments + if segIndex > 0 && out[segIndex-1].IsParam == false { + segIndex-- + out[segIndex].Const += "/" + aPattern[i] + // create new const segment + } else { + out[segIndex] = paramSeg{ + Const: aPattern[i], + } + } + } + segIndex++ + } + if segIndex == 0 { + segIndex++ + } + out[segIndex-1].IsLast = true + + p = parsedParams{Segs: out[:segIndex:segIndex], Keys: params} + return +} + +// Match ... +func (p *parsedParams) matchParams(s string) ([]string, bool) { + lenKeys := len(p.Keys) + params := paramsDummy[0:lenKeys:lenKeys] + var i, j, paramsIterator, partLen int + if len(s) > 0 { + s = s[1:] + } + for index, segment := range p.Segs { + partLen = len(s) + // check parameter + if segment.IsParam { + // determine parameter length + if segment.IsLast { + i = partLen + } else if segment.Param == "*" { + // for the expressjs behavior -> "/api/*/:param" - "/api/joker/batman/robin/1" -> "joker/batman/robin", "1" + i = findCharPos(s, '/', strings.Count(s, "/")-(len(p.Segs)-(index+1))+1) + } else { + i = strings.IndexByte(s, '/') + } + if i == -1 { + i = partLen + } + + if false == segment.IsOptional && i == 0 { + return nil, false + } + + params[paramsIterator] = s[:i] + paramsIterator++ + } else { + // check const segment + i = len(segment.Const) + if partLen < i || (i == 0 && partLen > 0) || s[:i] != segment.Const || (partLen > i && s[i] != '/') { + return nil, false + } + } + + // reduce founded part from the string + if partLen > 0 { + j = i + 1 + if segment.IsLast || partLen < j { + j = i + } + + s = s[j:] + } + } + + return params, true +} + +func paramTrimmer(param string) string { + start := 0 + end := len(param) + + if param[start] != ':' { // is not a param + return param + } + start++ + if param[end-1] == '?' { // is ? + end-- + } + + return param[start:end] +} +func findCharPos(s string, char byte, matchCount int) int { + if matchCount == 0 { + matchCount = 1 + } + endPos, pos := 0, 0 + for matchCount > 0 && pos != -1 { + if pos > 0 { + s = s[pos+1:] + endPos++ + } + pos = strings.IndexByte(s, char) + endPos += pos + matchCount-- + } + return endPos +} diff --git a/params_test.go b/params_test.go new file mode 100644 index 00000000..b69c3257 --- /dev/null +++ b/params_test.go @@ -0,0 +1,246 @@ +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ +// πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚠️ This path parser was based on urlpath by @ucarion (MIT License). +// πŸ’– Modified for the Fiber router by @renanbastos93 & @renewerner87 +// πŸ€– ucarion/urlpath - renanbastos93/fastpath - renewerner87/fastpath + +package fiber + +import ( + "fmt" + "reflect" + "testing" +) + +// params testing + +type testCase struct { + uri string + params []string + ok bool +} + +func Test_With_Param_And_Wildcard(t *testing.T) { + checkCases( + t, + parseParams("/api/v1/:param/*"), + []testCase{ + {uri: "/api/v1/entity", params: []string{"entity", ""}, ok: true}, + {uri: "/api/v1/entity/", params: []string{"entity", ""}, ok: true}, + {uri: "/api/v1/entity/1", params: []string{"entity", "1"}, ok: true}, + {uri: "/api/v", params: nil, ok: false}, + {uri: "/api/v2", params: nil, ok: false}, + {uri: "/api/v1/", params: nil, ok: false}, + }, + ) +} + +func Test_With_A_Param_Optional(t *testing.T) { + checkCases( + t, + parseParams("/api/v1/:param?"), + []testCase{ + {uri: "/api/v1", params: []string{""}, ok: true}, + {uri: "/api/v1/", params: []string{""}, ok: true}, + {uri: "/api/v1/optional", params: []string{"optional"}, ok: true}, + {uri: "/api/v", params: nil, ok: false}, + {uri: "/api/v2", params: nil, ok: false}, + {uri: "/api/xyz", params: nil, ok: false}, + }, + ) +} + +func Test_With_With_Wildcard(t *testing.T) { + checkCases( + t, + parseParams("/api/v1/*"), + []testCase{ + {uri: "/api/v1", params: []string{""}, ok: true}, + {uri: "/api/v1/", params: []string{""}, ok: true}, + {uri: "/api/v1/entity", params: []string{"entity"}, ok: true}, + {uri: "/api/v1/entity/1/2", params: []string{"entity/1/2"}, ok: true}, + {uri: "/api/v", params: nil, ok: false}, + {uri: "/api/v2", params: nil, ok: false}, + {uri: "/api/abc", params: nil, ok: false}, + }, + ) +} +func Test_With_With_Param(t *testing.T) { + checkCases( + t, + parseParams("/api/v1/:param"), + []testCase{ + {uri: "/api/v1/entity", params: []string{"entity"}, ok: true}, + {uri: "/api/v1", params: nil, ok: false}, + {uri: "/api/v1/", params: nil, ok: false}, + }, + ) +} + +func Test_With_Without_A_Param_Or_Wildcard(t *testing.T) { + checkCases( + t, + parseParams("/api/v1/const"), + []testCase{ + {uri: "/api/v1/const", params: []string{}, ok: true}, + {uri: "/api/v1", params: nil, ok: false}, + {uri: "/api/v1/", params: nil, ok: false}, + {uri: "/api/v1/something", params: nil, ok: false}, + }, + ) +} +func Test_With_With_A_Param_And_Wildcard_Differents_Positions(t *testing.T) { + checkCases( + t, + parseParams("/api/v1/:param/abc/*"), + []testCase{ + {uri: "/api/v1/well/abc/wildcard", params: []string{"well", "wildcard"}, ok: true}, + {uri: "/api/v1/well/abc/", params: []string{"well", ""}, ok: true}, + {uri: "/api/v1/well/abc", params: []string{"well", ""}, ok: true}, + {uri: "/api/v1/well/ttt", params: nil, ok: false}, + }, + ) +} +func Test_With_With_Params_And_Optional(t *testing.T) { + checkCases( + t, + parseParams("/api/:day/:month?/:year?"), + []testCase{ + {uri: "/api/1", params: []string{"1", "", ""}, ok: true}, + {uri: "/api/1/", params: []string{"1", "", ""}, ok: true}, + {uri: "/api/1/2", params: []string{"1", "2", ""}, ok: true}, + {uri: "/api/1/2/3", params: []string{"1", "2", "3"}, ok: true}, + {uri: "/api/", params: nil, ok: false}, + }, + ) +} +func Test_With_With_Simple_Wildcard(t *testing.T) { + checkCases( + t, + parseParams("/api/*"), + []testCase{ + {uri: "/api/", params: []string{""}, ok: true}, + {uri: "/api/joker", params: []string{"joker"}, ok: true}, + {uri: "/api", params: []string{""}, ok: true}, + {uri: "/api/v1/entity", params: []string{"v1/entity"}, ok: true}, + {uri: "/api2/v1/entity", params: nil, ok: false}, + {uri: "/api_ignore/v1/entity", params: nil, ok: false}, + }, + ) +} +func Test_With_With_Wildcard_And_Optional(t *testing.T) { + checkCases( + t, + parseParams("/api/*/:param?"), + []testCase{ + {uri: "/api/", params: []string{"", ""}, ok: true}, + {uri: "/api/joker", params: []string{"joker", ""}, ok: true}, + {uri: "/api/joker/batman", params: []string{"joker", "batman"}, ok: true}, + {uri: "/api/joker/batman/robin", params: []string{"joker/batman", "robin"}, ok: true}, + {uri: "/api/joker/batman/robin/1", params: []string{"joker/batman/robin", "1"}, ok: true}, + {uri: "/api", params: []string{"", ""}, ok: true}, + }, + ) +} +func Test_With_With_Wildcard_And_Param(t *testing.T) { + checkCases( + t, + parseParams("/api/*/:param"), + []testCase{ + {uri: "/api/test/abc", params: []string{"test", "abc"}, ok: true}, + {uri: "/api/joker/batman", params: []string{"joker", "batman"}, ok: true}, + {uri: "/api/joker/batman/robin", params: []string{"joker/batman", "robin"}, ok: true}, + {uri: "/api/joker/batman/robin/1", params: []string{"joker/batman/robin", "1"}, ok: true}, + {uri: "/api", params: nil, ok: false}, + }, + ) +} +func Test_With_With_Wildcard_And_2Params(t *testing.T) { + checkCases( + t, + parseParams("/api/*/:param/:param2"), + []testCase{ + {uri: "/api/test/abc", params: nil, ok: false}, + {uri: "/api/joker/batman", params: nil, ok: false}, + {uri: "/api/joker/batman/robin", params: []string{"joker", "batman", "robin"}, ok: true}, + {uri: "/api/joker/batman/robin/1", params: []string{"joker/batman", "robin", "1"}, ok: true}, + {uri: "/api/joker/batman/robin/1/2", params: []string{"joker/batman/robin", "1", "2"}, ok: true}, + {uri: "/api", params: nil, ok: false}, + }, + ) +} +func Test_With_With_Simple_Path(t *testing.T) { + checkCases( + t, + parseParams("/"), + []testCase{ + {uri: "/api", params: nil, ok: false}, + {uri: "", params: []string{}, ok: true}, + {uri: "/", params: []string{}, ok: true}, + }, + ) +} +func Test_With_With_Empty_Path(t *testing.T) { + checkCases( + t, + parseParams(""), + []testCase{ + {uri: "/api", params: nil, ok: false}, + {uri: "", params: []string{}, ok: true}, + {uri: "/", params: []string{}, ok: true}, + }, + ) +} + +func Test_With_With_FileName(t *testing.T) { + checkCases( + t, + parseParams("/config/abc.json"), + []testCase{ + {uri: "/config/abc.json", params: []string{}, ok: true}, + {uri: "config/abc.json", params: nil, ok: false}, + {uri: "/config/efg.json", params: nil, ok: false}, + {uri: "/config", params: nil, ok: false}, + }, + ) +} + +func Test_With_With_FileName_And_Wildcard(t *testing.T) { + checkCases( + t, + parseParams("/config/*.json"), + []testCase{ + {uri: "/config/abc.json", params: []string{"abc.json"}, ok: true}, + {uri: "/config/efg.json", params: []string{"efg.json"}, ok: true}, + //{uri: "/config/efg.csv", params: nil, ok: false},// doesn`t work, current: params: "efg.csv", true + {uri: "config/abc.json", params: nil, ok: false}, + {uri: "/config", params: nil, ok: false}, + }, + ) +} + +func Test_With_With_Simple_Path_And_NoMatch(t *testing.T) { + checkCases( + t, + parseParams("/xyz"), + []testCase{ + {uri: "xyz", params: nil, ok: false}, + {uri: "xyz/", params: nil, ok: false}, + }, + ) +} + +func checkCases(tParent *testing.T, parser parsedParams, tcases []testCase) { + for _, tcase := range tcases { + tParent.Run(fmt.Sprintf("%+v", tcase), func(t *testing.T) { + params, ok := parser.matchParams(tcase.uri) + if !reflect.DeepEqual(params, tcase.params) { + t.Errorf("Path.Match() got = %v, want %v", params, tcase.params) + } + if ok != tcase.ok { + t.Errorf("Path.Match() got1 = %v, want %v", ok, tcase.ok) + } + }) + } +} diff --git a/router.go b/router.go index 6b3e1553..9b457477 100644 --- a/router.go +++ b/router.go @@ -1,107 +1,101 @@ -// πŸš€ Fiber is an Express inspired web framework written in Go with πŸ’– -// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ // πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io package fiber import ( "log" - "regexp" "strings" "time" fasthttp "github.com/valyala/fasthttp" ) -// Route struct +// Route metadata type Route struct { - isGet bool // allows HEAD requests if GET + // Internal fields + use bool // USE matches path prefixes + star bool // Path equals '*' or '/*' + root bool // Path equals '/' + parsed parsedParams // parsed contains parsed params segments - isMiddleware bool // is middleware route - - isStar bool // path == '*' - isSlash bool // path == '/' - isRegex bool // needs regex parsing - - Method string // http method - Path string // original path - Params []string // path params - Regexp *regexp.Regexp // regexp matcher - - Handler func(*Ctx) // ctx handler + // External fields for ctx.Route() method + Path string // Registered route path + Method string // HTTP method + Params []string // Slice containing the params names + Handler func(*Ctx) // Ctx handler } func (app *App) nextRoute(ctx *Ctx) { - // Keep track of head matches - lenr := len(app.routes) - 1 + mINT := methodINT[ctx.method] + // Get stack length + lenr := len(app.routes[mINT]) - 1 + // Loop over stack starting from previous index for ctx.index < lenr { + // Increment stack index ctx.index++ - route := app.routes[ctx.index] - match, values := route.matchRoute(ctx.method, ctx.path) - if match { - ctx.route = route - ctx.values = values - route.Handler(ctx) - // Generate ETag if enabled / found - if app.Settings.ETag { - setETag(ctx, ctx.Fasthttp.Response.Body(), false) - } - return + // Get *Route + route := app.routes[mINT][ctx.index] + // Check if it matches the request path + match, values := route.matchRoute(ctx.path) + // No match, continue + if !match { + continue } + // Match! Set route and param values to Ctx + ctx.route = route + ctx.values = values + // Execute handler + route.Handler(ctx) + // Generate ETag if enabled + if app.Settings.ETag { + setETag(ctx, false) + } + return } - // Send a 404 + // Send a 404 by default if no route is matched if len(ctx.Fasthttp.Response.Body()) == 0 { ctx.SendStatus(404) } } -func (r *Route) matchRoute(method, path string) (match bool, values []string) { - // is route middleware? matches all http methods - if r.isMiddleware { - // '*' or '/' means its a valid match - if r.isStar || r.isSlash { +func (r *Route) matchRoute(path string) (match bool, values []string) { + // Middleware routes allow prefix matches + if r.use { + // Match any path if route equals '*' or '/' + if r.star || r.root { return true, values } - // if midware path starts with req.path + // Middleware matches path prefix if strings.HasPrefix(path, r.Path) { return true, values } - // middlewares dont support regex so bye! + // No prefix match, and we do not allow params in app.use return false, values } - // non-middleware route, http method must match! - // the wildcard method is for .All() & .Use() methods - // If route is GET, also match HEAD requests - if r.Method == method || r.Method[0] == '*' || (r.isGet && len(method) == 4 && method == "HEAD") { - // '*' means we match anything - if r.isStar { - return true, values - } - // simple '/' bool, so you avoid unnecessary comparison for long paths - if r.isSlash && path == "/" { - return true, values - } - // does this route need regex matching? - // does req.path match regex pattern? - if r.isRegex && r.Regexp.MatchString(path) { - // do we have parameters - if len(r.Params) > 0 { - // get values for parameters - matches := r.Regexp.FindAllStringSubmatch(path, -1) - // did we get the values? - if len(matches) > 0 && len(matches[0]) > 1 { - values = matches[0][1:len(matches[0])] - return true, values - } - return false, values - } - return true, values - } - // last thing to do is to check for a simple path match - if len(r.Path) == len(path) && r.Path == path { - return true, values + // '*' wildcard matches any path + if r.star { + return true, values + } + // Check if a single '/' matches + if r.root && path == "/" { + return true, values + } + // Does this route have parameters + if len(r.Params) > 0 { + // Do we have a match? + params, ok := r.parsed.matchParams(path) + // We have a match! + if ok { + return true, params } } + // Check for a simple path match + if len(r.Path) == len(path) && r.Path == path { + return true, values + } + // Nothing match return false, values } @@ -110,7 +104,7 @@ func (app *App) handler(fctx *fasthttp.RequestCtx) { // get fiber context from sync pool ctx := acquireCtx(fctx) defer releaseCtx(ctx) - // attach app poiner and compress settings + // Attach app poiner to access the routes ctx.app = app // Case sensitive routing @@ -149,44 +143,45 @@ func (app *App) registerMethod(method, path string, handlers ...func(*Ctx)) { path = strings.TrimRight(path, "/") } // Set route booleans - var isGet = method == "GET" - var isMiddleware = method == "USE" + var isUse = method == "USE" // Middleware / All allows all HTTP methods - if isMiddleware || method == "ALL" { + if isUse || method == "ALL" { method = "*" } var isStar = path == "*" || path == "/*" // Middleware containing only a `/` equals wildcard - if isMiddleware && path == "/" { + if isUse && path == "/" { isStar = true } - var isSlash = path == "/" - var isRegex = false + var isRoot = path == "/" // Route properties - var Params = getParams(original) - var Regexp *regexp.Regexp - // Params requires regex pattern - if len(Params) > 0 { - regex, err := getRegex(path) - if err != nil { - log.Fatal("Router: Invalid path pattern: " + path) - } - isRegex = true - Regexp = regex - } + var isParsed = parseParams(original) for i := range handlers { - app.routes = append(app.routes, &Route{ - isGet: isGet, - isMiddleware: isMiddleware, - isStar: isStar, - isSlash: isSlash, - isRegex: isRegex, - Method: method, - Path: path, - Params: Params, - Regexp: Regexp, - Handler: handlers[i], - }) + route := &Route{ + use: isUse, + star: isStar, + root: isRoot, + parsed: isParsed, + + Path: path, + Method: method, + Params: isParsed.Keys, + Handler: handlers[i], + } + if method == "*" { + // Add handler to all HTTP methods + for m := range methodINT { + app.addRoute(m, route) + } + continue + } + // Add route to stack + app.addRoute(method, route) + // Add route to HEAD method if GET + if method == MethodGet { + app.addRoute(MethodHead, route) + } + } } @@ -218,13 +213,13 @@ func (app *App) registerStatic(prefix, root string, config ...Static) { root = root[:len(root)-1] } // isSlash ? - var isSlash = prefix == "/" + var isRoot = prefix == "/" if strings.Contains(prefix, "*") { wildcard = true prefix = strings.Split(prefix, "*")[0] } var stripper = len(prefix) - if isSlash { + if isRoot { stripper = 0 } // Fileserver settings @@ -252,30 +247,36 @@ func (app *App) registerStatic(prefix, root string, config ...Static) { } } fileHandler := fs.NewRequestHandler() - app.routes = append(app.routes, &Route{ - isMiddleware: true, - isSlash: isSlash, - Method: "*", - Path: prefix, + route := &Route{ + use: true, + root: isRoot, + Method: "*", + Path: prefix, Handler: func(c *Ctx) { - // Only handle GET & HEAD methods - if c.method == "GET" || c.method == "HEAD" { - // Do stuff - if wildcard { - c.Fasthttp.Request.SetRequestURI(prefix) - } - // Serve file - fileHandler(c.Fasthttp) - - // Finish request if found and not forbidden - status := c.Fasthttp.Response.StatusCode() - if status != 404 && status != 403 { - return - } - // Reset response - c.Fasthttp.Response.Reset() + // Do stuff + if wildcard { + c.Fasthttp.Request.SetRequestURI(prefix) } + // Serve file + fileHandler(c.Fasthttp) + + // Finish request if found and not forbidden + status := c.Fasthttp.Response.StatusCode() + if status != 404 && status != 403 { + return + } + // Reset response + c.Fasthttp.Response.Reset() + // Next middleware c.Next() }, - }) + } + // Add route to stack + app.addRoute(MethodGet, route) + app.addRoute(MethodHead, route) +} + +func (app *App) addRoute(method string, route *Route) { + m := methodINT[method] + app.routes[m] = append(app.routes[m], route) } diff --git a/router_test.go b/router_test.go new file mode 100644 index 00000000..e100bd49 --- /dev/null +++ b/router_test.go @@ -0,0 +1,619 @@ +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ +// πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚠️ This path parser was based on urlpath by @ucarion (MIT License). +// πŸ’– Modified for the Fiber router by @renanbastos93 & @renewerner87 +// πŸ€– ucarion/urlpath - renanbastos93/fastpath - renewerner87/fastpath + +// router benchmarks + +package fiber + +import ( + "testing" +) + +var app *App + +func init() { + app = New() + h := func(c *Ctx) {} + for _, r := range githubAPI { + switch r.method { + case "GET": + app.Get(r.path, h) + case "POST": + app.Post(r.path, h) + case "PUT": + app.Put(r.path, h) + case "PATCH": + app.Patch(r.path, h) + case "DELETE": + app.Delete(r.path, h) + default: + panic("Unknow HTTP method: " + r.method) + } + } +} + +func Benchmark_All_Routes(b *testing.B) { + var match bool + var params []string + for n := 0; n < b.N; n++ { + for _, r := range testRoutes { + match, params = matchRoute(r.method, r.path) + } + if match { + if len(params) > 0 { + + } + } + } +} + +func Benchmark_Last_Route(b *testing.B) { + var match bool + var params []string + for n := 0; n < b.N; n++ { + match, params = matchRoute("DELETE", "/user/keys/1337") + } + if match { + if len(params) > 0 { + + } + } +} +func Benchmark_First_Route(b *testing.B) { + var match bool + var params []string + for n := 0; n < b.N; n++ { + match, params = matchRoute("GET", "/authorizations") + } + if match { + if len(params) > 0 { + + } + } +} + +func matchRoute(method, path string) (match bool, values []string) { + mINT := methodINT[method] + for i := range app.routes[mINT] { + match, values = app.routes[mINT][i].matchRoute(path) + if match { + return + } + } + return +} + +type testRoute struct { + method string + path string +} + +var testRoutes = []testRoute{ + // OAuth Authorizations + {"GET", "/authorizations"}, + {"GET", "/authorizations/1337"}, + {"POST", "/authorizations"}, + {"PUT", "/authorizations/clients/inf1nd873nf8912g9t"}, + {"PATCH", "/authorizations/1337"}, + {"DELETE", "/authorizations/1337"}, + {"GET", "/applications/2nds981mng6azl127y/tokens/sn108hbe1geheibf13f"}, + {"DELETE", "/applications/2nds981mng6azl127y/tokens"}, + {"DELETE", "/applications/2nds981mng6azl127y/tokens/sn108hbe1geheibf13f"}, + + // Activity + {"GET", "/events"}, + {"GET", "/repos/fenny/fiber/events"}, + {"GET", "/networks/fenny/fiber/events"}, + {"GET", "/orgs/gofiber/events"}, + {"GET", "/users/fenny/received_events"}, + {"GET", "/users/fenny/received_events/public"}, + {"GET", "/users/fenny/events"}, + {"GET", "/users/fenny/events/public"}, + {"GET", "/users/fenny/events/orgs/gofiber"}, + {"GET", "/feeds"}, + {"GET", "/notifications"}, + {"GET", "/repos/fenny/fiber/notifications"}, + {"PUT", "/notifications"}, + {"PUT", "/repos/fenny/fiber/notifications"}, + {"GET", "/notifications/threads/1337"}, + {"PATCH", "/notifications/threads/1337"}, + {"GET", "/notifications/threads/1337/subscription"}, + {"PUT", "/notifications/threads/1337/subscription"}, + {"DELETE", "/notifications/threads/1337/subscription"}, + {"GET", "/repos/fenny/fiber/stargazers"}, + {"GET", "/users/fenny/starred"}, + {"GET", "/user/starred"}, + {"GET", "/user/starred/fenny/fiber"}, + {"PUT", "/user/starred/fenny/fiber"}, + {"DELETE", "/user/starred/fenny/fiber"}, + {"GET", "/repos/fenny/fiber/subscribers"}, + {"GET", "/users/fenny/subscriptions"}, + {"GET", "/user/subscriptions"}, + {"GET", "/repos/fenny/fiber/subscription"}, + {"PUT", "/repos/fenny/fiber/subscription"}, + {"DELETE", "/repos/fenny/fiber/subscription"}, + {"GET", "/user/subscriptions/fenny/fiber"}, + {"PUT", "/user/subscriptions/fenny/fiber"}, + {"DELETE", "/user/subscriptions/fenny/fiber"}, + + // Gists + {"GET", "/users/fenny/gists"}, + {"GET", "/gists"}, + {"GET", "/gists/public"}, + {"GET", "/gists/starred"}, + {"GET", "/gists/1337"}, + {"POST", "/gists"}, + {"PATCH", "/gists/1337"}, + {"PUT", "/gists/1337/star"}, + {"DELETE", "/gists/1337/star"}, + {"GET", "/gists/1337/star"}, + {"POST", "/gists/1337/forks"}, + {"DELETE", "/gists/1337"}, + + // Git Data + {"GET", "/repos/fenny/fiber/git/blobs/v948b24g98ubngw9082bn02giub"}, + {"POST", "/repos/fenny/fiber/git/blobs"}, + {"GET", "/repos/fenny/fiber/git/commits/v948b24g98ubngw9082bn02giub"}, + {"POST", "/repos/fenny/fiber/git/commits"}, + {"GET", "/repos/fenny/fiber/git/refs/im/a/wildcard"}, + {"GET", "/repos/fenny/fiber/git/refs"}, + {"POST", "/repos/fenny/fiber/git/refs"}, + {"PATCH", "/repos/fenny/fiber/git/refs/im/a/wildcard"}, + {"DELETE", "/repos/fenny/fiber/git/refs/im/a/wildcard"}, + {"GET", "/repos/fenny/fiber/git/tags/v948b24g98ubngw9082bn02giub"}, + {"POST", "/repos/fenny/fiber/git/tags"}, + {"GET", "/repos/fenny/fiber/git/trees/v948b24g98ubngw9082bn02giub"}, + {"POST", "/repos/fenny/fiber/git/trees"}, + + // Issues + {"GET", "/issues"}, + {"GET", "/user/issues"}, + {"GET", "/orgs/gofiber/issues"}, + {"GET", "/repos/fenny/fiber/issues"}, + {"GET", "/repos/fenny/fiber/issues/1000"}, + {"POST", "/repos/fenny/fiber/issues"}, + {"PATCH", "/repos/fenny/fiber/issues/1000"}, + {"GET", "/repos/fenny/fiber/assignees"}, + {"GET", "/repos/fenny/fiber/assignees/nic"}, + {"GET", "/repos/fenny/fiber/issues/1000/comments"}, + {"GET", "/repos/fenny/fiber/issues/comments"}, + {"GET", "/repos/fenny/fiber/issues/comments/1337"}, + {"POST", "/repos/fenny/fiber/issues/1000/comments"}, + {"PATCH", "/repos/fenny/fiber/issues/comments/1337"}, + {"DELETE", "/repos/fenny/fiber/issues/comments/1337"}, + {"GET", "/repos/fenny/fiber/issues/1000/events"}, + {"GET", "/repos/fenny/fiber/issues/events"}, + {"GET", "/repos/fenny/fiber/issues/events/1337"}, + {"GET", "/repos/fenny/fiber/labels"}, + {"GET", "/repos/fenny/fiber/labels/john"}, + {"POST", "/repos/fenny/fiber/labels"}, + {"PATCH", "/repos/fenny/fiber/labels/john"}, + {"DELETE", "/repos/fenny/fiber/labels/john"}, + {"GET", "/repos/fenny/fiber/issues/1000/labels"}, + {"POST", "/repos/fenny/fiber/issues/1000/labels"}, + {"DELETE", "/repos/fenny/fiber/issues/1000/labels/john"}, + {"PUT", "/repos/fenny/fiber/issues/1000/labels"}, + {"DELETE", "/repos/fenny/fiber/issues/1000/labels"}, + {"GET", "/repos/fenny/fiber/milestones/1000/labels"}, + {"GET", "/repos/fenny/fiber/milestones"}, + {"GET", "/repos/fenny/fiber/milestones/1000"}, + {"POST", "/repos/fenny/fiber/milestones"}, + {"PATCH", "/repos/fenny/fiber/milestones/1000"}, + {"DELETE", "/repos/fenny/fiber/milestones/1000"}, + + // Miscellaneous + {"GET", "/emojis"}, + {"GET", "/gitignore/templates"}, + {"GET", "/gitignore/templates/john"}, + {"POST", "/markdown"}, + {"POST", "/markdown/raw"}, + {"GET", "/meta"}, + {"GET", "/rate_limit"}, + + // Organizations + {"GET", "/users/fenny/orgs"}, + {"GET", "/user/orgs"}, + {"GET", "/orgs/gofiber"}, + {"PATCH", "/orgs/gofiber"}, + {"GET", "/orgs/gofiber/members"}, + {"GET", "/orgs/gofiber/members/fenny"}, + {"DELETE", "/orgs/gofiber/members/fenny"}, + {"GET", "/orgs/gofiber/public_members"}, + {"GET", "/orgs/gofiber/public_members/fenny"}, + {"PUT", "/orgs/gofiber/public_members/fenny"}, + {"DELETE", "/orgs/gofiber/public_members/fenny"}, + {"GET", "/orgs/gofiber/teams"}, + {"GET", "/teams/1337"}, + {"POST", "/orgs/gofiber/teams"}, + {"PATCH", "/teams/1337"}, + {"DELETE", "/teams/1337"}, + {"GET", "/teams/1337/members"}, + {"GET", "/teams/1337/members/fenny"}, + {"PUT", "/teams/1337/members/fenny"}, + {"DELETE", "/teams/1337/members/fenny"}, + {"GET", "/teams/1337/repos"}, + {"GET", "/teams/1337/repos/fenny/fiber"}, + {"PUT", "/teams/1337/repos/fenny/fiber"}, + {"DELETE", "/teams/1337/repos/fenny/fiber"}, + {"GET", "/user/teams"}, + + // Pull Requests + {"GET", "/repos/fenny/fiber/pulls"}, + {"GET", "/repos/fenny/fiber/pulls/1000"}, + {"POST", "/repos/fenny/fiber/pulls"}, + {"PATCH", "/repos/fenny/fiber/pulls/1000"}, + {"GET", "/repos/fenny/fiber/pulls/1000/commits"}, + {"GET", "/repos/fenny/fiber/pulls/1000/files"}, + {"GET", "/repos/fenny/fiber/pulls/1000/merge"}, + {"PUT", "/repos/fenny/fiber/pulls/1000/merge"}, + {"GET", "/repos/fenny/fiber/pulls/1000/comments"}, + {"GET", "/repos/fenny/fiber/pulls/comments"}, + {"GET", "/repos/fenny/fiber/pulls/comments/1000"}, + {"PUT", "/repos/fenny/fiber/pulls/1000/comments"}, + {"PATCH", "/repos/fenny/fiber/pulls/comments/1000"}, + {"DELETE", "/repos/fenny/fiber/pulls/comments/1000"}, + + // Repositories + {"GET", "/user/repos"}, + {"GET", "/users/fenny/repos"}, + {"GET", "/orgs/gofiber/repos"}, + {"GET", "/repositories"}, + {"POST", "/user/repos"}, + {"POST", "/orgs/gofiber/repos"}, + {"GET", "/repos/fenny/fiber"}, + {"PATCH", "/repos/fenny/fiber"}, + {"GET", "/repos/fenny/fiber/contributors"}, + {"GET", "/repos/fenny/fiber/languages"}, + {"GET", "/repos/fenny/fiber/teams"}, + {"GET", "/repos/fenny/fiber/tags"}, + {"GET", "/repos/fenny/fiber/branches"}, + {"GET", "/repos/fenny/fiber/branches/master"}, + {"DELETE", "/repos/fenny/fiber"}, + {"GET", "/repos/fenny/fiber/collaborators"}, + {"GET", "/repos/fenny/fiber/collaborators/fenny"}, + {"PUT", "/repos/fenny/fiber/collaborators/fenny"}, + {"DELETE", "/repos/fenny/fiber/collaborators/fenny"}, + {"GET", "/repos/fenny/fiber/comments"}, + {"GET", "/repos/fenny/fiber/commits/v948b24g98ubngw9082bn02giub/comments"}, + {"POST", "/repos/fenny/fiber/commits/v948b24g98ubngw9082bn02giub/comments"}, + {"GET", "/repos/fenny/fiber/comments/1337"}, + {"PATCH", "/repos/fenny/fiber/comments/1337"}, + {"DELETE", "/repos/fenny/fiber/comments/1337"}, + {"GET", "/repos/fenny/fiber/commits"}, + {"GET", "/repos/fenny/fiber/commits/v948b24g98ubngw9082bn02giub"}, + {"GET", "/repos/fenny/fiber/readme"}, + {"GET", "/repos/fenny/fiber/contents/im/a/wildcard"}, + {"PUT", "/repos/fenny/fiber/contents/im/a/wildcard"}, + {"DELETE", "/repos/fenny/fiber/contents/im/a/wildcard"}, + {"GET", "/repos/fenny/fiber/gzip/google"}, + {"GET", "/repos/fenny/fiber/keys"}, + {"GET", "/repos/fenny/fiber/keys/1337"}, + {"POST", "/repos/fenny/fiber/keys"}, + {"PATCH", "/repos/fenny/fiber/keys/1337"}, + {"DELETE", "/repos/fenny/fiber/keys/1337"}, + {"GET", "/repos/fenny/fiber/downloads"}, + {"GET", "/repos/fenny/fiber/downloads/1337"}, + {"DELETE", "/repos/fenny/fiber/downloads/1337"}, + {"GET", "/repos/fenny/fiber/forks"}, + {"POST", "/repos/fenny/fiber/forks"}, + {"GET", "/repos/fenny/fiber/hooks"}, + {"GET", "/repos/fenny/fiber/hooks/1337"}, + {"POST", "/repos/fenny/fiber/hooks"}, + {"PATCH", "/repos/fenny/fiber/hooks/1337"}, + {"POST", "/repos/fenny/fiber/hooks/1337/tests"}, + {"DELETE", "/repos/fenny/fiber/hooks/1337"}, + {"POST", "/repos/fenny/fiber/merges"}, + {"GET", "/repos/fenny/fiber/releases"}, + {"GET", "/repos/fenny/fiber/releases/1337"}, + {"POST", "/repos/fenny/fiber/releases"}, + {"PATCH", "/repos/fenny/fiber/releases/1337"}, + {"DELETE", "/repos/fenny/fiber/releases/1337"}, + {"GET", "/repos/fenny/fiber/releases/1337/assets"}, + {"GET", "/repos/fenny/fiber/stats/contributors"}, + {"GET", "/repos/fenny/fiber/stats/commit_activity"}, + {"GET", "/repos/fenny/fiber/stats/code_frequency"}, + {"GET", "/repos/fenny/fiber/stats/participation"}, + {"GET", "/repos/fenny/fiber/stats/punch_card"}, + {"GET", "/repos/fenny/fiber/statuses/google"}, + {"POST", "/repos/fenny/fiber/statuses/google"}, + + // Search + {"GET", "/search/repositories"}, + {"GET", "/search/code"}, + {"GET", "/search/issues"}, + {"GET", "/search/users"}, + {"GET", "/legacy/issues/search/fenny/fibersitory/locked/finish"}, + {"GET", "/legacy/repos/search/finish"}, + {"GET", "/legacy/user/search/finish"}, + {"GET", "/legacy/user/email/info@gofiber.io"}, + + // Users + {"GET", "/users/fenny"}, + {"GET", "/user"}, + {"PATCH", "/user"}, + {"GET", "/users"}, + {"GET", "/user/emails"}, + {"POST", "/user/emails"}, + {"DELETE", "/user/emails"}, + {"GET", "/users/fenny/followers"}, + {"GET", "/user/followers"}, + {"GET", "/users/fenny/following"}, + {"GET", "/user/following"}, + {"GET", "/user/following/fenny"}, + {"GET", "/users/fenny/following/renan"}, + {"PUT", "/user/following/fenny"}, + {"DELETE", "/user/following/fenny"}, + {"GET", "/users/fenny/keys"}, + {"GET", "/user/keys"}, + {"GET", "/user/keys/1337"}, + {"POST", "/user/keys"}, + {"PATCH", "/user/keys/1337"}, + {"DELETE", "/user/keys/1337"}, +} + +var githubAPI = []testRoute{ + // OAuth Authorizations + {"GET", "/authorizations"}, + {"GET", "/authorizations/:id"}, + {"POST", "/authorizations"}, + {"PUT", "/authorizations/clients/:client_id"}, + {"PATCH", "/authorizations/:id"}, + {"DELETE", "/authorizations/:id"}, + {"GET", "/applications/:client_id/tokens/:access_token"}, + {"DELETE", "/applications/:client_id/tokens"}, + {"DELETE", "/applications/:client_id/tokens/:access_token"}, + + // Activity + {"GET", "/events"}, + {"GET", "/repos/:owner/:repo/events"}, + {"GET", "/networks/:owner/:repo/events"}, + {"GET", "/orgs/:org/events"}, + {"GET", "/users/:user/received_events"}, + {"GET", "/users/:user/received_events/public"}, + {"GET", "/users/:user/events"}, + {"GET", "/users/:user/events/public"}, + {"GET", "/users/:user/events/orgs/:org"}, + {"GET", "/feeds"}, + {"GET", "/notifications"}, + {"GET", "/repos/:owner/:repo/notifications"}, + {"PUT", "/notifications"}, + {"PUT", "/repos/:owner/:repo/notifications"}, + {"GET", "/notifications/threads/:id"}, + {"PATCH", "/notifications/threads/:id"}, + {"GET", "/notifications/threads/:id/subscription"}, + {"PUT", "/notifications/threads/:id/subscription"}, + {"DELETE", "/notifications/threads/:id/subscription"}, + {"GET", "/repos/:owner/:repo/stargazers"}, + {"GET", "/users/:user/starred"}, + {"GET", "/user/starred"}, + {"GET", "/user/starred/:owner/:repo"}, + {"PUT", "/user/starred/:owner/:repo"}, + {"DELETE", "/user/starred/:owner/:repo"}, + {"GET", "/repos/:owner/:repo/subscribers"}, + {"GET", "/users/:user/subscriptions"}, + {"GET", "/user/subscriptions"}, + {"GET", "/repos/:owner/:repo/subscription"}, + {"PUT", "/repos/:owner/:repo/subscription"}, + {"DELETE", "/repos/:owner/:repo/subscription"}, + {"GET", "/user/subscriptions/:owner/:repo"}, + {"PUT", "/user/subscriptions/:owner/:repo"}, + {"DELETE", "/user/subscriptions/:owner/:repo"}, + + // Gists + {"GET", "/users/:user/gists"}, + {"GET", "/gists"}, + {"GET", "/gists/public"}, + {"GET", "/gists/starred"}, + {"GET", "/gists/:id"}, + {"POST", "/gists"}, + {"PATCH", "/gists/:id"}, + {"PUT", "/gists/:id/star"}, + {"DELETE", "/gists/:id/star"}, + {"GET", "/gists/:id/star"}, + {"POST", "/gists/:id/forks"}, + {"DELETE", "/gists/:id"}, + + // Git Data + {"GET", "/repos/:owner/:repo/git/blobs/:sha"}, + {"POST", "/repos/:owner/:repo/git/blobs"}, + {"GET", "/repos/:owner/:repo/git/commits/:sha"}, + {"POST", "/repos/:owner/:repo/git/commits"}, + {"GET", "/repos/:owner/:repo/git/refs/*"}, + {"GET", "/repos/:owner/:repo/git/refs"}, + {"POST", "/repos/:owner/:repo/git/refs"}, + {"PATCH", "/repos/:owner/:repo/git/refs/*"}, + {"DELETE", "/repos/:owner/:repo/git/refs/*"}, + {"GET", "/repos/:owner/:repo/git/tags/:sha"}, + {"POST", "/repos/:owner/:repo/git/tags"}, + {"GET", "/repos/:owner/:repo/git/trees/:sha"}, + {"POST", "/repos/:owner/:repo/git/trees"}, + + // Issues + {"GET", "/issues"}, + {"GET", "/user/issues"}, + {"GET", "/orgs/:org/issues"}, + {"GET", "/repos/:owner/:repo/issues"}, + {"GET", "/repos/:owner/:repo/issues/:number"}, + {"POST", "/repos/:owner/:repo/issues"}, + {"PATCH", "/repos/:owner/:repo/issues/:number"}, + {"GET", "/repos/:owner/:repo/assignees"}, + {"GET", "/repos/:owner/:repo/assignees/:assignee"}, + {"GET", "/repos/:owner/:repo/issues/:number/comments"}, + {"GET", "/repos/:owner/:repo/issues/comments"}, + {"GET", "/repos/:owner/:repo/issues/comments/:id"}, + {"POST", "/repos/:owner/:repo/issues/:number/comments"}, + {"PATCH", "/repos/:owner/:repo/issues/comments/:id"}, + {"DELETE", "/repos/:owner/:repo/issues/comments/:id"}, + {"GET", "/repos/:owner/:repo/issues/:number/events"}, + {"GET", "/repos/:owner/:repo/issues/events"}, + {"GET", "/repos/:owner/:repo/issues/events/:id"}, + {"GET", "/repos/:owner/:repo/labels"}, + {"GET", "/repos/:owner/:repo/labels/:name"}, + {"POST", "/repos/:owner/:repo/labels"}, + {"PATCH", "/repos/:owner/:repo/labels/:name"}, + {"DELETE", "/repos/:owner/:repo/labels/:name"}, + {"GET", "/repos/:owner/:repo/issues/:number/labels"}, + {"POST", "/repos/:owner/:repo/issues/:number/labels"}, + {"DELETE", "/repos/:owner/:repo/issues/:number/labels/:name"}, + {"PUT", "/repos/:owner/:repo/issues/:number/labels"}, + {"DELETE", "/repos/:owner/:repo/issues/:number/labels"}, + {"GET", "/repos/:owner/:repo/milestones/:number/labels"}, + {"GET", "/repos/:owner/:repo/milestones"}, + {"GET", "/repos/:owner/:repo/milestones/:number"}, + {"POST", "/repos/:owner/:repo/milestones"}, + {"PATCH", "/repos/:owner/:repo/milestones/:number"}, + {"DELETE", "/repos/:owner/:repo/milestones/:number"}, + + // Miscellaneous + {"GET", "/emojis"}, + {"GET", "/gitignore/templates"}, + {"GET", "/gitignore/templates/:name"}, + {"POST", "/markdown"}, + {"POST", "/markdown/raw"}, + {"GET", "/meta"}, + {"GET", "/rate_limit"}, + + // Organizations + {"GET", "/users/:user/orgs"}, + {"GET", "/user/orgs"}, + {"GET", "/orgs/:org"}, + {"PATCH", "/orgs/:org"}, + {"GET", "/orgs/:org/members"}, + {"GET", "/orgs/:org/members/:user"}, + {"DELETE", "/orgs/:org/members/:user"}, + {"GET", "/orgs/:org/public_members"}, + {"GET", "/orgs/:org/public_members/:user"}, + {"PUT", "/orgs/:org/public_members/:user"}, + {"DELETE", "/orgs/:org/public_members/:user"}, + {"GET", "/orgs/:org/teams"}, + {"GET", "/teams/:id"}, + {"POST", "/orgs/:org/teams"}, + {"PATCH", "/teams/:id"}, + {"DELETE", "/teams/:id"}, + {"GET", "/teams/:id/members"}, + {"GET", "/teams/:id/members/:user"}, + {"PUT", "/teams/:id/members/:user"}, + {"DELETE", "/teams/:id/members/:user"}, + {"GET", "/teams/:id/repos"}, + {"GET", "/teams/:id/repos/:owner/:repo"}, + {"PUT", "/teams/:id/repos/:owner/:repo"}, + {"DELETE", "/teams/:id/repos/:owner/:repo"}, + {"GET", "/user/teams"}, + + // Pull Requests + {"GET", "/repos/:owner/:repo/pulls"}, + {"GET", "/repos/:owner/:repo/pulls/:number"}, + {"POST", "/repos/:owner/:repo/pulls"}, + {"PATCH", "/repos/:owner/:repo/pulls/:number"}, + {"GET", "/repos/:owner/:repo/pulls/:number/commits"}, + {"GET", "/repos/:owner/:repo/pulls/:number/files"}, + {"GET", "/repos/:owner/:repo/pulls/:number/merge"}, + {"PUT", "/repos/:owner/:repo/pulls/:number/merge"}, + {"GET", "/repos/:owner/:repo/pulls/:number/comments"}, + {"GET", "/repos/:owner/:repo/pulls/comments"}, + {"GET", "/repos/:owner/:repo/pulls/comments/:number"}, + {"PUT", "/repos/:owner/:repo/pulls/:number/comments"}, + {"PATCH", "/repos/:owner/:repo/pulls/comments/:number"}, + {"DELETE", "/repos/:owner/:repo/pulls/comments/:number"}, + + // Repositories + {"GET", "/user/repos"}, + {"GET", "/users/:user/repos"}, + {"GET", "/orgs/:org/repos"}, + {"GET", "/repositories"}, + {"POST", "/user/repos"}, + {"POST", "/orgs/:org/repos"}, + {"GET", "/repos/:owner/:repo"}, + {"PATCH", "/repos/:owner/:repo"}, + {"GET", "/repos/:owner/:repo/contributors"}, + {"GET", "/repos/:owner/:repo/languages"}, + {"GET", "/repos/:owner/:repo/teams"}, + {"GET", "/repos/:owner/:repo/tags"}, + {"GET", "/repos/:owner/:repo/branches"}, + {"GET", "/repos/:owner/:repo/branches/:branch"}, + {"DELETE", "/repos/:owner/:repo"}, + {"GET", "/repos/:owner/:repo/collaborators"}, + {"GET", "/repos/:owner/:repo/collaborators/:user"}, + {"PUT", "/repos/:owner/:repo/collaborators/:user"}, + {"DELETE", "/repos/:owner/:repo/collaborators/:user"}, + {"GET", "/repos/:owner/:repo/comments"}, + {"GET", "/repos/:owner/:repo/commits/:sha/comments"}, + {"POST", "/repos/:owner/:repo/commits/:sha/comments"}, + {"GET", "/repos/:owner/:repo/comments/:id"}, + {"PATCH", "/repos/:owner/:repo/comments/:id"}, + {"DELETE", "/repos/:owner/:repo/comments/:id"}, + {"GET", "/repos/:owner/:repo/commits"}, + {"GET", "/repos/:owner/:repo/commits/:sha"}, + {"GET", "/repos/:owner/:repo/readme"}, + {"GET", "/repos/:owner/:repo/contents/*"}, + {"PUT", "/repos/:owner/:repo/contents/*"}, + {"DELETE", "/repos/:owner/:repo/contents/*"}, + {"GET", "/repos/:owner/:repo/:archive_format/:ref"}, + {"GET", "/repos/:owner/:repo/keys"}, + {"GET", "/repos/:owner/:repo/keys/:id"}, + {"POST", "/repos/:owner/:repo/keys"}, + {"PATCH", "/repos/:owner/:repo/keys/:id"}, + {"DELETE", "/repos/:owner/:repo/keys/:id"}, + {"GET", "/repos/:owner/:repo/downloads"}, + {"GET", "/repos/:owner/:repo/downloads/:id"}, + {"DELETE", "/repos/:owner/:repo/downloads/:id"}, + {"GET", "/repos/:owner/:repo/forks"}, + {"POST", "/repos/:owner/:repo/forks"}, + {"GET", "/repos/:owner/:repo/hooks"}, + {"GET", "/repos/:owner/:repo/hooks/:id"}, + {"POST", "/repos/:owner/:repo/hooks"}, + {"PATCH", "/repos/:owner/:repo/hooks/:id"}, + {"POST", "/repos/:owner/:repo/hooks/:id/tests"}, + {"DELETE", "/repos/:owner/:repo/hooks/:id"}, + {"POST", "/repos/:owner/:repo/merges"}, + {"GET", "/repos/:owner/:repo/releases"}, + {"GET", "/repos/:owner/:repo/releases/:id"}, + {"POST", "/repos/:owner/:repo/releases"}, + {"PATCH", "/repos/:owner/:repo/releases/:id"}, + {"DELETE", "/repos/:owner/:repo/releases/:id"}, + {"GET", "/repos/:owner/:repo/releases/:id/assets"}, + {"GET", "/repos/:owner/:repo/stats/contributors"}, + {"GET", "/repos/:owner/:repo/stats/commit_activity"}, + {"GET", "/repos/:owner/:repo/stats/code_frequency"}, + {"GET", "/repos/:owner/:repo/stats/participation"}, + {"GET", "/repos/:owner/:repo/stats/punch_card"}, + {"GET", "/repos/:owner/:repo/statuses/:ref"}, + {"POST", "/repos/:owner/:repo/statuses/:ref"}, + + // Search + {"GET", "/search/repositories"}, + {"GET", "/search/code"}, + {"GET", "/search/issues"}, + {"GET", "/search/users"}, + {"GET", "/legacy/issues/search/:owner/:repository/:state/:keyword"}, + {"GET", "/legacy/repos/search/:keyword"}, + {"GET", "/legacy/user/search/:keyword"}, + {"GET", "/legacy/user/email/:email"}, + + // Users + {"GET", "/users/:user"}, + {"GET", "/user"}, + {"PATCH", "/user"}, + {"GET", "/users"}, + {"GET", "/user/emails"}, + {"POST", "/user/emails"}, + {"DELETE", "/user/emails"}, + {"GET", "/users/:user/followers"}, + {"GET", "/user/followers"}, + {"GET", "/users/:user/following"}, + {"GET", "/user/following"}, + {"GET", "/user/following/:user"}, + {"GET", "/users/:user/following/:target_user"}, + {"PUT", "/user/following/:user"}, + {"DELETE", "/user/following/:user"}, + {"GET", "/users/:user/keys"}, + {"GET", "/user/keys"}, + {"GET", "/user/keys/:id"}, + {"POST", "/user/keys"}, + {"PATCH", "/user/keys/:id"}, + {"DELETE", "/user/keys/:id"}, +} diff --git a/utils.go b/utils.go index def8f662..ea93207b 100644 --- a/utils.go +++ b/utils.go @@ -1,6 +1,6 @@ -// πŸš€ Fiber is an Express inspired web framework written in Go with πŸ’– -// πŸ“Œ API Documentation: https://docs.gofiber.io +// ⚑️ Fiber is an Express inspired web framework written in Go with β˜•οΈ // πŸ“ Github Repository: https://github.com/gofiber/fiber +// πŸ“Œ API Documentation: https://docs.gofiber.io package fiber @@ -10,15 +10,14 @@ import ( "hash/crc32" "net" "os" - "path/filepath" - "regexp" "strings" "time" "unsafe" ) -// Document elke line gelijk even -func setETag(ctx *Ctx, body []byte, weak bool) { +// Generate and set ETag header to response +func setETag(ctx *Ctx, weak bool) { + body := ctx.Fasthttp.Response.Body() // Skips ETag if no response body is present if len(body) <= 0 { return @@ -45,7 +44,7 @@ func setETag(ctx *Ctx, body []byte, weak bool) { return } // W/1 != W/2 || W/1 != 2 - ctx.Set("ETag", etag) + ctx.Set(HeaderETag, etag) return } if strings.Contains(clientEtag, etag) { @@ -55,10 +54,10 @@ func setETag(ctx *Ctx, body []byte, weak bool) { return } // 1 != 2 - ctx.Set("ETag", etag) + ctx.Set(HeaderETag, etag) } -func groupPaths(prefix, path string) string { +func getGroupPath(prefix, path string) string { if path == "/" { path = "" } @@ -67,67 +66,6 @@ func groupPaths(prefix, path string) string { return path } -func getParams(path string) (params []string) { - if len(path) < 1 { - return - } - segments := strings.Split(path, "/") - replacer := strings.NewReplacer(":", "", "?", "") - for i := range segments { - s := segments[i] - if s == "" { - continue - } else if s[0] == ':' { - params = append(params, replacer.Replace(s)) - } - if strings.Contains(s, "*") { - params = append(params, "*") - } - } - return -} - -func getRegex(path string) (*regexp.Regexp, error) { - pattern := "^" - segments := strings.Split(path, "/") - for i := range segments { - s := segments[i] - if s == "" { - continue - } - if s[0] == ':' { - if strings.Contains(s, "?") { - pattern += "(?:/([^/]+?))?" - } else { - pattern += "/(?:([^/]+?))" - } - } else if s[0] == '*' { - pattern += "/(.*)" - } else { - pattern += "/" + s - } - } - pattern += "/?$" - regex, err := regexp.Compile(pattern) - return regex, err -} - -func getFiles(root string) (files []string, dir bool, err error) { - root = filepath.Clean(root) - if _, err := os.Lstat(root); err != nil { - return files, dir, fmt.Errorf("%s", err) - } - err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error { - if !info.IsDir() { - files = append(files, path) - } else { - dir = true - } - return err - }) - return -} - func getMIME(extension string) (mime string) { if extension == "" { return mime @@ -228,8 +166,21 @@ func parseTokenList(noneMatchBytes []byte) []string { return list } +// HTTP methods and their unique INTs +var methodINT = map[string]int{ + MethodGet: 0, + MethodHead: 1, + MethodPost: 2, + MethodPut: 3, + MethodPatch: 4, + MethodDelete: 5, + MethodConnect: 6, + MethodOptions: 7, + MethodTrace: 8, +} + // HTTP status codes were copied from net/http. -var statusMessages = map[int]string{ +var statusMessage = map[int]string{ 100: "Continue", 101: "Switching Protocols", 102: "Processing", @@ -296,18 +247,15 @@ var statusMessages = map[int]string{ // MIME types were copied from labstack/echo const ( - MIMETextXML = "text/xml" - MIMETextHTML = "text/html" - MIMETextPlain = "text/plain" - + MIMETextXML = "text/xml" + MIMETextHTML = "text/html" + MIMETextPlain = "text/plain" MIMEApplicationJSON = "application/json" MIMEApplicationJavaScript = "application/javascript" MIMEApplicationXML = "application/xml" MIMEApplicationForm = "application/x-www-form-urlencoded" - - MIMEMultipartForm = "multipart/form-data" - - MIMEOctetStream = "application/octet-stream" + MIMEMultipartForm = "multipart/form-data" + MIMEOctetStream = "application/octet-stream" ) // MIME types were copied from nginx/mime.types. @@ -542,110 +490,77 @@ const ( // HTTP Headers were copied from net/http. const ( - // Authentication - HeaderAuthorization = "Authorization" - HeaderProxyAuthenticate = "Proxy-Authenticate" - HeaderProxyAuthorization = "Proxy-Authorization" - HeaderWWWAuthenticate = "WWW-Authenticate" - - // Caching - HeaderAge = "Age" - HeaderCacheControl = "Cache-Control" - HeaderClearSiteData = "Clear-Site-Data" - HeaderExpires = "Expires" - HeaderPragma = "Pragma" - HeaderWarning = "Warning" - - // Client hints - HeaderAcceptCH = "Accept-CH" - HeaderAcceptCHLifetime = "Accept-CH-Lifetime" - HeaderContentDPR = "Content-DPR" - HeaderDPR = "DPR" - HeaderEarlyData = "Early-Data" - HeaderSaveData = "Save-Data" - HeaderViewportWidth = "Viewport-Width" - HeaderWidth = "Width" - - // Conditionals - HeaderETag = "ETag" - HeaderIfMatch = "If-Match" - HeaderIfModifiedSince = "If-Modified-Since" - HeaderIfNoneMatch = "If-None-Match" - HeaderIfUnmodifiedSince = "If-Unmodified-Since" - HeaderLastModified = "Last-Modified" - HeaderVary = "Vary" - - // Connection management - HeaderConnection = "Connection" - HeaderKeepAlive = "Keep-Alive" - - // Content negotiation - HeaderAccept = "Accept" - HeaderAcceptCharset = "Accept-Charset" - HeaderAcceptEncoding = "Accept-Encoding" - HeaderAcceptLanguage = "Accept-Language" - - // Controls - HeaderCookie = "Cookie" - HeaderExpect = "Expect" - HeaderMaxForwards = "Max-Forwards" - HeaderSetCookie = "Set-Cookie" - - // CORS - HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials" - HeaderAccessControlAllowHeaders = "Access-Control-Allow-Headers" - HeaderAccessControlAllowMethods = "Access-Control-Allow-Methods" - HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin" - HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers" - HeaderAccessControlMaxAge = "Access-Control-Max-Age" - HeaderAccessControlRequestHeaders = "Access-Control-Request-Headers" - HeaderAccessControlRequestMethod = "Access-Control-Request-Method" - HeaderOrigin = "Origin" - HeaderTimingAllowOrigin = "Timing-Allow-Origin" - HeaderXPermittedCrossDomainPolicies = "X-Permitted-Cross-Domain-Policies" - - // Do Not Track - HeaderDNT = "DNT" - HeaderTk = "Tk" - - // Downloads - HeaderContentDisposition = "Content-Disposition" - - // Message body information - HeaderContentEncoding = "Content-Encoding" - HeaderContentLanguage = "Content-Language" - HeaderContentLength = "Content-Length" - HeaderContentLocation = "Content-Location" - HeaderContentType = "Content-Type" - - // Proxies - HeaderForwarded = "Forwarded" - HeaderVia = "Via" - HeaderXForwardedFor = "X-Forwarded-For" - HeaderXForwardedHost = "X-Forwarded-Host" - HeaderXForwardedProto = "X-Forwarded-Proto" - - // Redirects - HeaderLocation = "Location" - - // Request context - HeaderFrom = "From" - HeaderHost = "Host" - HeaderReferer = "Referer" - HeaderReferrerPolicy = "Referrer-Policy" - HeaderUserAgent = "User-Agent" - - // Response context - HeaderAllow = "Allow" - HeaderServer = "Server" - - // Range requests - HeaderAcceptRanges = "Accept-Ranges" - HeaderContentRange = "Content-Range" - HeaderIfRange = "If-Range" - HeaderRange = "Range" - - // Security + HeaderAuthorization = "Authorization" + HeaderProxyAuthenticate = "Proxy-Authenticate" + HeaderProxyAuthorization = "Proxy-Authorization" + HeaderWWWAuthenticate = "WWW-Authenticate" + HeaderAge = "Age" + HeaderCacheControl = "Cache-Control" + HeaderClearSiteData = "Clear-Site-Data" + HeaderExpires = "Expires" + HeaderPragma = "Pragma" + HeaderWarning = "Warning" + HeaderAcceptCH = "Accept-CH" + HeaderAcceptCHLifetime = "Accept-CH-Lifetime" + HeaderContentDPR = "Content-DPR" + HeaderDPR = "DPR" + HeaderEarlyData = "Early-Data" + HeaderSaveData = "Save-Data" + HeaderViewportWidth = "Viewport-Width" + HeaderWidth = "Width" + HeaderETag = "ETag" + HeaderIfMatch = "If-Match" + HeaderIfModifiedSince = "If-Modified-Since" + HeaderIfNoneMatch = "If-None-Match" + HeaderIfUnmodifiedSince = "If-Unmodified-Since" + HeaderLastModified = "Last-Modified" + HeaderVary = "Vary" + HeaderConnection = "Connection" + HeaderKeepAlive = "Keep-Alive" + HeaderAccept = "Accept" + HeaderAcceptCharset = "Accept-Charset" + HeaderAcceptEncoding = "Accept-Encoding" + HeaderAcceptLanguage = "Accept-Language" + HeaderCookie = "Cookie" + HeaderExpect = "Expect" + HeaderMaxForwards = "Max-Forwards" + HeaderSetCookie = "Set-Cookie" + HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials" + HeaderAccessControlAllowHeaders = "Access-Control-Allow-Headers" + HeaderAccessControlAllowMethods = "Access-Control-Allow-Methods" + HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin" + HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers" + HeaderAccessControlMaxAge = "Access-Control-Max-Age" + HeaderAccessControlRequestHeaders = "Access-Control-Request-Headers" + HeaderAccessControlRequestMethod = "Access-Control-Request-Method" + HeaderOrigin = "Origin" + HeaderTimingAllowOrigin = "Timing-Allow-Origin" + HeaderXPermittedCrossDomainPolicies = "X-Permitted-Cross-Domain-Policies" + HeaderDNT = "DNT" + HeaderTk = "Tk" + HeaderContentDisposition = "Content-Disposition" + HeaderContentEncoding = "Content-Encoding" + HeaderContentLanguage = "Content-Language" + HeaderContentLength = "Content-Length" + HeaderContentLocation = "Content-Location" + HeaderContentType = "Content-Type" + HeaderForwarded = "Forwarded" + HeaderVia = "Via" + HeaderXForwardedFor = "X-Forwarded-For" + HeaderXForwardedHost = "X-Forwarded-Host" + HeaderXForwardedProto = "X-Forwarded-Proto" + HeaderLocation = "Location" + HeaderFrom = "From" + HeaderHost = "Host" + HeaderReferer = "Referer" + HeaderReferrerPolicy = "Referrer-Policy" + HeaderUserAgent = "User-Agent" + HeaderAllow = "Allow" + HeaderServer = "Server" + HeaderAcceptRanges = "Accept-Ranges" + HeaderContentRange = "Content-Range" + HeaderIfRange = "If-Range" + HeaderRange = "Range" HeaderContentSecurityPolicy = "Content-Security-Policy" HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only" HeaderCrossOriginResourcePolicy = "Cross-Origin-Resource-Policy" @@ -660,107 +575,94 @@ const ( HeaderXFrameOptions = "X-Frame-Options" HeaderXPoweredBy = "X-Powered-By" HeaderXXSSProtection = "X-XSS-Protection" - - // Server-sent event - HeaderLastEventID = "Last-Event-ID" - HeaderNEL = "NEL" - HeaderPingFrom = "Ping-From" - HeaderPingTo = "Ping-To" - HeaderReportTo = "Report-To" - - // Transfer coding - HeaderTE = "TE" - HeaderTrailer = "Trailer" - HeaderTransferEncoding = "Transfer-Encoding" - - // WebSockets - HeaderSecWebSocketAccept = "Sec-WebSocket-Accept" - HeaderSecWebSocketExtensions = "Sec-WebSocket-Extensions" - HeaderSecWebSocketKey = "Sec-WebSocket-Key" - HeaderSecWebSocketProtocol = "Sec-WebSocket-Protocol" - HeaderSecWebSocketVersion = "Sec-WebSocket-Version" - - // Other - HeaderAcceptPatch = "Accept-Patch" - HeaderAcceptPushPolicy = "Accept-Push-Policy" - HeaderAcceptSignature = "Accept-Signature" - HeaderAltSvc = "Alt-Svc" - HeaderDate = "Date" - HeaderIndex = "Index" - HeaderLargeAllocation = "Large-Allocation" - HeaderLink = "Link" - HeaderPushPolicy = "Push-Policy" - HeaderRetryAfter = "Retry-After" - HeaderServerTiming = "Server-Timing" - HeaderSignature = "Signature" - HeaderSignedHeaders = "Signed-Headers" - HeaderSourceMap = "SourceMap" - HeaderUpgrade = "Upgrade" - HeaderXDNSPrefetchControl = "X-DNS-Prefetch-Control" - HeaderXPingback = "X-Pingback" - HeaderXRequestID = "X-Request-ID" - HeaderXRequestedWith = "X-Requested-With" - HeaderXRobotsTag = "X-Robots-Tag" - HeaderXUACompatible = "X-UA-Compatible" + HeaderLastEventID = "Last-Event-ID" + HeaderNEL = "NEL" + HeaderPingFrom = "Ping-From" + HeaderPingTo = "Ping-To" + HeaderReportTo = "Report-To" + HeaderTE = "TE" + HeaderTrailer = "Trailer" + HeaderTransferEncoding = "Transfer-Encoding" + HeaderSecWebSocketAccept = "Sec-WebSocket-Accept" + HeaderSecWebSocketExtensions = "Sec-WebSocket-Extensions" + HeaderSecWebSocketKey = "Sec-WebSocket-Key" + HeaderSecWebSocketProtocol = "Sec-WebSocket-Protocol" + HeaderSecWebSocketVersion = "Sec-WebSocket-Version" + HeaderAcceptPatch = "Accept-Patch" + HeaderAcceptPushPolicy = "Accept-Push-Policy" + HeaderAcceptSignature = "Accept-Signature" + HeaderAltSvc = "Alt-Svc" + HeaderDate = "Date" + HeaderIndex = "Index" + HeaderLargeAllocation = "Large-Allocation" + HeaderLink = "Link" + HeaderPushPolicy = "Push-Policy" + HeaderRetryAfter = "Retry-After" + HeaderServerTiming = "Server-Timing" + HeaderSignature = "Signature" + HeaderSignedHeaders = "Signed-Headers" + HeaderSourceMap = "SourceMap" + HeaderUpgrade = "Upgrade" + HeaderXDNSPrefetchControl = "X-DNS-Prefetch-Control" + HeaderXPingback = "X-Pingback" + HeaderXRequestID = "X-Request-ID" + HeaderXRequestedWith = "X-Requested-With" + HeaderXRobotsTag = "X-Robots-Tag" + HeaderXUACompatible = "X-UA-Compatible" ) // HTTP status codes were copied from net/http. const ( - StatusContinue = 100 // RFC 7231, 6.2.1 - StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2 - StatusProcessing = 102 // RFC 2518, 10.1 - StatusEarlyHints = 103 // RFC 8297 - - StatusOK = 200 // RFC 7231, 6.3.1 - StatusCreated = 201 // RFC 7231, 6.3.2 - StatusAccepted = 202 // RFC 7231, 6.3.3 - StatusNonAuthoritativeInfo = 203 // RFC 7231, 6.3.4 - StatusNoContent = 204 // RFC 7231, 6.3.5 - StatusResetContent = 205 // RFC 7231, 6.3.6 - StatusPartialContent = 206 // RFC 7233, 4.1 - StatusMultiStatus = 207 // RFC 4918, 11.1 - StatusAlreadyReported = 208 // RFC 5842, 7.1 - StatusIMUsed = 226 // RFC 3229, 10.4.1 - - StatusMultipleChoices = 300 // RFC 7231, 6.4.1 - StatusMovedPermanently = 301 // RFC 7231, 6.4.2 - StatusFound = 302 // RFC 7231, 6.4.3 - StatusSeeOther = 303 // RFC 7231, 6.4.4 - StatusNotModified = 304 // RFC 7232, 4.1 - StatusUseProxy = 305 // RFC 7231, 6.4.5 - - StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7 - StatusPermanentRedirect = 308 // RFC 7538, 3 - - StatusBadRequest = 400 // RFC 7231, 6.5.1 - StatusUnauthorized = 401 // RFC 7235, 3.1 - StatusPaymentRequired = 402 // RFC 7231, 6.5.2 - StatusForbidden = 403 // RFC 7231, 6.5.3 - StatusNotFound = 404 // RFC 7231, 6.5.4 - StatusMethodNotAllowed = 405 // RFC 7231, 6.5.5 - StatusNotAcceptable = 406 // RFC 7231, 6.5.6 - StatusProxyAuthRequired = 407 // RFC 7235, 3.2 - StatusRequestTimeout = 408 // RFC 7231, 6.5.7 - StatusConflict = 409 // RFC 7231, 6.5.8 - StatusGone = 410 // RFC 7231, 6.5.9 - StatusLengthRequired = 411 // RFC 7231, 6.5.10 - StatusPreconditionFailed = 412 // RFC 7232, 4.2 - StatusRequestEntityTooLarge = 413 // RFC 7231, 6.5.11 - StatusRequestURITooLong = 414 // RFC 7231, 6.5.12 - StatusUnsupportedMediaType = 415 // RFC 7231, 6.5.13 - StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4 - StatusExpectationFailed = 417 // RFC 7231, 6.5.14 - StatusTeapot = 418 // RFC 7168, 2.3.3 - StatusMisdirectedRequest = 421 // RFC 7540, 9.1.2 - StatusUnprocessableEntity = 422 // RFC 4918, 11.2 - StatusLocked = 423 // RFC 4918, 11.3 - StatusFailedDependency = 424 // RFC 4918, 11.4 - StatusUpgradeRequired = 426 // RFC 7231, 6.5.15 - StatusPreconditionRequired = 428 // RFC 6585, 3 - StatusTooManyRequests = 429 // RFC 6585, 4 - StatusRequestHeaderFieldsTooLarge = 431 // RFC 6585, 5 - StatusUnavailableForLegalReasons = 451 // RFC 7725, 3 - + StatusContinue = 100 // RFC 7231, 6.2.1 + StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2 + StatusProcessing = 102 // RFC 2518, 10.1 + StatusEarlyHints = 103 // RFC 8297 + StatusOK = 200 // RFC 7231, 6.3.1 + StatusCreated = 201 // RFC 7231, 6.3.2 + StatusAccepted = 202 // RFC 7231, 6.3.3 + StatusNonAuthoritativeInfo = 203 // RFC 7231, 6.3.4 + StatusNoContent = 204 // RFC 7231, 6.3.5 + StatusResetContent = 205 // RFC 7231, 6.3.6 + StatusPartialContent = 206 // RFC 7233, 4.1 + StatusMultiStatus = 207 // RFC 4918, 11.1 + StatusAlreadyReported = 208 // RFC 5842, 7.1 + StatusIMUsed = 226 // RFC 3229, 10.4.1 + StatusMultipleChoices = 300 // RFC 7231, 6.4.1 + StatusMovedPermanently = 301 // RFC 7231, 6.4.2 + StatusFound = 302 // RFC 7231, 6.4.3 + StatusSeeOther = 303 // RFC 7231, 6.4.4 + StatusNotModified = 304 // RFC 7232, 4.1 + StatusUseProxy = 305 // RFC 7231, 6.4.5 + StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7 + StatusPermanentRedirect = 308 // RFC 7538, 3 + StatusBadRequest = 400 // RFC 7231, 6.5.1 + StatusUnauthorized = 401 // RFC 7235, 3.1 + StatusPaymentRequired = 402 // RFC 7231, 6.5.2 + StatusForbidden = 403 // RFC 7231, 6.5.3 + StatusNotFound = 404 // RFC 7231, 6.5.4 + StatusMethodNotAllowed = 405 // RFC 7231, 6.5.5 + StatusNotAcceptable = 406 // RFC 7231, 6.5.6 + StatusProxyAuthRequired = 407 // RFC 7235, 3.2 + StatusRequestTimeout = 408 // RFC 7231, 6.5.7 + StatusConflict = 409 // RFC 7231, 6.5.8 + StatusGone = 410 // RFC 7231, 6.5.9 + StatusLengthRequired = 411 // RFC 7231, 6.5.10 + StatusPreconditionFailed = 412 // RFC 7232, 4.2 + StatusRequestEntityTooLarge = 413 // RFC 7231, 6.5.11 + StatusRequestURITooLong = 414 // RFC 7231, 6.5.12 + StatusUnsupportedMediaType = 415 // RFC 7231, 6.5.13 + StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4 + StatusExpectationFailed = 417 // RFC 7231, 6.5.14 + StatusTeapot = 418 // RFC 7168, 2.3.3 + StatusMisdirectedRequest = 421 // RFC 7540, 9.1.2 + StatusUnprocessableEntity = 422 // RFC 4918, 11.2 + StatusLocked = 423 // RFC 4918, 11.3 + StatusFailedDependency = 424 // RFC 4918, 11.4 + StatusUpgradeRequired = 426 // RFC 7231, 6.5.15 + StatusPreconditionRequired = 428 // RFC 6585, 3 + StatusTooManyRequests = 429 // RFC 6585, 4 + StatusRequestHeaderFieldsTooLarge = 431 // RFC 6585, 5 + StatusUnavailableForLegalReasons = 451 // RFC 7725, 3 StatusInternalServerError = 500 // RFC 7231, 6.6.1 StatusNotImplemented = 501 // RFC 7231, 6.6.2 StatusBadGateway = 502 // RFC 7231, 6.6.3