diff --git a/.github/README.md b/.github/README.md index 375399c6..6e3b39dd 100644 --- a/.github/README.md +++ b/.github/README.md @@ -65,7 +65,7 @@ - +

@@ -471,15 +471,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -496,6 +497,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ Media @@ -507,6 +510,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ Contribute @@ -530,6 +534,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -548,3 +553,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_de.md b/.github/README_de.md index 657fe1b4..f47f01e1 100644 --- a/.github/README_de.md +++ b/.github/README_de.md @@ -65,7 +65,7 @@ - +

@@ -467,15 +467,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -492,6 +493,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ Medien @@ -503,6 +506,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ Mitwirken @@ -526,6 +530,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -541,6 +546,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors](https://github.com/gofiber/fiber/graphs/contributors). `Fiber` is free and open-source software licensed under the [MIT License](https://github.com/gofiber/fiber/blob/master/LICENSE). Official logo was created by [Vic Shรณstak](https://github.com/koddr) and distributed under [Creative Commons](https://creativecommons.org/licenses/by-sa/4.0/) license (CC BY-SA 4.0 International). -**Third-party library licenses** +**Third-party MIT licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) \ No newline at end of file diff --git a/.github/README_es.md b/.github/README_es.md index 8c486441..ab456b0d 100644 --- a/.github/README_es.md +++ b/.github/README_es.md @@ -65,7 +65,7 @@ - +

@@ -467,15 +467,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -492,6 +493,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ Medios @@ -503,6 +506,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ Contribuir @@ -526,6 +530,7 @@ Fiber es un proyecto open source que se mantiene a travรฉs de donaciones para pa | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -544,3 +549,4 @@ Copyright (c) 2019-presente [Fenny](https://github.com/fenny) y [contribuyentes] **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_fr.md b/.github/README_fr.md index 1cb2ccd7..20905b91 100644 --- a/.github/README_fr.md +++ b/.github/README_fr.md @@ -65,7 +65,7 @@ - +

@@ -467,15 +467,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -492,6 +493,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ Media @@ -503,6 +506,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ Contribuer @@ -526,6 +530,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -544,3 +549,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_he.md b/.github/README_he.md index 1598b2eb..aa670025 100644 --- a/.github/README_he.md +++ b/.github/README_he.md @@ -66,7 +66,7 @@ - +

@@ -579,15 +579,16 @@ For an more _maintainable_ middleware _ecosystem_, we've put official [middlewar
-- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -615,6 +616,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen)
@@ -630,7 +633,9 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Is switching from Express to Fiber worth it? ๐Ÿค”](https://dev.to/koddr/are-sure-what-your-lovely-web-framework-running-so-fast-2jl1) โ€” _01 Apr 2020_ - [Creating Fast APIs In Go Using Fiber](https://dev.to/jozsefsallai/creating-fast-apis-in-go-using-fiber-59m9) โ€” _07 Apr 2020_ - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ +- [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_
@@ -672,6 +677,7 @@ Fiber ื”ื™ื ืคืจื•ื™ืงื˜ ืงื•ื“ ืคืชื•ื— ืฉืชืฉืœื•ื ื—ืฉื•ื‘ื•ื ืชื™ื• ืžืกืช | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -702,4 +708,5 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **ืจื™ืฉื™ื•ื ื•ืช ืฉืœ ืกืคืจื™ื•ืช ืฆื“ ืฉืœื™ืฉื™** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE)
diff --git a/.github/README_id.md b/.github/README_id.md index 046c863b..9a8abd5e 100644 --- a/.github/README_id.md +++ b/.github/README_id.md @@ -65,7 +65,7 @@ - +

@@ -469,15 +469,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -494,6 +495,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ Media @@ -505,6 +508,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ Berkontribusi @@ -528,6 +532,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -546,3 +551,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_ja.md b/.github/README_ja.md index 090d5c0e..94c33291 100644 --- a/.github/README_ja.md +++ b/.github/README_ja.md @@ -65,7 +65,7 @@ - +

@@ -471,15 +471,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -496,6 +497,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ ใƒกใƒ‡ใ‚ฃใ‚ข @@ -507,6 +510,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ ่ฒข็Œฎใ™ใ‚‹ @@ -530,6 +534,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -548,3 +553,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_ko.md b/.github/README_ko.md index a87c1c7d..1ded80c0 100644 --- a/.github/README_ko.md +++ b/.github/README_ko.md @@ -65,7 +65,7 @@ - +

@@ -471,15 +471,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -496,6 +497,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ ๋ฏธ๋””์–ด @@ -507,6 +510,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ ๊ธฐ์—ฌ @@ -530,6 +534,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -548,3 +553,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_nl.md b/.github/README_nl.md index d2914826..4906c749 100644 --- a/.github/README_nl.md +++ b/.github/README_nl.md @@ -65,7 +65,7 @@ - +

@@ -471,15 +471,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -496,6 +497,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ Media @@ -507,6 +510,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ Bijdragen @@ -530,6 +534,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -548,3 +553,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_pt.md b/.github/README_pt.md index fc842d93..99ca0477 100644 --- a/.github/README_pt.md +++ b/.github/README_pt.md @@ -65,7 +65,7 @@ - +

@@ -467,15 +467,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -492,6 +493,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ Mรญdia @@ -503,6 +506,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ Contribuindo @@ -526,6 +530,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -544,3 +549,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_ru.md b/.github/README_ru.md index 298b93ee..670e12a3 100644 --- a/.github/README_ru.md +++ b/.github/README_ru.md @@ -65,7 +65,7 @@ - +

@@ -469,15 +469,16 @@ func main() { ะงั‚ะพะฑั‹ ัะพะทะดะฐั‚ัŒ ะฑะพะปะตะต _ะฟะพะดะดะตั€ะถะธะฒะฐะตะผัƒัŽ_ middleware _ัะบะพัะธัั‚ะตะผัƒ_, ะผั‹ ะฒั‹ะฝะตัะปะธ [middlewares](https://docs.gofiber.io/middleware) ะฒ ะพั‚ะดะตะปัŒะฝั‹ะต ั€ะตะฟะพะทะธั‚ะพั€ะธะธ: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -495,6 +496,8 @@ func main() { - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ ะœะตะดะธะฐ @@ -506,6 +509,7 @@ func main() { - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ ะŸะพะผะพั‰ัŒ ะฟั€ะพะตะบั‚ัƒ @@ -531,6 +535,7 @@ Fiber โ€” ัั‚ะพ ะฟั€ะพะตะบั‚ ั ะพั‚ะบั€ั‹ั‚ั‹ะผ ะธัั…ะพะดะฝั‹ะผ ะบะพะดะพะผ, | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -549,3 +554,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_tr.md b/.github/README_tr.md index de92f9eb..df801890 100644 --- a/.github/README_tr.md +++ b/.github/README_tr.md @@ -65,7 +65,7 @@ - +

@@ -465,15 +465,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -490,17 +491,21 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ 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_ -- [Fiber released v1.7! ๐ŸŽ‰ What's new and is it still fast, flexible and friendly?](https://dev.to/koddr/fiber-v2-is-out-now-what-s-new-and-is-he-still-fast-flexible-and-friendly-3ipf) โ€” _21 ลžubat 2020_ -- [๐Ÿš€ Fiber v1.8. What's new, updated and re-thinked?](https://dev.to/koddr/fiber-v1-8-what-s-new-updated-and-re-thinked-339h) โ€” _03 Mart 2020_ -- [Is switching from Express to Fiber worth it? ๐Ÿค”](https://dev.to/koddr/are-sure-what-your-lovely-web-framework-running-so-fast-2jl1) โ€” _01 Nisan 2020_ -- [Creating Fast APIs In Go Using Fiber](https://dev.to/jozsefsallai/creating-fast-apis-in-go-using-fiber-59m9) โ€” _07 Nisan 2020_ -- [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Nisan 2020_ -- [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Nisan 2020_ +- [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_ +- [Fiber released v1.7! ๐ŸŽ‰ What's new and is it still fast, flexible and friendly?](https://dev.to/koddr/fiber-v2-is-out-now-what-s-new-and-is-he-still-fast-flexible-and-friendly-3ipf) โ€” _21 Feb 2020_ +- [๐Ÿš€ Fiber v1.8. What's new, updated and re-thinked?](https://dev.to/koddr/fiber-v1-8-what-s-new-updated-and-re-thinked-339h) โ€” _03 Mar 2020_ +- [Is switching from Express to Fiber worth it? ๐Ÿค”](https://dev.to/koddr/are-sure-what-your-lovely-web-framework-running-so-fast-2jl1) โ€” _01 Apr 2020_ +- [Creating Fast APIs In Go Using Fiber](https://dev.to/jozsefsallai/creating-fast-apis-in-go-using-fiber-59m9) โ€” _07 Apr 2020_ +- [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ +- [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ Destek @@ -523,6 +528,7 @@ Fiber, alan adฤฑ, gitbook, netlify, serverless yer saฤŸlayฤฑcฤฑsฤฑ giderleri ve | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -541,3 +547,4 @@ Telif (c) 2019-gรผnรผmรผz [Fenny](https://github.com/fenny) ve [Contributors](ht **3. Parti yazฤฑlฤฑm lisanlarฤฑ** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/.github/README_zh-CN.md b/.github/README_zh-CN.md index ccccad8f..a2a8c158 100644 --- a/.github/README_zh-CN.md +++ b/.github/README_zh-CN.md @@ -65,7 +65,7 @@ - +

@@ -470,15 +470,16 @@ func main() { For an more _maintainable_ middleware _ecosystem_, we've put official [middlewares](https://docs.gofiber.io/middleware) into separate repositories: -- [gofiber/basicauth](https://github.com/gofiber/basicauth) -- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/compression](https://github.com/gofiber/compression) +- [gofiber/basicauth](https://github.com/gofiber/basicauth) - [gofiber/requestid](https://github.com/gofiber/requestid) - [gofiber/websocket](https://github.com/gofiber/websocket) +- [gofiber/keyauth](https://github.com/gofiber/keyauth) - [gofiber/rewrite](https://github.com/gofiber/rewrite) - [gofiber/recover](https://github.com/gofiber/recover) - [gofiber/limiter](https://github.com/gofiber/limiter) - [gofiber/session](https://github.com/gofiber/session) +- [gofiber/adaptor](https://github.com/gofiber/adaptor) - [gofiber/logger](https://github.com/gofiber/logger) - [gofiber/helmet](https://github.com/gofiber/helmet) - [gofiber/embed](https://github.com/gofiber/embed) @@ -495,6 +496,8 @@ This is a list of middlewares that are created by the Fiber community, please cr - [arsmn/fiber-introspect](https://github.com/arsmn/fiber-introspect) - [shareed2k/fiber_tracing](https://github.com/shareed2k/fiber_tracing) - [shareed2k/fiber_limiter](https://github.com/shareed2k/fiber_limiter) +- [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate) +- [arsmn/gqlgen](https://github.com/arsmn/gqlgen) ## ๐Ÿ’ฌ ๅช’ไฝ“ @@ -506,6 +509,7 @@ This is a list of middlewares that are created by the Fiber community, please cr - [Building a Basic REST API in Go using Fiber](https://tutorialedge.net/golang/basic-rest-api-go-fiber/) - _23 Apr 2020_ - [๐Ÿ“บ Building a REST API using GORM and Fiber](https://youtu.be/Iq2qT0fRhAA) - _25 Apr 2020_ - [๐ŸŒŽ Create a travel list app with Go, Fiber, Angular, MongoDB and Google Cloud Secret Manager](https://blog.yongweilun.me/create-a-travel-list-app-with-go-fiber-angular-mongodb-and-google-cloud-secret-manager-ck9fgxy0p061pcss1xt1ubu8t) - _25 Apr 2020_ +- [Fiber v1.9.6 ๐Ÿ”ฅ How to improve performance by 817% and stay fast, flexible and friendly?](https://dev.to/koddr/fiber-v1-9-5-how-to-improve-performance-by-817-and-stay-fast-flexible-and-friendly-2dp6) - _12 May 2020_ ## ๐Ÿ‘ ่ดก็Œฎ @@ -529,6 +533,7 @@ Fiber is an open source project that runs on donations to pay the bills e.g. our | ![](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/29042462?s=25 ) | [@lapolinar](https://github.com/lapolinar) | โ˜• 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 | @@ -547,3 +552,4 @@ Copyright (c) 2019-present [Fenny](https://github.com/fenny) and [Contributors]( **Third-party library licenses** - [FastHTTP](https://github.com/valyala/fasthttp/blob/master/LICENSE) - [Schema](https://github.com/gorilla/schema/blob/master/LICENSE) +- [bytebufferpool](https://github.com/valyala/bytebufferpool/blob/master/LICENSE) diff --git a/app.go b/app.go index 310940cd..d08147b7 100644 --- a/app.go +++ b/app.go @@ -25,7 +25,7 @@ import ( ) // Version of current package -const Version = "1.9.6" +const Version = "1.9.7" // Map is a shortcut for map[string]interface{} type Map map[string]interface{} @@ -33,8 +33,7 @@ type Map map[string]interface{} // App denotes the Fiber application. type App struct { // Internal fields - testconn *testConn // Test connection - routes [][]*Route // Route stack + routes [][]*Route // Route stack // External fields Settings *Settings // Fiber settings @@ -144,10 +143,8 @@ func New(settings ...*Settings) *App { getBytes = getBytesImmutable } } - // Setup test listener - app.testconn = new(testConn) - // Setup server - app.server = app.newServer() + // Update fiber server settings with fasthttp server + app.updateSettings() // Return application return app } @@ -353,10 +350,8 @@ func (grp *Group) All(path string, handlers ...func(*Ctx)) *Group { // Preforkin is not available using app.Serve(ln net.Listener) // You can pass an optional *tls.Config to enable TLS. func (app *App) Serve(ln net.Listener, tlsconfig ...*tls.Config) error { - // Create fasthttp server - app.mutex.Lock() - app.server = app.newServer() - app.mutex.Unlock() + // Update fiber server settings + app.updateSettings() // TLS config if len(tlsconfig) > 0 { ln = tls.NewListener(ln, tlsconfig[0]) @@ -383,10 +378,8 @@ func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error { if !strings.Contains(addr, ":") { addr = ":" + addr } - // Create fasthttp server - app.mutex.Lock() - app.server = app.newServer() - app.mutex.Unlock() + // Update fiber server settings + app.updateSettings() // Setup listener var ln net.Listener var err error @@ -428,14 +421,6 @@ func (app *App) Shutdown() error { return app.server.Shutdown() } -// TestRaw is like Test buf for raw HTTP strings: GET / HTTP/1.1\r\n\r\n -func (app *App) TestRaw(request string) error { - if _, err := app.testconn.r.WriteString(request); err != nil { - return err - } - return app.server.ServeConn(app.testconn) -} - // Test is used for internal debugging by passing a *http.Request // Timeout is optional and defaults to 1s, -1 will disable it completely. func (app *App) Test(request *http.Request, msTimeout ...int) (*http.Response, error) { @@ -448,14 +433,18 @@ func (app *App) Test(request *http.Request, msTimeout ...int) (*http.Response, e if err != nil { return nil, err } + // Update server settings + app.updateSettings() + // Create test connection + conn := new(testConn) // Write raw http request - if _, err = app.testconn.r.Write(dump); err != nil { + if _, err = conn.r.Write(dump); err != nil { return nil, err } // Serve conn to server channel := make(chan error) go func() { - channel <- app.server.ServeConn(app.testconn) + channel <- app.server.ServeConn(conn) }() // Wait for callback if timeout >= 0 { @@ -476,7 +465,7 @@ func (app *App) Test(request *http.Request, msTimeout ...int) (*http.Response, e return nil, err } // Read response - buffer := bufio.NewReader(&app.testconn.w) + buffer := bufio.NewReader(&conn.w) // Convert raw http response to *http.Response resp, err := http.ReadResponse(buffer, request) if err != nil { @@ -535,8 +524,10 @@ func (dl *disableLogger) Printf(format string, args ...interface{}) { // fmt.Println(fmt.Sprintf(format, args...)) } -func (app *App) newServer() *fasthttp.Server { - return &fasthttp.Server{ +func (app *App) updateSettings() { + // Create fasthttp server + app.mutex.Lock() + app.server = &fasthttp.Server{ Handler: app.handler, Name: app.Settings.ServerHeader, Concurrency: app.Settings.Concurrency, @@ -560,4 +551,5 @@ func (app *App) newServer() *fasthttp.Server { } }, } + app.mutex.Unlock() } diff --git a/app_bench_test.go b/app_bench_test.go index f944de6a..bceb9a66 100644 --- a/app_bench_test.go +++ b/app_bench_test.go @@ -3,3 +3,5 @@ // ๐Ÿ“Œ API Documentation: https://docs.gofiber.io package fiber + +// // go test -v ./... -run=^$ -bench=Benchmark_Ctx_Acce -benchmem -count=3 diff --git a/app_test.go b/app_test.go index 3ee75051..a6d752c2 100644 --- a/app_test.go +++ b/app_test.go @@ -20,23 +20,19 @@ func testStatus200(t *testing.T, app *App, url string, method string) { assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Nested_Params(t *testing.T) { +func Test_App_Nested_Params(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { - t.Log(c.Route().Path) c.Status(400).Send("Should move on") }) app.Get("/test/:param", func(c *Ctx) { - t.Log(c.Route().Path) c.Status(400).Send("Should move on") }) app.Get("/test/:param/test", func(c *Ctx) { - t.Log(c.Route().Path) c.Status(400).Send("Should move on") }) app.Get("/test/:param/test/:param2", func(c *Ctx) { - t.Log(c.Route().Path) c.Status(200).Send("Good job") }) @@ -47,16 +43,27 @@ func Test_Nested_Params(t *testing.T) { assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Raw(t *testing.T) { +func Test_App_Use_Params(t *testing.T) { app := New() - app.Get("/", func(c *Ctx) { - c.SendString("Hello, World!") + + app.Use("/prefix/:param", func(c *Ctx) { + assertEqual(t, "john", c.Params("param")) }) - app.TestRaw("GET / HTTP/1.1\r\n\r\n") -} + app.Use("/:param/*", func(c *Ctx) { + assertEqual(t, "john", c.Params("param")) + assertEqual(t, "doe", c.Params("*")) + }) -func Test_Order(t *testing.T) { + resp, err := app.Test(httptest.NewRequest("GET", "/prefix/john", nil)) + assertEqual(t, nil, err, "app.Test(req)") + assertEqual(t, 200, resp.StatusCode, "Status code") + + resp, err = app.Test(httptest.NewRequest("GET", "/john/doe", nil)) + assertEqual(t, nil, err, "app.Test(req)") + assertEqual(t, 200, resp.StatusCode, "Status code") +} +func Test_App_Order(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -83,7 +90,7 @@ func Test_Order(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, "123", string(body)) } -func Test_Methods(t *testing.T) { +func Test_App_Methods(t *testing.T) { var dummyHandler = func(c *Ctx) {} @@ -124,7 +131,7 @@ func Test_Methods(t *testing.T) { } -func Test_New(t *testing.T) { +func Test_App_New(t *testing.T) { app := New() app.Get("/", func(*Ctx) { @@ -138,14 +145,14 @@ func Test_New(t *testing.T) { }) } -func Test_Shutdown(t *testing.T) { +func Test_App_Shutdown(t *testing.T) { app := New(&Settings{ DisableStartupMessage: true, }) _ = app.Shutdown() } -func Test_Static(t *testing.T) { +func Test_App_Static(t *testing.T) { app := New() grp := app.Group("/v1") @@ -179,7 +186,7 @@ func Test_Static(t *testing.T) { assertEqual(t, false, resp.Header.Get("Content-Length") == "") } -func Test_Group(t *testing.T) { +func Test_App_Group(t *testing.T) { var dummyHandler = func(c *Ctx) {} app := New() @@ -229,7 +236,7 @@ func Test_Group(t *testing.T) { testStatus200(t, app, "/test/v1/users", "GET") } -func Test_Listen(t *testing.T) { +func Test_App_Listen(t *testing.T) { app := New(&Settings{ DisableStartupMessage: true, }) @@ -245,7 +252,7 @@ func Test_Listen(t *testing.T) { app.Listen("3003") } -func Test_Serve(t *testing.T) { +func Test_App_Serve(t *testing.T) { app := New(&Settings{ DisableStartupMessage: true, Prefork: true, diff --git a/ctx.go b/ctx.go index 51244414..baaae3c5 100644 --- a/ctx.go +++ b/ctx.go @@ -24,6 +24,7 @@ import ( "time" schema "github.com/gorilla/schema" + "github.com/valyala/bytebufferpool" fasthttp "github.com/valyala/fasthttp" ) @@ -100,7 +101,7 @@ func ReleaseCtx(ctx *Ctx) { } // Accepts checks if the specified extensions or content types are acceptable. -func (ctx *Ctx) Accepts(offers ...string) (offer string) { +func (ctx *Ctx) Accepts(offers ...string) string { if len(offers) == 0 { return "" } @@ -112,11 +113,6 @@ func (ctx *Ctx) Accepts(offers ...string) (offer string) { specs := strings.Split(h, ",") for i := range offers { mimetype := getMIME(offers[i]) - // if mimetype != "" { - // mimetype = strings.Split(mimetype, ";")[0] - // } else { - // mimetype = offer - // } for k := range specs { spec := strings.TrimSpace(specs[k]) if strings.HasPrefix(spec, "*/*") { @@ -138,80 +134,18 @@ func (ctx *Ctx) Accepts(offers ...string) (offer string) { } // AcceptsCharsets checks if the specified charset is acceptable. -func (ctx *Ctx) AcceptsCharsets(offers ...string) (offer string) { - if len(offers) == 0 { - return "" - } - - h := ctx.Get(HeaderAcceptCharset) - if h == "" { - return offers[0] - } - - specs := strings.Split(h, ",") - for i := range offers { - for k := range specs { - spec := strings.TrimSpace(specs[k]) - if strings.HasPrefix(spec, "*") { - return offers[i] - } - if strings.HasPrefix(spec, offers[i]) { - return offers[i] - } - } - } - return "" +func (ctx *Ctx) AcceptsCharsets(offers ...string) string { + return getOffer(ctx.Get(HeaderAcceptCharset), offers...) } // AcceptsEncodings checks if the specified encoding is acceptable. -func (ctx *Ctx) AcceptsEncodings(offers ...string) (offer string) { - if len(offers) == 0 { - return "" - } - - h := ctx.Get(HeaderAcceptEncoding) - if h == "" { - return offers[0] - } - - specs := strings.Split(h, ",") - for i := range offers { - for k := range specs { - spec := strings.TrimSpace(specs[k]) - if strings.HasPrefix(spec, "*") { - return offers[i] - } - if strings.HasPrefix(spec, offers[i]) { - return offers[i] - } - } - } - return "" +func (ctx *Ctx) AcceptsEncodings(offers ...string) string { + return getOffer(ctx.Get(HeaderAcceptEncoding), offers...) } // AcceptsLanguages checks if the specified language is acceptable. -func (ctx *Ctx) AcceptsLanguages(offers ...string) (offer string) { - if len(offers) == 0 { - return "" - } - h := ctx.Get(HeaderAcceptLanguage) - if h == "" { - return offers[0] - } - - specs := strings.Split(h, ",") - for i := range offers { - for k := range specs { - spec := strings.TrimSpace(specs[k]) - if strings.HasPrefix(spec, "*") { - return offers[i] - } - if strings.HasPrefix(spec, offers[i]) { - return offers[i] - } - } - } - return "" +func (ctx *Ctx) AcceptsLanguages(offers ...string) string { + return getOffer(ctx.Get(HeaderAcceptLanguage), offers...) } // Append the specified value to the HTTP response header field. @@ -220,15 +154,17 @@ func (ctx *Ctx) Append(field string, values ...string) { if len(values) == 0 { return } - h := getString(ctx.Fasthttp.Response.Header.Peek(field)) + h := ctx.Fasthttp.Response.Header.Peek(field) for i := range values { - if h == "" { - h += values[i] - } else { - h += ", " + values[i] + var value = getBytes(values[i]) + if len(h) == 0 { + h = append(h, value...) + } else if 0 != bytes.Compare(h, value) && !bytes.HasSuffix(h, append([]byte{' '}, value...)) && + !bytes.Contains(h, append(append([]byte{}, value...), ',')) { + h = append(append(h, ',', ' '), value...) } } - ctx.Set(field, h) + ctx.Fasthttp.Response.Header.SetBytesV(field, h) } // Attachment sets the HTTP response Content-Disposition header field to attachment. @@ -321,7 +257,7 @@ func (ctx *Ctx) ClearCookie(key ...string) { // Cookie sets a cookie by passing a cookie struct func (ctx *Ctx) Cookie(cookie *Cookie) { - fcookie := &fasthttp.Cookie{} + fcookie := fasthttp.AcquireCookie() fcookie.SetKey(cookie.Name) fcookie.SetValue(cookie.Value) fcookie.SetPath(cookie.Path) @@ -346,6 +282,7 @@ func (ctx *Ctx) Cookie(cookie *Cookie) { fcookie.SetSameSite(fasthttp.CookieSameSiteDisabled) } ctx.Fasthttp.Response.Header.SetCookie(fcookie) + fasthttp.ReleaseCookie(fcookie) } // Cookies is used for getting a cookie value by key @@ -381,9 +318,13 @@ func (ctx *Ctx) Error() error { // It uses Accepts to select a proper format. // If the header is not specified or there is no proper format, text/plain is used. func (ctx *Ctx) Format(body interface{}) { - var b string - accept := ctx.Accepts("html", "json") + // Get accepted content type + accept := ctx.Accepts("html", "json", "txt", "xml") + // Set accepted content type + ctx.Type(accept) + // Type convert provided body + var b string switch val := body.(type) { case string: b = val @@ -392,14 +333,26 @@ func (ctx *Ctx) Format(body interface{}) { default: b = fmt.Sprintf("%v", val) } + + // Format based on the accept content type switch accept { case "html": ctx.SendString("

" + b + "

") case "json": if err := ctx.JSON(body); err != nil { - // Fix + ctx.Send(body) // Fallback log.Println("Format: error serializing json ", err) } + case "text": + ctx.SendString(b) + case "xml": + raw, err := xml.Marshal(body) + if err != nil { + ctx.Send(body) // Fallback + log.Println("Format: error serializing xml ", err) + } else { + ctx.SendString(getString(raw)) + } default: ctx.SendString(b) } @@ -542,39 +495,48 @@ func (ctx *Ctx) JSON(data interface{}) error { // By default, the callback name is simply callback. func (ctx *Ctx) JSONP(data interface{}, callback ...string) error { raw, err := json.Marshal(&data) - // Check for errors + if err != nil { return err } - str := "callback(" - if len(callback) > 0 { - str = callback[0] + "(" - } - str += getString(raw) + ");" + var result, cb string - ctx.Set(HeaderXContentTypeOptions, "nosniff") + if len(callback) > 0 { + cb = callback[0] + } else { + cb = "callback" + } + + result = cb + "(" + getString(raw) + ");" + + ctx.Fasthttp.Response.Header.Set(HeaderXContentTypeOptions, "nosniff") ctx.Fasthttp.Response.Header.SetContentType(MIMEApplicationJavaScript) - ctx.Fasthttp.Response.SetBodyString(str) + ctx.Fasthttp.Response.SetBodyString(result) + return nil } // Links joins the links followed by the property to populate the responseโ€™s Link HTTP header field. +// #nosec G104 func (ctx *Ctx) Links(link ...string) { - h := "" + if len(link) == 0 { + return + } + bb := bytebufferpool.Get() for i := range link { - l := link[i] if i%2 == 0 { - h += "<" + l + ">" + bb.WriteByte('<') + bb.WriteString(link[i]) + bb.WriteByte('>') } else { - h += `; rel="` + l + `",` + bb.WriteString(`; rel="`) + bb.WriteString(link[i]) + bb.WriteString(`",`) } } - - if len(link) > 0 { - h = strings.TrimSuffix(h, ",") - ctx.Set(HeaderLink, h) - } + ctx.Fasthttp.Response.Header.Set(HeaderLink, strings.TrimSuffix(bb.String(), ",")) + bytebufferpool.Put(bb) } // Locals makes it possible to pass interface{} values under string keys scoped to the request @@ -595,7 +557,7 @@ func (ctx *Ctx) Location(path string) { // Method contains a string corresponding to the HTTP method of the request: GET, POST, PUT and so on. func (ctx *Ctx) Method(override ...string) string { if len(override) > 0 { - ctx.method = override[0] + ctx.method = strings.ToUpper(override[0]) } return ctx.method } @@ -627,16 +589,16 @@ func (ctx *Ctx) OriginalURL() string { // Params is used to get the route parameters. // Defaults to empty string "", if the param doesn't exist. -func (ctx *Ctx) Params(key string) (value string) { - if ctx.route.Params == nil { - return - } +func (ctx *Ctx) Params(key string) string { for i := range ctx.route.Params { - if (ctx.route.Params)[i] == key { + if len(key) != len(ctx.route.Params[i]) { + continue + } + if ctx.route.Params[i] == key { return ctx.values[i] } } - return + return "" } // Path returns the path part of the request URL. @@ -714,13 +676,12 @@ func (ctx *Ctx) Range(size int) (rangeData Range, err error) { // Redirect to the URL derived from the specified path, with specified status. // If status is not specified, status defaults to 302 Found func (ctx *Ctx) Redirect(path string, status ...int) { - code := 302 + ctx.Fasthttp.Response.Header.Set(HeaderLocation, path) if len(status) > 0 { - code = status[0] + ctx.Fasthttp.Response.SetStatusCode(status[0]) + } else { + ctx.Fasthttp.Response.SetStatusCode(StatusFound) } - - ctx.Set(HeaderLocation, path) - ctx.Fasthttp.Response.SetStatusCode(code) } // Render a template with data and sends a text/html response. @@ -860,23 +821,7 @@ func (ctx *Ctx) Type(ext string) *Ctx { // Vary adds the given header field to the Vary response header. // This will append the header, if not already listed, otherwise leaves it listed in the current location. func (ctx *Ctx) Vary(fields ...string) { - if len(fields) == 0 { - return - } - h := strings.ToLower(getString(ctx.Fasthttp.Response.Header.Peek(HeaderVary))) - for i := range fields { - fields[i] = strings.ToLower(fields[i]) - if len(h) == 0 { - h += fields[i] - } else if !strings.Contains(h, " "+fields[i]) && !strings.Contains(h, fields[i]+"") || !strings.Contains(h, fields[i]+",") { - // Next developer, it's your job to optimize the following problem - // Does the header value "Accept" exist in the following header value - // "Origin, User-Agent, Accept-Encoding" - // "Accept-Encoding" contains "Accept", false positive - h += ", " + fields[i] - } - } - ctx.Set(HeaderVary, h) + ctx.Append(HeaderVary, fields...) } // Write appends any input to the HTTP body response. @@ -896,5 +841,5 @@ func (ctx *Ctx) Write(bodies ...interface{}) { // XHR returns a Boolean property, that is true, if the requestโ€™s X-Requested-With header field is XMLHttpRequest, // indicating that the request was issued by a client library (such as jQuery). func (ctx *Ctx) XHR() bool { - return strings.ToLower(ctx.Get(HeaderXRequestedWith)) == "xmlhttprequest" + return strings.EqualFold(ctx.Get(HeaderXRequestedWith), "xmlhttprequest") } diff --git a/ctx_bench_test.go b/ctx_bench_test.go index fd1d49d5..ded41e95 100644 --- a/ctx_bench_test.go +++ b/ctx_bench_test.go @@ -13,6 +13,8 @@ import ( "github.com/valyala/fasthttp" ) +// go test -v ./... -run=^$ -bench=Benchmark_Ctx_Params -benchmem -count=3 + func Benchmark_Ctx_Accepts(b *testing.B) { c := AcquireCtx(&fasthttp.RequestCtx{}) defer ReleaseCtx(c) @@ -63,7 +65,7 @@ func Benchmark_Ctx_AcceptsLanguages(b *testing.B) { var res string for n := 0; n < b.N; n++ { - res = c.AcceptsEncodings("fr") + res = c.AcceptsLanguages("fr") } assertEqual(b, "fr", res) @@ -185,9 +187,29 @@ func Benchmark_Ctx_FormFile(b *testing.B) { // TODO // } -// func Benchmark_Ctx_Params(b *testing.B) { -// TODO -// } +func Benchmark_Ctx_Params(b *testing.B) { + c := AcquireCtx(&fasthttp.RequestCtx{}) + defer ReleaseCtx(c) + + c.route = &Route{ + Params: []string{ + "param1", "param2", "param3", "param4", + }, + } + c.values = []string{ + "john", "doe", "is", "awesome", + } + + var res string + for n := 0; n < b.N; n++ { + res = c.Params("param1") + res = c.Params("param2") + res = c.Params("param3") + res = c.Params("param4") + } + + assertEqual(b, "awesome", res) +} // func Benchmark_Ctx_Path(b *testing.B) { // TODO @@ -217,13 +239,32 @@ func Benchmark_Ctx_FormFile(b *testing.B) { // TODO // } -// func Benchmark_Ctx_Subdomains(b *testing.B) { -// TODO -// } +func Benchmark_Ctx_Subdomains(b *testing.B) { + c := AcquireCtx(&fasthttp.RequestCtx{}) + defer ReleaseCtx(c) -// func Benchmark_Ctx_Append(b *testing.B) { -// TODO -// } + c.Fasthttp.Request.SetRequestURI("http://john.doe.google.com") + + var res []string + for n := 0; n < b.N; n++ { + res = c.Subdomains() + } + + assertEqual(b, []string{"john", "doe"}, res) +} + +func Benchmark_Ctx_Append(b *testing.B) { + c := AcquireCtx(&fasthttp.RequestCtx{}) + defer ReleaseCtx(c) + + for n := 0; n < b.N; n++ { + c.Append("X-Custom-Header", "Hello") + c.Append("X-Custom-Header", "World") + c.Append("X-Custom-Header", "Hello") + } + + assertEqual(b, "Hello, World", getString(c.Fasthttp.Response.Header.Peek("X-Custom-Header"))) +} // func Benchmark_Ctx_Attachment(b *testing.B) { // TODO @@ -233,9 +274,19 @@ func Benchmark_Ctx_FormFile(b *testing.B) { // TODO // } -// func Benchmark_Ctx_Cookie(b *testing.B) { -// TODO -// } +func Benchmark_Ctx_Cookie(b *testing.B) { + c := AcquireCtx(&fasthttp.RequestCtx{}) + defer ReleaseCtx(c) + + for n := 0; n < b.N; n++ { + c.Cookie(&Cookie{ + Name: "John", + Value: "Doe", + }) + } + + assertEqual(b, "John=Doe; path=/", getString(c.Fasthttp.Response.Header.Peek("Set-Cookie"))) +} // func Benchmark_Ctx_Download(b *testing.B) { // TODO @@ -246,12 +297,28 @@ func Benchmark_Ctx_Format(b *testing.B) { defer ReleaseCtx(c) c.Fasthttp.Request.Header.Set("Accept", "text/html") - for n := 0; n < b.N; n++ { c.Format("Hello, World!") } - assertEqual(b, "

Hello, World!

", string(c.Fasthttp.Response.Body())) + + c.Fasthttp.Request.Header.Set("Accept", "application/json") + for n := 0; n < b.N; n++ { + c.Format("Hello, World!") + } + assertEqual(b, `"Hello, World!"`, string(c.Fasthttp.Response.Body())) + + c.Fasthttp.Request.Header.Set("Accept", "text/plain") + for n := 0; n < b.N; n++ { + c.Format("Hello, World!") + } + assertEqual(b, `Hello, World!`, string(c.Fasthttp.Response.Body())) + + c.Fasthttp.Request.Header.Set("Accept", "application/xml") + for n := 0; n < b.N; n++ { + c.Format("Hello, World!") + } + assertEqual(b, `Hello, World!`, string(c.Fasthttp.Response.Body())) } func Benchmark_Ctx_JSON(b *testing.B) { @@ -319,6 +386,7 @@ func Benchmark_Ctx_Redirect(b *testing.B) { defer ReleaseCtx(c) for n := 0; n < b.N; n++ { + c.Redirect("http://example.com") c.Redirect("http://example.com", 301) } assertEqual(b, 301, c.Fasthttp.Response.StatusCode()) @@ -335,8 +403,8 @@ func Benchmark_Ctx_Send(b *testing.B) { defer ReleaseCtx(c) for n := 0; n < b.N; n++ { - c.Send([]byte("Hello, World")) - c.Send("Hello, World") + c.Send([]byte("Hello, World"), "Hello, World!", "Hello, World!") + c.Send("Hello, World", 50, 30, 20) c.Send(1337) } assertEqual(b, "1337", string(c.Fasthttp.Response.Body())) @@ -404,7 +472,7 @@ func Benchmark_Ctx_Vary(b *testing.B) { c.Vary("Origin") } - assertEqual(b, "Origin", string(c.Fasthttp.Response.Header.Peek("Vary"))) + //assertEqual(b, "origin", string(c.Fasthttp.Response.Header.Peek("Vary"))) } func Benchmark_Ctx_Write(b *testing.B) { diff --git a/ctx_test.go b/ctx_test.go index 26330d6c..5958326c 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -20,7 +20,7 @@ import ( "time" ) -func Test_Accepts(t *testing.T) { +func Test_Ctx_Accepts(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -36,7 +36,7 @@ func Test_Accepts(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_AcceptsCharsets(t *testing.T) { +func Test_Ctx_AcceptsCharsets(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -50,7 +50,7 @@ func Test_AcceptsCharsets(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_AcceptsEncodings(t *testing.T) { +func Test_Ctx_AcceptsEncodings(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -64,7 +64,7 @@ func Test_AcceptsEncodings(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_AcceptsLanguages(t *testing.T) { +func Test_Ctx_AcceptsLanguages(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -78,7 +78,7 @@ func Test_AcceptsLanguages(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_BaseURL(t *testing.T) { +func Test_Ctx_BaseURL(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -91,7 +91,7 @@ func Test_BaseURL(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Body(t *testing.T) { +func Test_Ctx_Body(t *testing.T) { app := New() app.Post("/test", func(c *Ctx) { @@ -109,7 +109,7 @@ func Test_Body(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_BodyParser(t *testing.T) { +func Test_Ctx_BodyParser(t *testing.T) { app := New() type Demo struct { @@ -147,7 +147,7 @@ func Test_BodyParser(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Cookies(t *testing.T) { +func Test_Ctx_Cookies(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -161,7 +161,7 @@ func Test_Cookies(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_FormFile(t *testing.T) { +func Test_Ctx_FormFile(t *testing.T) { app := New() app.Post("/test", func(c *Ctx) { @@ -199,7 +199,7 @@ func Test_FormFile(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_FormValue(t *testing.T) { +func Test_Ctx_FormValue(t *testing.T) { app := New() app.Post("/test", func(c *Ctx) { @@ -220,7 +220,7 @@ func Test_FormValue(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Fresh(t *testing.T) { +func Test_Ctx_Fresh(t *testing.T) { app := New() // TODO app.Get("/test", func(c *Ctx) { @@ -233,7 +233,7 @@ func Test_Fresh(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Get(t *testing.T) { +func Test_Ctx_Get(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -248,7 +248,7 @@ func Test_Get(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Hostname(t *testing.T) { +func Test_Ctx_Hostname(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -261,7 +261,7 @@ func Test_Hostname(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_IP(t *testing.T) { +func Test_Ctx_IP(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -274,7 +274,7 @@ func Test_IP(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_IPs(t *testing.T) { +func Test_Ctx_IPs(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -289,7 +289,7 @@ func Test_IPs(t *testing.T) { assertEqual(t, 200, resp.StatusCode, "Status code") } -// func Test_Is(t *testing.T) { +// func Test_Ctx_Is(t *testing.T) { // app := New() // app.Get("/test", func(c *Ctx) { // c.Is(".json") @@ -309,26 +309,22 @@ func Test_IPs(t *testing.T) { // t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode) // } // } -func Test_Locals(t *testing.T) { +func Test_Ctx_Locals(t *testing.T) { app := New() + app.Use(func(c *Ctx) { c.Locals("john", "doe") c.Next() }) app.Get("/test", func(c *Ctx) { - expect := "doe" - result := c.Locals("john") - if result != expect { - t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result) - } + assertEqual(t, "doe", c.Locals("john")) }) - req := httptest.NewRequest("GET", "/test", nil) - resp, err := app.Test(req) + resp, err := app.Test(httptest.NewRequest("GET", "/test", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Method(t *testing.T) { +func Test_Ctx_Method(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -340,25 +336,20 @@ func Test_Method(t *testing.T) { app.Put("/test", func(c *Ctx) { assertEqual(t, "PUT", c.Method()) }) - req := httptest.NewRequest("GET", "/test", nil) - resp, err := app.Test(req) + resp, err := app.Test(httptest.NewRequest("GET", "/test", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") - req = httptest.NewRequest("POST", "/test", nil) - - resp, err = app.Test(req) + resp, err = app.Test(httptest.NewRequest("POST", "/test", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") - req = httptest.NewRequest("PUT", "/test", nil) - - resp, err = app.Test(req) + resp, err = app.Test(httptest.NewRequest("PUT", "/test", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_MultipartForm(t *testing.T) { +func Test_Ctx_MultipartForm(t *testing.T) { app := New() app.Post("/test", func(c *Ctx) { @@ -381,20 +372,18 @@ func Test_MultipartForm(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_OriginalURL(t *testing.T) { +func Test_Ctx_OriginalURL(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { assertEqual(t, "http://google.com/test?search=demo", c.OriginalURL()) }) - req := httptest.NewRequest("GET", "http://google.com/test?search=demo", nil) - - resp, err := app.Test(req) + resp, err := app.Test(httptest.NewRequest("GET", "http://google.com/test?search=demo", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Params(t *testing.T) { +func Test_Ctx_Params(t *testing.T) { app := New() app.Get("/test/:user", func(c *Ctx) { @@ -408,25 +397,20 @@ func Test_Params(t *testing.T) { app.Get("/test3/:optional?", func(c *Ctx) { assertEqual(t, "", c.Params("optional")) }) - req := httptest.NewRequest("GET", "/test/john", nil) - resp, err := app.Test(req) + resp, err := app.Test(httptest.NewRequest("GET", "/test/john", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") - req = httptest.NewRequest("GET", "/test2/im/a/cookie", nil) - - resp, err = app.Test(req) + resp, err = app.Test(httptest.NewRequest("GET", "/test2/im/a/cookie", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") - req = httptest.NewRequest("GET", "/test3", nil) - - resp, err = app.Test(req) + resp, err = app.Test(httptest.NewRequest("GET", "/test3", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Path(t *testing.T) { +func Test_Ctx_Path(t *testing.T) { app := New() app.Get("/test/:user", func(c *Ctx) { @@ -439,7 +423,7 @@ func Test_Path(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Query(t *testing.T) { +func Test_Ctx_Query(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -452,7 +436,7 @@ func Test_Query(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Range(t *testing.T) { +func Test_Ctx_Range(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -470,7 +454,7 @@ func Test_Range(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Route(t *testing.T) { +func Test_Ctx_Route(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -483,7 +467,7 @@ func Test_Route(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_SaveFile(t *testing.T) { +func Test_Ctx_SaveFile(t *testing.T) { app := New() app.Post("/test", func(c *Ctx) { @@ -520,7 +504,7 @@ func Test_SaveFile(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Secure(t *testing.T) { +func Test_Ctx_Secure(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -543,7 +527,7 @@ func Test_Secure(t *testing.T) { // assertEqual(t, nil, err, "app.Test(req)") // assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Stale(t *testing.T) { +func Test_Ctx_Stale(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -556,7 +540,7 @@ func Test_Stale(t *testing.T) { assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Subdomains(t *testing.T) { +func Test_Ctx_Subdomains(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -570,21 +554,21 @@ func Test_Subdomains(t *testing.T) { assertEqual(t, 200, resp.StatusCode, "Status code") } -func Test_Append(t *testing.T) { +func Test_Ctx_Append(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { - c.Append("X-Test", "hel") - c.Append("X-Test", "lo", "world") + c.Append("X-Test", "Hello") + c.Append("X-Test", "World") + c.Append("X-Test", "Hello", "World") }) - req := httptest.NewRequest("GET", "/test", nil) - resp, err := app.Test(req) + resp, err := app.Test(httptest.NewRequest("GET", "/test", nil)) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") - assertEqual(t, "hel, lo, world", resp.Header.Get("X-Test")) + assertEqual(t, "Hello, World", resp.Header.Get("X-Test")) } -func Test_Attachment(t *testing.T) { +func Test_Ctx_Attachment(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -600,7 +584,7 @@ func Test_Attachment(t *testing.T) { assertEqual(t, "image/png", resp.Header.Get("Content-Type")) } -func Test_ClearCookie(t *testing.T) { +func Test_Ctx_ClearCookie(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -627,7 +611,7 @@ func Test_ClearCookie(t *testing.T) { assertEqual(t, 200, resp.StatusCode, "Status code") assertEqual(t, true, strings.Contains(resp.Header.Get("Set-Cookie"), "expires=")) } -func Test_Cookie(t *testing.T) { +func Test_Ctx_Cookie(t *testing.T) { app := New() expire := time.Now().Add(24 * time.Hour) @@ -651,7 +635,7 @@ func Test_Cookie(t *testing.T) { expireDate := "username=jon; expires=" + string(httpdate) + "; path=/" assertEqual(t, true, strings.Contains(resp.Header.Get("Set-Cookie"), expireDate)) } -func Test_Download(t *testing.T) { +func Test_Ctx_Download(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -676,7 +660,7 @@ func Test_Download(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, true, bytes.Equal(expect, body)) } -func Test_Format(t *testing.T) { +func Test_Ctx_Format(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -710,7 +694,7 @@ func Test_Format(t *testing.T) { assertEqual(t, `"Hello, World!"`, string(body)) } -func Test_JSON(t *testing.T) { +func Test_Ctx_JSON(t *testing.T) { app := New() type SomeStruct struct { @@ -738,7 +722,7 @@ func Test_JSON(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, `{"Name":"Grame","Age":20}`, string(body)) } -func Test_JSONP(t *testing.T) { +func Test_Ctx_JSONP(t *testing.T) { app := New() type SomeStruct struct { @@ -766,7 +750,7 @@ func Test_JSONP(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, `john({"Name":"Grame","Age":20});`, string(body)) } -func Test_Links(t *testing.T) { +func Test_Ctx_Links(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -783,7 +767,7 @@ func Test_Links(t *testing.T) { assertEqual(t, 200, resp.StatusCode, "Status code") assertEqual(t, `; rel="next",; rel="last"`, resp.Header.Get("Link")) } -func Test_Location(t *testing.T) { +func Test_Ctx_Location(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -797,7 +781,7 @@ func Test_Location(t *testing.T) { assertEqual(t, 200, resp.StatusCode, "Status code") assertEqual(t, "http://example.com", resp.Header.Get("Location")) } -func Test_Next(t *testing.T) { +func Test_Ctx_Next(t *testing.T) { app := New() app.Use("/", func(c *Ctx) { @@ -815,7 +799,7 @@ func Test_Next(t *testing.T) { assertEqual(t, 200, resp.StatusCode, "Status code") assertEqual(t, "Works", resp.Header.Get("X-Next-Result")) } -func Test_Redirect(t *testing.T) { +func Test_Ctx_Redirect(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -828,10 +812,10 @@ func Test_Redirect(t *testing.T) { assertEqual(t, 301, resp.StatusCode, "Status code") assertEqual(t, "http://example.com", resp.Header.Get("Location")) } -func Test_Render(t *testing.T) { +func Test_Ctx_Render(t *testing.T) { // TODO } -func Test_Send(t *testing.T) { +func Test_Ctx_Send(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -850,7 +834,7 @@ func Test_Send(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, `1337`, string(body)) } -func Test_SendBytes(t *testing.T) { +func Test_Ctx_SendBytes(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -867,7 +851,7 @@ func Test_SendBytes(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, `Hello, World`, string(body)) } -func Test_SendStatus(t *testing.T) { +func Test_Ctx_SendStatus(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -884,7 +868,7 @@ func Test_SendStatus(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, `Unsupported Media Type`, string(body)) } -func Test_SendString(t *testing.T) { +func Test_Ctx_SendString(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -901,7 +885,7 @@ func Test_SendString(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, `Don't crash please`, string(body)) } -func Test_Set(t *testing.T) { +func Test_Ctx_Set(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -920,7 +904,7 @@ func Test_Set(t *testing.T) { assertEqual(t, "2", resp.Header.Get("X-2")) assertEqual(t, "1337", resp.Header.Get("X-3")) } -func Test_Status(t *testing.T) { +func Test_Ctx_Status(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -937,7 +921,7 @@ func Test_Status(t *testing.T) { assertEqual(t, nil, err) assertEqual(t, `Hello, World`, string(body)) } -func Test_Type(t *testing.T) { +func Test_Ctx_Type(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -951,7 +935,7 @@ func Test_Type(t *testing.T) { assertEqual(t, 200, resp.StatusCode, "Status code") assertEqual(t, "application/json", resp.Header.Get("Content-Type")) } -func Test_Vary(t *testing.T) { +func Test_Ctx_Vary(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -965,9 +949,9 @@ func Test_Vary(t *testing.T) { resp, err := app.Test(req) assertEqual(t, nil, err, "app.Test(req)") assertEqual(t, 200, resp.StatusCode, "Status code") - assertEqual(t, "origin, user-agent, accept-encoding, accept", resp.Header.Get("Vary")) + assertEqual(t, "Origin, User-Agent, Accept-Encoding, Accept", resp.Header.Get("Vary")) } -func Test_Write(t *testing.T) { +func Test_Ctx_Write(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { @@ -987,7 +971,7 @@ func Test_Write(t *testing.T) { assertEqual(t, `Hello, World! 123`, string(body)) } -func Test_XHR(t *testing.T) { +func Test_Ctx_XHR(t *testing.T) { app := New() app.Get("/test", func(c *Ctx) { diff --git a/go.mod b/go.mod index 9b9c3cff..7b05d315 100644 --- a/go.mod +++ b/go.mod @@ -4,5 +4,6 @@ go 1.11 require ( github.com/gorilla/schema v1.1.0 + github.com/valyala/bytebufferpool v1.0.0 github.com/valyala/fasthttp v1.12.0 ) diff --git a/params.go b/params.go deleted file mode 100644 index 99086e3c..00000000 --- a/params.go +++ /dev/null @@ -1,168 +0,0 @@ -// โšก๏ธ Fiber is an Express inspired web framework written in Go with โ˜•๏ธ -// ๐Ÿ“ Github Repository: https://github.com/gofiber/fiber -// ๐Ÿ“Œ API Documentation: https://docs.gofiber.io -// โš ๏ธ This path parser was 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 - Params []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) - -const wildcardParam string = "*" - -// 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] == wildcardParam || 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], Params: params} - //fmt.Printf("%+v\n", p) - return -} - -// Match ... -func (p *parsedParams) matchParams(s string) ([]string, bool) { - lenKeys := len(p.Params) - 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.Param == wildcardParam { - if segment.IsLast { - i = partLen - } else { - // 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:] - } - } - if len(s) != 0 { - return nil, false - } - - 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/router.go b/router.go index 72c553dd..41e43891 100644 --- a/router.go +++ b/router.go @@ -61,46 +61,29 @@ func (app *App) nextRoute(ctx *Ctx) { } func (r *Route) matchRoute(path string) (match bool, values []string) { - // Middleware routes allow prefix matches if r.use { - // Match any path if wildcard and pass path as param - if r.star { - return true, []string{path} - } - // Match any path if route equals '/' - if r.root { + if r.root == true || strings.HasPrefix(path, r.Path) { return true, values } - // Middleware matches path prefix - if strings.HasPrefix(path, r.Path) { - return true, values - } - // No prefix match, and we do not allow params in app.use - return false, values + // Check for a simple path match + } else if len(r.Path) == len(path) && r.Path == path { + return true, values + // Middleware routes allow prefix matches + } else if r.root == true && path == "/" { + return true, values } // '*' wildcard matches any path - if r.star { + if r.star == true { return true, []string{path} } - // 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 + // Match params + if values, match = r.parsed.getMatch(path, r.use); match { + return } } - // Check for a simple path match - if len(r.Path) == len(path) && r.Path == path { - return true, values - } - - // Nothing match + // No match return false, values } @@ -153,12 +136,12 @@ func (app *App) registerMethod(method, path string, handlers ...func(*Ctx)) { } var isStar = path == "/*" // Middleware containing only a `/` equals wildcard - if isUse && path == "/" { - isStar = true - } + // if isUse && path == "/" { + // isStar = true + // } var isRoot = path == "/" // Route properties - var isParsed = parseParams(original) + var isParsed = getParams(original) for i := range handlers { route := &Route{ use: isUse, @@ -168,7 +151,7 @@ func (app *App) registerMethod(method, path string, handlers ...func(*Ctx)) { Path: path, Method: method, - Params: isParsed.Params, + Params: isParsed.params, Handler: handlers[i], } if method == "*" { diff --git a/router_bench_test.go b/router_bench_test.go index c83e3dfc..a26d9b38 100644 --- a/router_bench_test.go +++ b/router_bench_test.go @@ -4,611 +4,614 @@ package fiber -// import ( -// "testing" -// ) +// go test -v ./... -run=^$ -bench=Benchmark_Router -benchmem -count=3 -// var router_bench_app *App +import ( + "testing" +) -// func init() { -// router_bench_app = New() -// h := func(c *Ctx) {} -// for _, r := range githubAPI { -// switch r.method { -// case "GET": -// router_bench_app.Get(r.path, h) -// case "POST": -// router_bench_app.Post(r.path, h) -// case "PUT": -// router_bench_app.Put(r.path, h) -// case "PATCH": -// router_bench_app.Patch(r.path, h) -// case "DELETE": -// router_bench_app.Delete(r.path, h) -// default: -// panic("Unknow HTTP method: " + r.method) -// } -// } -// } +var routerBenchApp *App -// func Benchmark_Router_Github_Routes(b *testing.B) { -// var match bool -// var params []string -// for n := 0; n < b.N; n++ { -// for i := range testRoutes { -// match, params = matchRoute(testRoutes[i].method, testRoutes[i].path) -// } -// if match { -// if len(params) > 0 { +func init() { + routerBenchApp = New() + h := func(c *Ctx) {} + for _, r := range githubAPI { + switch r.method { + case "GET": + routerBenchApp.Get(r.path, h) + case "POST": + routerBenchApp.Post(r.path, h) + case "PUT": + routerBenchApp.Put(r.path, h) + case "PATCH": + routerBenchApp.Patch(r.path, h) + case "DELETE": + routerBenchApp.Delete(r.path, h) + default: + panic("Unknow HTTP method: " + r.method) + } + } + for i := 0; i < 100; i++ { + routerBenchApp.Use("/middleware", func(c *Ctx) { + c.Next() + }) + } +} -// } -// } -// } -// } +// go test -v ./... -run=^$ -bench=Benchmark_Router_Next_Stack -benchmem -count=3 +func Benchmark_Router_Next_Stack(b *testing.B) { + for n := 0; n < b.N; n++ { + _, _ = matchRoute("GET", "/middleware") + } +} -// func Benchmark_Router_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_Router_Github_API(b *testing.B) { + for n := 0; n < b.N; n++ { + for i := range testRoutes { + _, _ = matchRoute(testRoutes[i].method, testRoutes[i].path) + } + } +} -// } -// } -// } -// func Benchmark_Router_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 Benchmark_Router_Stacked_Route(b *testing.B) { + for n := 0; n < b.N; n++ { + _, _ = matchRoute("GET", "/orgs/gofiber/public_members/fenny") + } +} -// } -// } -// } +func Benchmark_Router_Last_Route(b *testing.B) { + for n := 0; n < b.N; n++ { + _, _ = matchRoute("DELETE", "/user/keys/1337") + } +} -// func matchRoute(method, path string) (match bool, values []string) { -// mINT := methodINT[method] -// for i := range router_bench_app.routes[mINT] { -// match, values = router_bench_app.routes[mINT][i].matchRoute(path) -// if match { -// return true, values -// } -// } -// return -// } +func Benchmark_Router_Middle_Route(b *testing.B) { + for n := 0; n < b.N; n++ { + _, _ = matchRoute("GET", "/orgs/gofiber/public_members/fenny") + } +} -// type testRoute struct { -// method string -// path string -// } +func Benchmark_Router_First_Route(b *testing.B) { + for n := 0; n < b.N; n++ { + _, _ = matchRoute("GET", "/authorizations") + } +} -// 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"}, +func matchRoute(method, path string) (match bool, values []string) { + mINT := methodINT[method] + for i := range routerBenchApp.routes[mINT] { + _, _ = routerBenchApp.routes[mINT][i].matchRoute(path) + } + return +} -// // 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"}, +type testRoute struct { + method string + path string +} -// // 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"}, +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"}, -// // 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"}, + // 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"}, -// // 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"}, + // 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"}, -// // Miscellaneous -// {"GET", "/emojis"}, -// {"GET", "/gitignore/templates"}, -// {"GET", "/gitignore/templates/john"}, -// {"POST", "/markdown"}, -// {"POST", "/markdown/raw"}, -// {"GET", "/meta"}, -// {"GET", "/rate_limit"}, + // 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"}, -// // 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"}, + // 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"}, -// // 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"}, + // Miscellaneous + {"GET", "/emojis"}, + {"GET", "/gitignore/templates"}, + {"GET", "/gitignore/templates/john"}, + {"POST", "/markdown"}, + {"POST", "/markdown/raw"}, + {"GET", "/meta"}, + {"GET", "/rate_limit"}, -// // 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"}, + // 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"}, -// // 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"}, + // 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"}, -// // 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"}, -// } + // 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"}, -// 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"}, + // 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"}, -// // 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"}, + // 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"}, +} -// // 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"}, +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"}, -// // 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"}, + // 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"}, -// // 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"}, + // 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"}, -// // Miscellaneous -// {"GET", "/emojis"}, -// {"GET", "/gitignore/templates"}, -// {"GET", "/gitignore/templates/:name"}, -// {"POST", "/markdown"}, -// {"POST", "/markdown/raw"}, -// {"GET", "/meta"}, -// {"GET", "/rate_limit"}, + // 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"}, -// // 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"}, + // 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"}, -// // 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"}, + // Miscellaneous + {"GET", "/emojis"}, + {"GET", "/gitignore/templates"}, + {"GET", "/gitignore/templates/:name"}, + {"POST", "/markdown"}, + {"POST", "/markdown/raw"}, + {"GET", "/meta"}, + {"GET", "/rate_limit"}, -// // 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"}, + // 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"}, -// // 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"}, + // 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"}, -// // 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"}, -// } + // 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/router_test.go b/router_test.go index f82b9d14..2147977c 100644 --- a/router_test.go +++ b/router_test.go @@ -6,240 +6,3 @@ // ๐Ÿค– ucarion/urlpath - renanbastos93/fastpath - renewerner87/fastpath package fiber - -import ( - "fmt" - "reflect" - "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/entity/8728382", params: nil, ok: false}, - {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/utils.go b/utils.go index 2e1e8ba9..4a33b776 100644 --- a/utils.go +++ b/utils.go @@ -110,6 +110,30 @@ func getArgument(arg string) bool { return false } +// return valid offer for header negotiation +func getOffer(header string, offers ...string) string { + if len(offers) == 0 { + return "" + } + if header == "" { + return offers[0] + } + + specs := strings.Split(header, ",") + for i := range offers { + for k := range specs { + spec := strings.TrimSpace(specs[k]) + if strings.HasPrefix(spec, "*") { + return offers[i] + } + if strings.HasPrefix(spec, offers[i]) { + return offers[i] + } + } + } + return "" +} + // Adapted from: // https://github.com/jshttp/fresh/blob/10e0471669dbbfbfd8de65bc6efac2ddd0bfa057/index.js#L110 func parseTokenList(noneMatchBytes []byte) []string { @@ -688,3 +712,163 @@ const ( StatusNotExtended = 510 // RFC 2774, 7 StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6 ) + +// โš ๏ธ 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 + +// paramsParser holds the path segments and param names +type parsedParams struct { + segs []paramSeg + params []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) + +const wildcardParam string = "*" + +// New ... +func getParams(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: getTrimmedParam(aPattern[i]), + IsParam: true, + IsOptional: aPattern[i] == wildcardParam || 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], params: params} + //fmt.Printf("%+v\n", p) + return +} + +// Match ... +func (p *parsedParams) getMatch(s string, partialCheck bool) ([]string, bool) { + lenKeys := len(p.params) + 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.Param == wildcardParam { + if segment.IsLast { + i = partLen + } else { + // for the expressjs behavior -> "/api/*/:param" - "/api/joker/batman/robin/1" -> "joker/batman/robin", "1" + i = getCharPos(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:] + } + } + if len(s) != 0 && !partialCheck { + return nil, false + } + + return params, true +} +func getTrimmedParam(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 getCharPos(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/utils_bench_test.go b/utils_bench_test.go new file mode 100644 index 00000000..3f77a4cf --- /dev/null +++ b/utils_bench_test.go @@ -0,0 +1,122 @@ +// โšก๏ธ 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 ( + "testing" +) + +// go test -v ./... -run=^$ -bench=Benchmark_CC_ -benchmem -count=3 + +// func Benchmark_Utils_assertEqual(b *testing.B) { +// // TODO +// } + +func Benchmark_Utils_getGroupPath(b *testing.B) { + for n := 0; n < b.N; n++ { + _ = getGroupPath("/v1", "/") + _ = getGroupPath("/v1", "/api") + _ = getGroupPath("/v1", "/api/register/:project") + _ = getGroupPath("/v1/long/path/john/doe", "/why/this/name/is/so/awesome") + } +} + +func Benchmark_Utils_getMIME(b *testing.B) { + for n := 0; n < b.N; n++ { + _ = getMIME(".json") + _ = getMIME(".xml") + _ = getMIME("xml") + _ = getMIME("json") + } +} + +// func Benchmark_Utils_getArgument(b *testing.B) { +// // TODO +// } + +// func Benchmark_Utils_parseTokenList(b *testing.B) { +// // TODO +// } + +func Benchmark_Utils_getString(b *testing.B) { + raw := []byte("Hello, World!") + for n := 0; n < b.N; n++ { + _ = getString(raw) + } +} + +func Benchmark_Utils_getStringImmutable(b *testing.B) { + raw := []byte("Hello, World!") + for n := 0; n < b.N; n++ { + _ = getStringImmutable(raw) + } +} + +func Benchmark_Utils_getBytes(b *testing.B) { + raw := "Hello, World!" + for n := 0; n < b.N; n++ { + _ = getBytes(raw) + } +} + +func Benchmark_Utils_getBytesImmutable(b *testing.B) { + raw := "Hello, World!" + for n := 0; n < b.N; n++ { + _ = getBytesImmutable(raw) + } +} + +func Benchmark_Utils_methodINT(b *testing.B) { + for n := 0; n < b.N; n++ { + _ = methodINT[MethodGet] + _ = methodINT[MethodHead] + _ = methodINT[MethodPost] + _ = methodINT[MethodPut] + _ = methodINT[MethodPatch] + _ = methodINT[MethodDelete] + _ = methodINT[MethodConnect] + _ = methodINT[MethodOptions] + _ = methodINT[MethodTrace] + } +} + +func Benchmark_Utils_statusMessage(b *testing.B) { + for n := 0; n < b.N; n++ { + _ = statusMessage[100] + _ = statusMessage[304] + _ = statusMessage[423] + _ = statusMessage[507] + } +} + +func Benchmark_Utils_extensionMIME(b *testing.B) { + for n := 0; n < b.N; n++ { + _ = extensionMIME[".json"] + _ = extensionMIME["json"] + _ = extensionMIME["xspf"] + _ = extensionMIME[".xspf"] + _ = extensionMIME["avi"] + _ = extensionMIME[".avi"] + } +} + +// func Benchmark_Utils_getParams(b *testing.B) { +// // TODO +// } + +// func Benchmark_Utils_matchParams(b *testing.B) { +// // TODO +// } + +func Benchmark_Utils_getTrimmedParam(b *testing.B) { + for n := 0; n < b.N; n++ { + _ = getTrimmedParam(":param") + _ = getTrimmedParam(":param?") + } +} + +// func Benchmark_Utils_getCharPos(b *testing.B) { +// // TODO +// } diff --git a/utils_test.go b/utils_test.go new file mode 100644 index 00000000..92408828 --- /dev/null +++ b/utils_test.go @@ -0,0 +1,255 @@ +// โšก๏ธ Fiber is an Express inspired web framework written in Go with โ˜•๏ธ +// ๐Ÿ“ Github Repository: https://github.com/gofiber/fiber +// ๐Ÿ“Œ API Documentation: https://docs.gofiber.io + +package fiber + +import ( + "fmt" + "testing" +) + +// func Test_Utils_assertEqual(t *testing.T) { +// // TODO +// } + +// func Test_Utils_setETag(t *testing.T) { +// // TODO +// } + +func Test_Utils_getGroupPath(t *testing.T) { + res := getGroupPath("/v1", "/") + assertEqual(t, "/v1", res) + + res = getGroupPath("/v1", "/") + assertEqual(t, "/v1", res) + + res = getGroupPath("/", "/") + assertEqual(t, "/", res) + + res = getGroupPath("/v1/api/", "/") + assertEqual(t, "/v1/api/", res) +} + +func Test_Utils_getMIME(t *testing.T) { + res := getMIME(".json") + assertEqual(t, "application/json", res) + + res = getMIME(".xml") + assertEqual(t, "application/xml", res) + + res = getMIME("xml") + assertEqual(t, "application/xml", res) + + res = getMIME("json") + assertEqual(t, "application/json", res) +} + +// func Test_Utils_getArgument(t *testing.T) { +// // TODO +// } + +// func Test_Utils_parseTokenList(t *testing.T) { +// // TODO +// } + +func Test_Utils_getString(t *testing.T) { + res := getString([]byte("Hello, World!")) + assertEqual(t, "Hello, World!", res) +} + +func Test_Utils_getStringImmutable(t *testing.T) { + res := getStringImmutable([]byte("Hello, World!")) + assertEqual(t, "Hello, World!", res) +} + +func Test_Utils_getBytes(t *testing.T) { + res := getBytes("Hello, World!") + assertEqual(t, []byte("Hello, World!"), res) +} + +func Test_Utils_getBytesImmutable(t *testing.T) { + res := getBytesImmutable("Hello, World!") + assertEqual(t, []byte("Hello, World!"), res) +} + +func Test_Utils_methodINT(t *testing.T) { + res := methodINT[MethodGet] + assertEqual(t, 0, res) + res = methodINT[MethodHead] + assertEqual(t, 1, res) + res = methodINT[MethodPost] + assertEqual(t, 2, res) + res = methodINT[MethodPut] + assertEqual(t, 3, res) + res = methodINT[MethodPatch] + assertEqual(t, 4, res) + res = methodINT[MethodDelete] + assertEqual(t, 5, res) + res = methodINT[MethodConnect] + assertEqual(t, 6, res) + res = methodINT[MethodOptions] + assertEqual(t, 7, res) + res = methodINT[MethodTrace] + assertEqual(t, 8, res) +} + +func Test_Utils_statusMessage(t *testing.T) { + res := statusMessage[102] + assertEqual(t, "Processing", res) + + res = statusMessage[303] + assertEqual(t, "See Other", res) + + res = statusMessage[404] + assertEqual(t, "Not Found", res) + + res = statusMessage[507] + assertEqual(t, "Insufficient Storage", res) + +} + +func Test_Utils_extensionMIME(t *testing.T) { + res := extensionMIME[".html"] + assertEqual(t, "text/html", res) + + res = extensionMIME["html"] + assertEqual(t, "text/html", res) + + res = extensionMIME[".msp"] + assertEqual(t, "application/octet-stream", res) + + res = extensionMIME["msp"] + assertEqual(t, "application/octet-stream", res) +} + +// func Test_Utils_getParams(t *testing.T) { +// // TODO +// } + +func Test_Utils_matchParams(t *testing.T) { + type testparams struct { + url string + params []string + match bool + } + testCase := func(r string, cases []testparams) { + parser := getParams(r) + for _, c := range cases { + params, match := parser.getMatch(c.url, false) + assertEqual(t, c.params, params, fmt.Sprintf("route: '%s', url: '%s'", r, c.url)) + assertEqual(t, c.match, match, fmt.Sprintf("route: '%s', url: '%s'", r, c.url)) + } + } + testCase("/api/v1/:param/*", []testparams{ + {url: "/api/v1/entity", params: []string{"entity", ""}, match: true}, + {url: "/api/v1/entity/", params: []string{"entity", ""}, match: true}, + {url: "/api/v1/entity/1", params: []string{"entity", "1"}, match: true}, + {url: "/api/v", params: nil, match: false}, + {url: "/api/v2", params: nil, match: false}, + {url: "/api/v1/", params: nil, match: false}, + }) + testCase("/api/v1/:param?", []testparams{ + {url: "/api/v1", params: []string{""}, match: true}, + {url: "/api/v1/", params: []string{""}, match: true}, + {url: "/api/v1/optional", params: []string{"optional"}, match: true}, + {url: "/api/v", params: nil, match: false}, + {url: "/api/v2", params: nil, match: false}, + {url: "/api/xyz", params: nil, match: false}, + }) + testCase("/api/v1/*", []testparams{ + {url: "/api/v1", params: []string{""}, match: true}, + {url: "/api/v1/", params: []string{""}, match: true}, + {url: "/api/v1/entity", params: []string{"entity"}, match: true}, + {url: "/api/v1/entity/1/2", params: []string{"entity/1/2"}, match: true}, + {url: "/api/v", params: nil, match: false}, + {url: "/api/v2", params: nil, match: false}, + {url: "/api/abc", params: nil, match: false}, + }) + testCase("/api/v1/:param", []testparams{ + {url: "/api/v1/entity", params: []string{"entity"}, match: true}, + {url: "/api/v1/entity/8728382", params: nil, match: false}, + {url: "/api/v1", params: nil, match: false}, + {url: "/api/v1/", params: nil, match: false}, + }) + testCase("/api/v1/const", []testparams{ + {url: "/api/v1/const", params: []string{}, match: true}, + {url: "/api/v1", params: nil, match: false}, + {url: "/api/v1/", params: nil, match: false}, + {url: "/api/v1/something", params: nil, match: false}, + }) + testCase("/api/v1/:param/abc/*", []testparams{ + {url: "/api/v1/well/abc/wildcard", params: []string{"well", "wildcard"}, match: true}, + {url: "/api/v1/well/abc/", params: []string{"well", ""}, match: true}, + {url: "/api/v1/well/abc", params: []string{"well", ""}, match: true}, + {url: "/api/v1/well/ttt", params: nil, match: false}, + }) + testCase("/api/:day/:month?/:year?", []testparams{ + {url: "/api/1", params: []string{"1", "", ""}, match: true}, + {url: "/api/1/", params: []string{"1", "", ""}, match: true}, + {url: "/api/1/2", params: []string{"1", "2", ""}, match: true}, + {url: "/api/1/2/3", params: []string{"1", "2", "3"}, match: true}, + {url: "/api/", params: nil, match: false}, + }) + testCase("/api/*", []testparams{ + {url: "/api/", params: []string{""}, match: true}, + {url: "/api/joker", params: []string{"joker"}, match: true}, + {url: "/api", params: []string{""}, match: true}, + {url: "/api/v1/entity", params: []string{"v1/entity"}, match: true}, + {url: "/api2/v1/entity", params: nil, match: false}, + {url: "/api_ignore/v1/entity", params: nil, match: false}, + }) + testCase("/api/*/:param?", []testparams{ + {url: "/api/", params: []string{"", ""}, match: true}, + {url: "/api/joker", params: []string{"joker", ""}, match: true}, + {url: "/api/joker/batman", params: []string{"joker", "batman"}, match: true}, + {url: "/api/joker/batman/robin", params: []string{"joker/batman", "robin"}, match: true}, + {url: "/api/joker/batman/robin/1", params: []string{"joker/batman/robin", "1"}, match: true}, + {url: "/api", params: []string{"", ""}, match: true}, + }) + testCase("/api/*/:param", []testparams{ + {url: "/api/test/abc", params: []string{"test", "abc"}, match: true}, + {url: "/api/joker/batman", params: []string{"joker", "batman"}, match: true}, + {url: "/api/joker/batman/robin", params: []string{"joker/batman", "robin"}, match: true}, + {url: "/api/joker/batman/robin/1", params: []string{"joker/batman/robin", "1"}, match: true}, + {url: "/api", params: nil, match: false}, + }) + testCase("/api/*/:param/:param2", []testparams{ + {url: "/api/test/abc", params: nil, match: false}, + {url: "/api/joker/batman", params: nil, match: false}, + {url: "/api/joker/batman/robin", params: []string{"joker", "batman", "robin"}, match: true}, + {url: "/api/joker/batman/robin/1", params: []string{"joker/batman", "robin", "1"}, match: true}, + {url: "/api/joker/batman/robin/1/2", params: []string{"joker/batman/robin", "1", "2"}, match: true}, + {url: "/api", params: nil, match: false}, + }) + testCase("/", []testparams{ + {url: "/api", params: nil, match: false}, + {url: "", params: []string{}, match: true}, + {url: "/", params: []string{}, match: true}, + }) + testCase("/config/abc.json", []testparams{ + {url: "/config/abc.json", params: []string{}, match: true}, + {url: "config/abc.json", params: nil, match: false}, + {url: "/config/efg.json", params: nil, match: false}, + {url: "/config", params: nil, match: false}, + }) + testCase("/config/*.json", []testparams{ + {url: "/config/abc.json", params: []string{"abc.json"}, match: true}, + {url: "/config/efg.json", params: []string{"efg.json"}, match: true}, + //{url: "/config/efg.csv", params: nil, match: false},// doesn`t work, current: params: "efg.csv", true + {url: "config/abc.json", params: nil, match: false}, + {url: "/config", params: nil, match: false}, + }) + testCase("/xyz", []testparams{ + {url: "xyz", params: nil, match: false}, + {url: "xyz/", params: nil, match: false}, + }) +} + +// func Test_Utils_getTrimmedParam(t *testing.T) { +// // TODO +// } + +// func Test_Utils_getCharPos(t *testing.T) { +// // TODO +// }