♻️ refactor: merge some external middlewares to core (#2453)

* ♻️ refactor: merge adaptor, helmet, keyauth, redirect, rewrite middlewares to core

* fix linting issues

* fix linting issues

* fix linting issues

* update
pull/2456/head
M. Efe Çetin 2023-05-10 09:01:49 +03:00 committed by GitHub
parent 9cc10e942a
commit c7c37d9b50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 3191 additions and 110 deletions

10
.github/README.md vendored
View File

@ -627,7 +627,12 @@ Here is a list of middleware that are included within the Fiber framework.
| [requestid](https://github.com/gofiber/fiber/tree/master/middleware/requestid) | Adds a requestid to every request. |
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler if a predicate is true. |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
## 🧬 External Middleware
@ -635,12 +640,7 @@ List of externally hosted middleware modules and maintained by the [Fiber team](
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_az.md vendored
View File

@ -627,6 +627,11 @@ Aşağıda Fiber-in daxilində olan middleware-lər siyahı şəklində göstər
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session üçün middleware. Qeyd: Bu middleware Fiber-in öz storage struktrunu istifadə edir. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware-i verilən şərt true olduğu halda handler-i görməyərək üstündən ötüb keçir. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Bir request üçün maksimum vaxt əlavə edir. Əgər arada fasilə yaranarsa, onda proses məhz ErrorHandler-ə göndərilərək icra edilir. |
| [keyauth](https://github.com/gofiber/keyauth) | Key giriş middleware-i, key əsaslı bir authentication metodudur. |
| [redirect](https://github.com/gofiber/redirect) | Yönləndirmə üçün middleware. |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware-i verilən qanunlara əsasən URL yolunu (path) yenidən yazır. Geri dönüşün icrası üçün uyğunluq təşkil edən təsviri linklərin yaradılması üçün nəzərdə tutulmuşdur. |
| [adaptor](https://github.com/gofiber/adaptor) | Fiber request handler-dən net/http handler-ə çevirici. @arsmn-ə xüsusi təşəkkürlər! |
| [helmet](https://github.com/gofiber/helmet) | Fərqli HTTP header istifadə edərək tətbiqi daha təhlükəsiz saxlamağa kömək edir. |
## 🧬 Xarici Middleware
@ -634,12 +639,7 @@ Aşağıda Fiber-in daxilində olan middleware-lər siyahı şəklində göstər
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Fiber request handler-dən net/http handler-ə çevirici. @arsmn-ə xüsusi təşəkkürlər! |
| [helmet](https://github.com/gofiber/helmet) | Fərqli HTTP header istifadə edərək tətbiqi daha təhlükəsiz saxlamağa kömək edir. |
| [jwt](https://github.com/gofiber/jwt) | JWT, JSON Web Token(JWT) girişi qaytaran bir middleware-dir. |
| [keyauth](https://github.com/gofiber/keyauth) | Key giriş middleware-i, key əsaslı bir authentication metodudur. |
| [redirect](https://github.com/gofiber/redirect) | Yönləndirmə üçün middleware. |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware-i verilən qanunlara əsasən URL yolunu (path) yenidən yazır. Geri dönüşün icrası üçün uyğunluq təşkil edən təsviri linklərin yaradılması üçün nəzərdə tutulmuşdur. |
| [storage](https://github.com/gofiber/storage) | Fiber-in Storage arxitekturasını dəstəkləyən bir sıra storage driver verir. Bu sayədə storage-ə ehtiyac duyan Fiber middleware-də rahatlıqla istifadə oluna bilər. |
| [template](https://github.com/gofiber/template) | Bu paket, Fiber `v1.10.x`, Go versiyası 1.13 və ya daha yuxarı olduqda istifadə oluna bilər. 8 template mühərriki var. |
| [websocket](https://github.com/gofiber/websocket) | Yerlilərin dəstəyi ilə WebSocket-ə əsaslanan Fiber üçün Fasthttp. |

10
.github/README_ckb.md vendored
View File

@ -627,6 +627,11 @@ func main() {
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 کاڵا دەرەکییەکان
@ -634,12 +639,7 @@ func main() {
| کاڵا | دەربارە |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_de.md vendored
View File

@ -597,6 +597,11 @@ Hier finden Sie eine Liste der Middleware, die im Fiber-Framework enthalten ist.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 External Middleware
@ -604,12 +609,7 @@ Liste der extern gehosteten Middleware-Module, die vom [Fiber team](https://gith
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. || [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_es.md vendored
View File

@ -597,6 +597,11 @@ Aquí está una lista del middleware incluido en el marco web Fiber.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 Middleware Externo
@ -604,12 +609,7 @@ Lista de módulos de middleware alojados externamente, y mantenidos por el [equi
| Middleware | Descripción |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_fa.md vendored
View File

@ -712,6 +712,11 @@ func main() {
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) |برای ذخیره و مدیریت شناسه کاربری یا session بازدید کنندگان استفاده .میشود|
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) |این میدلور میتواند با استفاده از شرط های تعیین شده درخواست هایی را نادیده بگیرد.|
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) |این میدلور محدودیت زمانی ای را برای درخواست ها تنظیم میکند، در صورتی که محدودیت به پایان برسد ErrorHandler صدا زده میشود.|
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
</div>
</br></br>
@ -728,12 +733,7 @@ func main() {
| Middleware | توضیحات |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_fr.md vendored
View File

@ -599,6 +599,11 @@ Here is a list of middleware that are included within the Fiber framework.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 External Middleware
@ -606,12 +611,7 @@ List of externally hosted middleware modules and maintained by the [Fiber team](
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_he.md vendored
View File

@ -715,6 +715,11 @@ Here is a list of middleware that are included within the Fiber framework.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
</div>
@ -734,12 +739,7 @@ Here is a list of middleware that are included within the Fiber framework.
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_id.md vendored
View File

@ -600,6 +600,11 @@ Kumpulan `middleware` yang ada didalam kerangka kerja Fiber.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 Middleware External
@ -607,12 +612,7 @@ Kumpulan `middleware` yang dihost external dan diurus oleh [Tim Fiber](https://g
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_it.md vendored
View File

@ -623,6 +623,11 @@ Qui una lista dei middleware inclusi con Fiber.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Middleware per sessioni. NOTA: Questo middleware usa il nostro Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Middleware che salta un wrapped handler se un predicate è vero. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Aggiunge un tempo massimo per una richiesta e lo manda a ErrorHandler se si supera. |
| [keyauth](https://github.com/gofiber/keyauth) | Usa auth basato su chiavi. |
| [redirect](https://github.com/gofiber/redirect) | Middleware per reinderizzare |
| [rewrite](https://github.com/gofiber/rewrite) | Riscrive la path all URL con le regole date. Può essere di aiuto per compatibilità o per creare link puliti e più descrittivi. |
| [adaptor](https://github.com/gofiber/adaptor) | Converte gli handler net/http a/da i request handlers di Fiber, grazie tante a @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Aiuta a mettere sicurezza alla tua app usando vari header HTTP. |
## 🧬 Middleware Esterni
@ -630,12 +635,7 @@ La lista dei moduli middleware hostati esternamente e mantenuti dal [team di Fib
| Middleware | Descrizione |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converte gli handler net/http a/da i request handlers di Fiber, grazie tante a @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Aiuta a mettere sicurezza alla tua app usando vari header HTTP. |
| [jwt](https://github.com/gofiber/jwt) | Usa JSON Web Token \(JWT\) auth. |
| [keyauth](https://github.com/gofiber/keyauth) | Usa auth basato su chiavi. |
| [redirect](https://github.com/gofiber/redirect) | Middleware per reinderizzare |
| [rewrite](https://github.com/gofiber/rewrite) | Riscrive la path all URL con le regole date. Può essere di aiuto per compatibilità o per creare link puliti e più descrittivi. |
| [storage](https://github.com/gofiber/storage) | Dirver di storage che implementa la interfaccia Storage, fatto per essere usato con vari Fiber middleware. |
| [template](https://github.com/gofiber/template) | Questo pachetto contiene 8 motori template che possono essere usati con Fiber `v1.10.x`. Versione di go neccesaria: 1.13+. |
| [websocket](https://github.com/gofiber/websocket) | Basato su Fasthttp WebSocket per Fiber con supporto per Locals! |

10
.github/README_ja.md vendored
View File

@ -602,6 +602,11 @@ func main() {
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 外部ミドルウェア
@ -609,12 +614,7 @@ func main() {
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_ko.md vendored
View File

@ -603,6 +603,11 @@ Fiber 프레임워크에 포함되는 미들웨어 목록입니다.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 External Middleware
@ -610,12 +615,7 @@ Fiber 프레임워크에 포함되는 미들웨어 목록입니다.
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_nl.md vendored
View File

@ -603,6 +603,11 @@ Here is a list of middleware that are included within the Fiber framework.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
## 🧬 External Middleware
@ -610,12 +615,7 @@ List of externally hosted middleware modules and maintained by the [Fiber team](
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_pt.md vendored
View File

@ -597,6 +597,11 @@ Here is a list of middleware that are included within the Fiber framework.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 External Middleware
@ -604,12 +609,7 @@ List of externally hosted middleware modules and maintained by the [Fiber team](
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_ru.md vendored
View File

@ -604,6 +604,11 @@ func main() {
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 Внешние Middleware
@ -611,12 +616,7 @@ func main() {
| Middleware | Описание |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_sa.md vendored
View File

@ -668,6 +668,11 @@ Here is a list of middleware that are included within the Fiber framework.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session middleware. NOTE: This middleware uses our Storage package. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware that skips a wrapped handler is a predicate is true. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Adds a max time for a request and forwards to ErrorHandler if it is exceeded. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
## 🧬 External Middleware
@ -675,12 +680,7 @@ List of externally hosted middleware modules and maintained by the [Fiber team](
| Middleware | Description |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [adaptor](https://github.com/gofiber/adaptor) | Converter for net/http handlers to/from Fiber request handlers, special thanks to @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Helps secure your apps by setting various HTTP headers. |
| [jwt](https://github.com/gofiber/jwt) | JWT returns a JSON Web Token \(JWT\) auth middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware provides a key based authentication. |
| [redirect](https://github.com/gofiber/redirect) | Redirect middleware |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links. |
| [storage](https://github.com/gofiber/storage) | Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares. |
| [template](https://github.com/gofiber/template) | This package contains 8 template engines that can be used with Fiber `v1.10.x` Go version 1.13 or higher is required. |
| [websocket](https://github.com/gofiber/websocket) | Based on Fasthttp WebSocket for Fiber with Locals support! |

10
.github/README_tr.md vendored
View File

@ -597,6 +597,11 @@ Fiber'a dahil edilen middlewareların bir listesi aşağıda verilmiştir.
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session için middleware. NOTE: Bu middleware Fiber'in Storage yapısını kullanır. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip middleware'ı verilen koşul `true` olduğunda handler'ı atlar ve işlemez. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Bir request için maksimum süre ekler ve aşılırsa ErrorHandler'a iletir. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware, key tabanlı bir authentication sağlar. |
| [redirect](https://github.com/gofiber/redirect) | Yönlendirme middleware 'ı. |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware, sağlanan kurallara göre URL yolunu yeniden yazar. Geriye dönük uyumluluk için veya yalnızca daha temiz ve daha açıklayıcı bağlantılar oluşturmak için yardımcı olabilir. |
| [adaptor](https://github.com/gofiber/adaptor) | Fiber request handlerdan net/http handlerları için dönüştürücü, @arsmn'a özel teşekkürler! |
| [helmet](https://github.com/gofiber/helmet) | Çeşitli HTTP headerları ayarlayarak uygulamalarınızın güvenliğini sağlamaya yardımcı olur. |
## 🧬 Harici Middlewarelar
@ -604,12 +609,7 @@ Harici olarak barındırılan middlewareların modüllerinin listesi. Bu middlew
| Middleware | Açıklama |
| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [adaptor](https://github.com/gofiber/adaptor) | Fiber request handlerdan net/http handlerları için dönüştürücü, @arsmn'a özel teşekkürler! |
| [helmet](https://github.com/gofiber/helmet) | Çeşitli HTTP headerları ayarlayarak uygulamalarınızın güvenliğini sağlamaya yardımcı olur. |
| [jwt](https://github.com/gofiber/jwt) | JWT, bir JSON Web Token \(JWT\) yetkilendirmesi döndüren middleware. |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth middleware, key tabanlı bir authentication sağlar. |
| [redirect](https://github.com/gofiber/redirect) | Yönlendirme middleware 'ı. |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite middleware, sağlanan kurallara göre URL yolunu yeniden yazar. Geriye dönük uyumluluk için veya yalnızca daha temiz ve daha açıklayıcı bağlantılar oluşturmak için yardımcı olabilir. |
| [storage](https://github.com/gofiber/storage) | Fiber'in Storage yapısını destekleyen birçok storage driver'ı verir. Bu sayede depolama gerektiren Fiber middlewarelarında kolaylıkla kullanılabilir. |
| [template](https://github.com/gofiber/template) | Bu paket, Fiber `v2.x.x`, Go sürüm 1.17 veya üzeri gerekli olduğunda kullanılabilecek 9 template motoru içerir. |
| [websocket](https://github.com/gofiber/websocket) | Yereller desteğiyle Fiber için Fasthttp WebSocket'a dayalıdır! |

10
.github/README_uk.md vendored
View File

@ -632,6 +632,11 @@ func main() {
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Middleware для сеансів. ПРИМІТКА: Цей middleware використовує наш пакет зберігання. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Middleware який пропускає упакований обробник, якщо предикат є істинним. |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | Додає максимальний час для запиту та пересилає до ErrorHandler, якщо його перевищено. |
| [keyauth](https://github.com/gofiber/keyauth) | Middleware для автентифікації по ключам. |
| [redirect](https://github.com/gofiber/redirect) | Middleware для перенаправлення. |
| [rewrite](https://github.com/gofiber/rewrite) | Middleware для перезапису URL-адреси на основі наданих правил. |
| [adaptor](https://github.com/gofiber/adaptor) | Конвентор для обробників net/http до/з обробників запитів Fiber, особлива подяка @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Допомагає захистити ваші програми, встановлюючи різні заголовки HTTP. |
## 🧬 Зовнішні Middleware
@ -639,12 +644,7 @@ func main() {
| Middleware | Опис |
| :------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------- |
| [adaptor](https://github.com/gofiber/adaptor) | Конвентор для обробників net/http до/з обробників запитів Fiber, особлива подяка @arsmn! |
| [helmet](https://github.com/gofiber/helmet) | Допомагає захистити ваші програми, встановлюючи різні заголовки HTTP. |
| [jwt](https://github.com/gofiber/jwt) | JWT повертає middleware автентифікації JSON Web Token \(JWT\). |
| [keyauth](https://github.com/gofiber/keyauth) | Middleware для автентифікації по ключам. |
| [redirect](https://github.com/gofiber/redirect) | Middleware для перенаправлення. |
| [rewrite](https://github.com/gofiber/rewrite) | Middleware для перезапису URL-адреси на основі наданих правил. |
| [storage](https://github.com/gofiber/storage) | Драйвер зберігання який може використовуватися в різних middleware. |
| [template](https://github.com/gofiber/template) | Цей пакет містить 8 модулів шаблонів, які можна використовувати з Fiber `v1.10.x` Потрібно версія Go 1.13 або новішу. |
| [websocket](https://github.com/gofiber/websocket) | На основі Fasthttp WebSocket для Fiber з підтримкою місцевих користувачів! |

View File

@ -605,6 +605,11 @@ func main() {
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | Session 中间件. 注意: 此中间件使用了我们的存储包. |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | Skip 中间件会在判断条为 true 时忽略此次请求 |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | 添加请求的最大时间如果超时则发送给ErrorHandler 进行处理. |
| [adaptor](https://github.com/gofiber/adaptor) | net/http 处理程序与 Fiber 请求处理程序之间的转换器,特别感谢 @arsmn |
| [helmet](https://github.com/gofiber/helmet) | 通过设置各种 HTTP 头帮助保护您的应用程序 |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth 中间件提供基于密钥的身份验证 |
| [redirect](https://github.com/gofiber/redirect) | 用于重定向请求的中间件 |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite 中间件根据提供的规则重写URL路径。它有助于向后兼容或者创建更清晰、更具描述性的链接 |
## 🧬 外部中间件
@ -612,12 +617,7 @@ func main() {
| 中间件 | 描述 |
|:--------------------------------------------------|:-------------------------------------------------------------------------------------------|
| [adaptor](https://github.com/gofiber/adaptor) | net/http 处理程序与 Fiber 请求处理程序之间的转换器,特别感谢 @arsmn |
| [helmet](https://github.com/gofiber/helmet) | 通过设置各种 HTTP 头帮助保护您的应用程序 |
| [jwt](https://github.com/gofiber/jwt) | JWT 返回一个 JSON Web Token\(JWT\) 身份验证中间件 |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth 中间件提供基于密钥的身份验证 |
| [redirect](https://github.com/gofiber/redirect) | 用于重定向请求的中间件 |
| [rewrite](https://github.com/gofiber/rewrite) | Rewrite 中间件根据提供的规则重写URL路径。它有助于向后兼容或者创建更清晰、更具描述性的链接 |
| [storage](https://github.com/gofiber/storage) | 包含实现 Storage 接口的数据库驱动,它的设计旨在配合 fiber 的其他中间件来进行使用 |
| [template](https://github.com/gofiber/template) | 该中间件包含 8 个模板引擎,可与 Fiber `v1.10.x` Go 1.13或更高版本一起使用 |
| [websocket](https://github.com/gofiber/websocket) | 基于 Fasthttp WebSocket for Fiber 实现,支持使用 [Locals](https://docs.gofiber.io/api/ctx#locals) |

View File

@ -636,6 +636,11 @@ func main() {
| [session](https://github.com/gofiber/fiber/tree/master/middleware/session) | 連線階段中介模組。注意:這個中介模組有用到我們的 Storage 套件。 |
| [skip](https://github.com/gofiber/fiber/tree/master/middleware/skip) | 略過中介模組,會在條件成立時略過封裝過的處理常式。 |
| [timeout](https://github.com/gofiber/fiber/tree/master/middleware/timeout) | 為請求加上最長時限,並在逾時後轉送至錯誤處理常式 (ErrorHandler)。 |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth 中介模組提供以金鑰為基礎的認證模式。 |
| [redirect](https://github.com/gofiber/redirect) | 用來重新導向的中介模組。 |
| [rewrite](https://github.com/gofiber/rewrite) | 重寫 (Rewrite) 中介模組:根據提供規則重寫 URL 路徑,適合用來向後相容,或者是製作更乾淨且更好懂的連結。 |
| [adaptor](https://github.com/gofiber/adaptor) | 將 net/http 處理常式轉換至 Fiber 處理常式,或者是反著做。特別感謝 @arsmn |
| [helmet](https://github.com/gofiber/helmet) | 透過設定多種 HTTP 標頭,協助保護您應用程式的安全。 |
## 🧬 外掛中介模組
@ -643,12 +648,7 @@ func main() {
| 中介模組 | 描述 |
| :------------------------------------------------ | :----------------------------------------------------------------------------------------------------- |
| [adaptor](https://github.com/gofiber/adaptor) | 將 net/http 處理常式轉換至 Fiber 處理常式,或者是反著做。特別感謝 @arsmn |
| [helmet](https://github.com/gofiber/helmet) | 透過設定多種 HTTP 標頭,協助保護您應用程式的安全。 |
| [jwt](https://github.com/gofiber/jwt) | JWT 回傳 JSON Web Token \(JWT\) 認證中介模組。 |
| [keyauth](https://github.com/gofiber/keyauth) | Key auth 中介模組提供以金鑰為基礎的認證模式。 |
| [redirect](https://github.com/gofiber/redirect) | 用來重新導向的中介模組。 |
| [rewrite](https://github.com/gofiber/rewrite) | 重寫 (Rewrite) 中介模組:根據提供規則重寫 URL 路徑,適合用來向後相容,或者是製作更乾淨且更好懂的連結。 |
| [storage](https://github.com/gofiber/storage) | 已經做好,實作 Storage 介面的儲存區驅動模組,設計用來與各種 Fiber 中介模組搭配使用。 |
| [template](https://github.com/gofiber/template) | 本套件包含 8 種樣板引擎,可以和 Fiber `v1.10.x` 一起使用。需要 Go 1.13 或更新版本。 |
| [websocket](https://github.com/gofiber/websocket) | 適用於 Fiber建基於 Fasthttp 的 WebSocket。支援本機空間 (Locals) |

View File

@ -0,0 +1,135 @@
---
id: adaptor
title: Adaptor
---
Converter for net/http handlers to/from Fiber request handlers, special thanks to [@arsmn](https://github.com/arsmn)!
## Signatures
| Name | Signature | Description
| :--- | :--- | :---
| HTTPHandler | `HTTPHandler(h http.Handler) fiber.Handler` | http.Handler -> fiber.Handler
| HTTPHandlerFunc | `HTTPHandlerFunc(h http.HandlerFunc) fiber.Handler` | http.HandlerFunc -> fiber.Handler
| HTTPMiddleware | `HTTPHandlerFunc(mw func(http.Handler) http.Handler) fiber.Handler` | func(http.Handler) http.Handler -> fiber.Handler
| FiberHandler | `FiberHandler(h fiber.Handler) http.Handler` | fiber.Handler -> http.Handler
| FiberHandlerFunc | `FiberHandlerFunc(h fiber.Handler) http.HandlerFunc` | fiber.Handler -> http.HandlerFunc
| FiberApp | `FiberApp(app *fiber.App) http.HandlerFunc` | Fiber app -> http.HandlerFunc
| CopyContextToFiberContex | `CopyContextToFiberContext(context interface{}, requestContext *fasthttp.RequestCtx)` | context.Context -> fasthttp.RequestCtx
## Examples
### net/http to Fiber
```go
package main
import (
"fmt"
"net/http"
"github.com/gofiber/v2/middleware/adaptor"
"github.com/gofiber/fiber/v2"
)
func main() {
// New fiber app
app := fiber.New()
// http.Handler -> fiber.Handler
app.Get("/", adaptor.HTTPHandler(handler(greet)))
// http.HandlerFunc -> fiber.Handler
app.Get("/func", adaptor.HTTPHandlerFunc(greet))
// Listen on port 3000
app.Listen(":3000")
}
func handler(f http.HandlerFunc) http.Handler {
return http.HandlerFunc(f)
}
func greet(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello World!")
}
```
### net/http middleware to Fiber
```go
package main
import (
"log"
"net/http"
"github.com/gofiber/v2/middleware/adaptor"
"github.com/gofiber/fiber/v2"
)
func main() {
// New fiber app
app := fiber.New()
// http middleware -> fiber.Handler
app.Use(adaptor.HTTPMiddleware(logMiddleware))
// Listen on port 3000
app.Listen(":3000")
}
func logMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("log middleware")
next.ServeHTTP(w, r)
})
}
```
### Fiber Handler to net/http
```go
package main
import (
"net/http"
"github.com/gofiber/v2/middleware/adaptor"
"github.com/gofiber/fiber/v2"
)
func main() {
// fiber.Handler -> http.Handler
http.Handle("/", adaptor.FiberHandler(greet))
// fiber.Handler -> http.HandlerFunc
http.HandleFunc("/func", adaptor.FiberHandlerFunc(greet))
// Listen on port 3000
http.ListenAndServe(":3000", nil)
}
func greet(c *fiber.Ctx) error {
return c.SendString("Hello World!")
}
```
### Fiber App to net/http
```go
package main
import (
"github.com/gofiber/v2/middleware/adaptor"
"github.com/gofiber/fiber/v2"
"net/http"
)
func main() {
app := fiber.New()
app.Get("/greet", greet)
// Listen on port 3000
http.ListenAndServe(":3000", adaptor.FiberApp(app))
}
func greet(c *fiber.Ctx) error {
return c.SendString("Hello World!")
}
```

View File

@ -11,13 +11,6 @@ Filesystem middleware for [Fiber](https://github.com/gofiber/fiber) that enables
**To handle paths with spaces (or other url encoded values) make sure to set `fiber.Config{ UnescapePath: true }`**
:::
## Table of Contents
* [Signatures](filesystem.md#signatures)
* [Examples](filesystem.md#examples)
* [Config](filesystem.md#config)
* [Default Config](filesystem.md#default-config)
## Signatures
```go

View File

@ -0,0 +1,138 @@
---
id: helmet
title: Helmet
---
Helmet middleware helps secure your apps by setting various HTTP headers.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/helmet"
)
func main() {
app := fiber.New()
app.Use(helmet.New())
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome!")
})
app.Listen(":3000")
}
```
**Test:**
```curl
curl -I http://localhost:3000
```
## Config
```go
// Config defines the config for middleware.
type Config struct {
// Next defines a function to skip middleware.
// Optional. Default: nil
Next func(*fiber.Ctx) bool
// XSSProtection
// Optional. Default value "0".
XSSProtection string
// ContentTypeNosniff
// Optional. Default value "nosniff".
ContentTypeNosniff string
// XFrameOptions
// Optional. Default value "SAMEORIGIN".
// Possible values: "SAMEORIGIN", "DENY", "ALLOW-FROM uri"
XFrameOptions string
// HSTSMaxAge
// Optional. Default value 0.
HSTSMaxAge int
// HSTSExcludeSubdomains
// Optional. Default value false.
HSTSExcludeSubdomains bool
// ContentSecurityPolicy
// Optional. Default value "".
ContentSecurityPolicy string
// CSPReportOnly
// Optional. Default value false.
CSPReportOnly bool
// HSTSPreloadEnabled
// Optional. Default value false.
HSTSPreloadEnabled bool
// ReferrerPolicy
// Optional. Default value "ReferrerPolicy".
ReferrerPolicy string
// Permissions-Policy
// Optional. Default value "".
PermissionPolicy string
// Cross-Origin-Embedder-Policy
// Optional. Default value "require-corp".
CrossOriginEmbedderPolicy string
// Cross-Origin-Opener-Policy
// Optional. Default value "same-origin".
CrossOriginOpenerPolicy string
// Cross-Origin-Resource-Policy
// Optional. Default value "same-origin".
CrossOriginResourcePolicy string
// Origin-Agent-Cluster
// Optional. Default value "?1".
OriginAgentCluster string
// X-DNS-Prefetch-Control
// Optional. Default value "off".
XDNSPrefetchControl string
// X-Download-Options
// Optional. Default value "noopen".
XDownloadOptions string
// X-Permitted-Cross-Domain-Policies
// Optional. Default value "none".
XPermittedCrossDomain string
}
```
## Default Config
```go
var ConfigDefault = Config{
XSSProtection: "0",
ContentTypeNosniff: "nosniff",
XFrameOptions: "SAMEORIGIN",
ReferrerPolicy: "no-referrer",
CrossOriginEmbedderPolicy: "require-corp",
CrossOriginOpenerPolicy: "same-origin",
CrossOriginResourcePolicy: "same-origin",
OriginAgentCluster: "?1",
XDNSPrefetchControl: "off",
XDownloadOptions: "noopen",
XPermittedCrossDomain: "none",
}
```

View File

@ -0,0 +1,272 @@
---
id: keyauth
title: Keyauth
---
Key auth middleware provides a key based authentication.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
```go
package main
import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
)
var (
apiKey = "correct horse battery staple"
)
func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))
if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
}
func main() {
app := fiber.New()
// note that the keyauth middleware needs to be defined before the routes are defined!
app.Use(keyauth.New(keyauth.Config{
KeyLookup: "cookie:access_token",
Validator: validateAPIKey,
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})
app.Listen(":3000")
}
```
**Test:**
```bash
# No api-key specified -> 400 missing
curl http://localhost:3000
#> missing or malformed API Key
curl --cookie "access_token=correct horse battery staple" http://localhost:3000
#> Successfully authenticated!
curl --cookie "access_token=Clearly A Wrong Key" http://localhost:3000
#> missing or malformed API Key
```
For a more detailed example, see also the [`github.com/gofiber/recipes`](https://github.com/gofiber/recipes) repository and specifically the `fiber-envoy-extauthz` repository and the [`keyauth example`](https://github.com/gofiber/recipes/blob/master/fiber-envoy-extauthz/authz/main.go) code.
### Authenticate only certain endpoints
If you want to authenticate only certain endpoints, you can use the `Config` of keyauth and apply a filter function (eg. `authFilter`) like so
```go
package main
import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
"regexp"
"strings"
)
var (
apiKey = "correct horse battery staple"
protectedURLs = []*regexp.Regexp{
regexp.MustCompile("^/authenticated$"),
regexp.MustCompile("^/auth2$"),
}
)
func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))
if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
}
func authFilter(c *fiber.Ctx) bool {
originalURL := strings.ToLower(c.OriginalURL())
for _, pattern := range protectedURLs {
if pattern.MatchString(originalURL) {
return false
}
}
return true
}
func main() {
app := fiber.New()
app.Use(keyauth.New(keyauth.Config{
Next: authFilter,
KeyLookup: "cookie:access_token",
Validator: validateAPIKey,
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome")
})
app.Get("/authenticated", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})
app.Get("/auth2", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated 2!")
})
app.Listen(":3000")
}
```
Which results in this
```bash
# / does not need to be authenticated
curl http://localhost:3000
#> Welcome
# /authenticated needs to be authenticated
curl --cookie "access_token=correct horse battery staple" http://localhost:3000/authenticated
#> Successfully authenticated!
# /auth2 needs to be authenticated too
curl --cookie "access_token=correct horse battery staple" http://localhost:3000/auth2
#> Successfully authenticated 2!
```
### Specifying middleware in the handler
```go
package main
import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
)
const (
apiKey = "my-super-secret-key"
)
func main() {
app := fiber.New()
authMiddleware := keyauth.New(keyauth.Config{
Validator: func(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))
if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
},
})
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome")
})
app.Get("/allowed", authMiddleware, func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})
app.Listen(":3000")
}
```
Which results in this
```bash
# / does not need to be authenticated
curl http://localhost:3000
#> Welcome
# /allowed needs to be authenticated too
curl --header "Authorization: Bearer my-super-secret-key" http://localhost:3000/allowed
#> Successfully authenticated!
```
## Config
```go
// Config defines the config for middleware.
type Config struct {
// Next defines a function to skip middleware.
// Optional. Default: nil
Next func(*fiber.Ctx) bool
// SuccessHandler defines a function which is executed for a valid key.
// Optional. Default: nil
SuccessHandler fiber.Handler
// ErrorHandler defines a function which is executed for an invalid key.
// It may be used to define a custom error.
// Optional. Default: 401 Invalid or expired key
ErrorHandler fiber.ErrorHandler
// KeyLookup is a string in the form of "<source>:<name>" that is used
// to extract key from the request.
// Optional. Default value "header:Authorization".
// Possible values:
// - "header:<name>"
// - "query:<name>"
// - "form:<name>"
// - "param:<name>"
// - "cookie:<name>"
KeyLookup string
// AuthScheme to be used in the Authorization header.
// Optional. Default value "Bearer".
AuthScheme string
// Validator is a function to validate key.
Validator func(*fiber.Ctx, string) (bool, error)
// Context key to store the bearertoken from the token into context.
// Optional. Default: "token".
ContextKey string
}
```
## Default Config
```go
var ConfigDefault = Config{
SuccessHandler: func(c *fiber.Ctx) error {
return c.Next()
},
ErrorHandler: func(c *fiber.Ctx, err error) error {
if err == ErrMissingOrMalformedAPIKey {
return c.Status(fiber.StatusUnauthorized).SendString(err.Error())
}
return c.Status(fiber.StatusUnauthorized).SendString("Invalid or expired API Key")
},
KeyLookup: "header:" + fiber.HeaderAuthorization,
AuthScheme: "Bearer",
ContextKey: "token",
}
```

View File

@ -5,9 +5,6 @@ title: Pprof
Pprof middleware for [Fiber](https://github.com/gofiber/fiber) that serves via its HTTP server runtime profiling data in the format expected by the pprof visualization tool. The package is typically only imported for the side effect of registering its HTTP handlers. The handled paths all begin with /debug/pprof/.
* [Signatures](pprof.md#signatures)
* [Examples](pprof.md#examples)
## Signatures
```go

View File

@ -0,0 +1,86 @@
---
id: redirect
title: Redirect
---
Redirection middleware for Fiber.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/redirect"
)
func main() {
app := fiber.New()
app.Use(redirect.New(redirect.Config{
Rules: map[string]string{
"/old": "/new",
"/old/*": "/new/$1",
},
StatusCode: 301,
}))
app.Get("/new", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Get("/new/*", func(c *fiber.Ctx) error {
return c.SendString("Wildcard: " + c.Params("*"))
})
app.Listen(":3000")
}
```
**Test:**
```curl
curl http://localhost:3000/old
curl http://localhost:3000/old/hello
```
## Config
```go
// Config defines the config for middleware.
type Config struct {
// Filter defines a function to skip middleware.
// Optional. Default: nil
Next func(*fiber.Ctx) bool
// Rules defines the URL path rewrite rules. The values captured in asterisk can be
// retrieved by index e.g. $1, $2 and so on.
// Required. Example:
// "/old": "/new",
// "/api/*": "/$1",
// "/js/*": "/public/javascripts/$1",
// "/users/*/orders/*": "/user/$1/order/$2",
Rules map[string]string
// The status code when redirecting
// This is ignored if Redirect is disabled
// Optional. Default: 302 (fiber.StatusFound)
StatusCode int
rulesRegex map[*regexp.Regexp]string
}
```
## Default Config
```go
var ConfigDefault = Config{
StatusCode: fiber.StatusFound,
}
```

View File

@ -0,0 +1,51 @@
---
id: rewrite
title: Rewrite
---
Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
### Examples
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/rewrite"
)
func main() {
app := fiber.New()
app.Use(rewrite.New(rewrite.Config{
Rules: map[string]string{
"/old": "/new",
"/old/*": "/new/$1",
},
}))
app.Get("/new", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Get("/new/*", func(c *fiber.Ctx) error {
return c.SendString("Wildcard: " + c.Params("*"))
})
app.Listen(":3000")
}
```
**Test:**
```curl
curl http://localhost:3000/old
curl http://localhost:3000/old/hello
```

View File

@ -0,0 +1,163 @@
package adaptor
import (
"io"
"net"
"net/http"
"reflect"
"unsafe"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
"github.com/valyala/fasthttp"
"github.com/valyala/fasthttp/fasthttpadaptor"
)
// HTTPHandlerFunc wraps net/http handler func to fiber handler
func HTTPHandlerFunc(h http.HandlerFunc) fiber.Handler {
return HTTPHandler(h)
}
// HTTPHandler wraps net/http handler to fiber handler
func HTTPHandler(h http.Handler) fiber.Handler {
return func(c *fiber.Ctx) error {
handler := fasthttpadaptor.NewFastHTTPHandler(h)
handler(c.Context())
return nil
}
}
// CopyContextToFiberContext copies the values of context.Context to a fasthttp.RequestCtx
func CopyContextToFiberContext(context interface{}, requestContext *fasthttp.RequestCtx) {
contextValues := reflect.ValueOf(context).Elem()
contextKeys := reflect.TypeOf(context).Elem()
if contextKeys.Kind() == reflect.Struct {
var lastKey interface{}
for i := 0; i < contextValues.NumField(); i++ {
reflectValue := contextValues.Field(i)
/* #nosec */
reflectValue = reflect.NewAt(reflectValue.Type(), unsafe.Pointer(reflectValue.UnsafeAddr())).Elem()
reflectField := contextKeys.Field(i)
if reflectField.Name == "noCopy" {
break
} else if reflectField.Name == "Context" {
CopyContextToFiberContext(reflectValue.Interface(), requestContext)
} else if reflectField.Name == "key" {
lastKey = reflectValue.Interface()
} else if lastKey != nil && reflectField.Name == "val" {
requestContext.SetUserValue(lastKey, reflectValue.Interface())
} else {
lastKey = nil
}
}
}
}
// HTTPMiddleware wraps net/http middleware to fiber middleware
func HTTPMiddleware(mw func(http.Handler) http.Handler) fiber.Handler {
return func(c *fiber.Ctx) error {
var next bool
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next = true
// Convert again in case request may modify by middleware
c.Request().Header.SetMethod(r.Method)
c.Request().SetRequestURI(r.RequestURI)
c.Request().SetHost(r.Host)
for key, val := range r.Header {
for _, v := range val {
c.Request().Header.Set(key, v)
}
}
CopyContextToFiberContext(r.Context(), c.Context())
})
if err := HTTPHandler(mw(nextHandler))(c); err != nil {
return err
}
if next {
return c.Next()
}
return nil
}
}
// FiberHandler wraps fiber handler to net/http handler
func FiberHandler(h fiber.Handler) http.Handler {
return FiberHandlerFunc(h)
}
// FiberHandlerFunc wraps fiber handler to net/http handler func
func FiberHandlerFunc(h fiber.Handler) http.HandlerFunc {
return handlerFunc(fiber.New(), h)
}
// FiberApp wraps fiber app to net/http handler func
func FiberApp(app *fiber.App) http.HandlerFunc {
return handlerFunc(app)
}
func handlerFunc(app *fiber.App, h ...fiber.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// New fasthttp request
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
// Convert net/http -> fasthttp request
if r.Body != nil {
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, utils.StatusMessage(fiber.StatusInternalServerError), fiber.StatusInternalServerError)
return
}
req.Header.SetContentLength(len(body))
_, err = req.BodyWriter().Write(body)
if err != nil {
http.Error(w, utils.StatusMessage(fiber.StatusInternalServerError), fiber.StatusInternalServerError)
return
}
}
req.Header.SetMethod(r.Method)
req.SetRequestURI(r.RequestURI)
req.SetHost(r.Host)
for key, val := range r.Header {
for _, v := range val {
req.Header.Set(key, v)
}
}
if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil && err.(*net.AddrError).Err == "missing port in address" { //nolint:errorlint, forcetypeassert // overlinting
r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
}
remoteAddr, err := net.ResolveTCPAddr("tcp", r.RemoteAddr)
if err != nil {
http.Error(w, utils.StatusMessage(fiber.StatusInternalServerError), fiber.StatusInternalServerError)
return
}
// New fasthttp Ctx
var fctx fasthttp.RequestCtx
fctx.Init(req, remoteAddr, nil)
if len(h) > 0 {
// New fiber Ctx
ctx := app.AcquireCtx(&fctx)
defer app.ReleaseCtx(ctx)
// Execute fiber Ctx
err := h[0](ctx)
if err != nil {
_ = app.Config().ErrorHandler(ctx, err) //nolint:errcheck // not needed
}
} else {
// Execute fasthttp Ctx though app.Handler
app.Handler()(&fctx)
}
// Convert fasthttp Ctx > net/http
fctx.Response.Header.VisitAll(func(k, v []byte) {
w.Header().Add(string(k), string(v))
})
w.WriteHeader(fctx.Response.StatusCode())
_, _ = w.Write(fctx.Response.Body()) //nolint:errcheck // not needed
}
}

View File

@ -0,0 +1,462 @@
//nolint:bodyclose, contextcheck, revive // Much easier to just ignore memory leaks in tests
package adaptor
import (
"context"
"fmt"
"io"
"net"
"net/http"
"net/url"
"reflect"
"testing"
"github.com/gofiber/fiber/v2"
"github.com/valyala/fasthttp"
)
func Test_HTTPHandler(t *testing.T) {
expectedMethod := fiber.MethodPost
expectedProto := "HTTP/1.1"
expectedProtoMajor := 1
expectedProtoMinor := 1
expectedRequestURI := "/foo/bar?baz=123"
expectedBody := "body 123 foo bar baz"
expectedContentLength := len(expectedBody)
expectedHost := "foobar.com"
expectedRemoteAddr := "1.2.3.4:6789"
expectedHeader := map[string]string{
"Foo-Bar": "baz",
"Abc": "defg",
"XXX-Remote-Addr": "123.43.4543.345",
}
expectedURL, err := url.ParseRequestURI(expectedRequestURI)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
expectedContextKey := "contextKey"
expectedContextValue := "contextValue"
callsCount := 0
nethttpH := func(w http.ResponseWriter, r *http.Request) {
callsCount++
if r.Method != expectedMethod {
t.Fatalf("unexpected method %q. Expecting %q", r.Method, expectedMethod)
}
if r.Proto != expectedProto {
t.Fatalf("unexpected proto %q. Expecting %q", r.Proto, expectedProto)
}
if r.ProtoMajor != expectedProtoMajor {
t.Fatalf("unexpected protoMajor %d. Expecting %d", r.ProtoMajor, expectedProtoMajor)
}
if r.ProtoMinor != expectedProtoMinor {
t.Fatalf("unexpected protoMinor %d. Expecting %d", r.ProtoMinor, expectedProtoMinor)
}
if r.RequestURI != expectedRequestURI {
t.Fatalf("unexpected requestURI %q. Expecting %q", r.RequestURI, expectedRequestURI)
}
if r.ContentLength != int64(expectedContentLength) {
t.Fatalf("unexpected contentLength %d. Expecting %d", r.ContentLength, expectedContentLength)
}
if len(r.TransferEncoding) != 0 {
t.Fatalf("unexpected transferEncoding %q. Expecting []", r.TransferEncoding)
}
if r.Host != expectedHost {
t.Fatalf("unexpected host %q. Expecting %q", r.Host, expectedHost)
}
if r.RemoteAddr != expectedRemoteAddr {
t.Fatalf("unexpected remoteAddr %q. Expecting %q", r.RemoteAddr, expectedRemoteAddr)
}
body, err := io.ReadAll(r.Body)
if err != nil {
t.Fatalf("unexpected error when reading request body: %s", err)
}
if string(body) != expectedBody {
t.Fatalf("unexpected body %q. Expecting %q", body, expectedBody)
}
if !reflect.DeepEqual(r.URL, expectedURL) {
t.Fatalf("unexpected URL: %#v. Expecting %#v", r.URL, expectedURL)
}
if r.Context().Value(expectedContextKey) != expectedContextValue {
t.Fatalf("unexpected context value for key %q. Expecting %q", expectedContextKey, expectedContextValue)
}
for k, expectedV := range expectedHeader {
v := r.Header.Get(k)
if v != expectedV {
t.Fatalf("unexpected header value %q for key %q. Expecting %q", v, k, expectedV)
}
}
w.Header().Set("Header1", "value1")
w.Header().Set("Header2", "value2")
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "request body is %q", body)
}
fiberH := HTTPHandlerFunc(http.HandlerFunc(nethttpH))
fiberH = setFiberContextValueMiddleware(fiberH, expectedContextKey, expectedContextValue)
var fctx fasthttp.RequestCtx
var req fasthttp.Request
req.Header.SetMethod(expectedMethod)
req.SetRequestURI(expectedRequestURI)
req.Header.SetHost(expectedHost)
req.BodyWriter().Write([]byte(expectedBody)) //nolint:errcheck, gosec // not needed
for k, v := range expectedHeader {
req.Header.Set(k, v)
}
remoteAddr, err := net.ResolveTCPAddr("tcp", expectedRemoteAddr)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
fctx.Init(&req, remoteAddr, nil)
app := fiber.New()
ctx := app.AcquireCtx(&fctx)
defer app.ReleaseCtx(ctx)
err = fiberH(ctx)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if callsCount != 1 {
t.Fatalf("unexpected callsCount: %d. Expecting 1", callsCount)
}
resp := &fctx.Response
if resp.StatusCode() != fiber.StatusBadRequest {
t.Fatalf("unexpected statusCode: %d. Expecting %d", resp.StatusCode(), fiber.StatusBadRequest)
}
if string(resp.Header.Peek("Header1")) != "value1" {
t.Fatalf("unexpected header value: %q. Expecting %q", resp.Header.Peek("Header1"), "value1")
}
if string(resp.Header.Peek("Header2")) != "value2" {
t.Fatalf("unexpected header value: %q. Expecting %q", resp.Header.Peek("Header2"), "value2")
}
expectedResponseBody := fmt.Sprintf("request body is %q", expectedBody)
if string(resp.Body()) != expectedResponseBody {
t.Fatalf("unexpected response body %q. Expecting %q", resp.Body(), expectedResponseBody)
}
}
type contextKey string
func (c contextKey) String() string {
return "test-" + string(c)
}
var (
TestContextKey = contextKey("TestContextKey")
TestContextSecondKey = contextKey("TestContextSecondKey")
)
func Test_HTTPMiddleware(t *testing.T) {
tests := []struct {
name string
url string
method string
statusCode int
}{
{
name: "Should return 200",
url: "/",
method: "POST",
statusCode: 200,
},
{
name: "Should return 405",
url: "/",
method: "GET",
statusCode: 405,
},
{
name: "Should return 400",
url: "/unknown",
method: "POST",
statusCode: 404,
},
}
nethttpMW := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
r = r.WithContext(context.WithValue(r.Context(), TestContextKey, "okay"))
r = r.WithContext(context.WithValue(r.Context(), TestContextSecondKey, "not_okay"))
r = r.WithContext(context.WithValue(r.Context(), TestContextSecondKey, "okay"))
next.ServeHTTP(w, r)
})
}
app := fiber.New()
app.Use(HTTPMiddleware(nethttpMW))
app.Post("/", func(c *fiber.Ctx) error {
value := c.Context().Value(TestContextKey)
val, ok := value.(string)
if !ok {
t.Error("unexpected error on type-assertion")
}
if value != nil {
c.Set("context_okay", val)
}
value = c.Context().Value(TestContextSecondKey)
if value != nil {
val, ok := value.(string)
if !ok {
t.Error("unexpected error on type-assertion")
}
c.Set("context_second_okay", val)
}
return c.SendStatus(fiber.StatusOK)
})
for _, tt := range tests {
req, err := http.NewRequestWithContext(context.Background(), tt.method, tt.url, nil)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != tt.statusCode {
t.Fatalf(`%s: StatusCode: got %v - expected %v`, t.Name(), resp.StatusCode, tt.statusCode)
}
}
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodPost, "/", nil)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.Header.Get("context_okay") != "okay" {
t.Fatalf(`%s: Header context_okay: got %v - expected %v`, t.Name(), resp.Header.Get("context_okay"), "okay")
}
if resp.Header.Get("context_second_okay") != "okay" {
t.Fatalf(`%s: Header context_second_okay: got %v - expected %v`, t.Name(), resp.Header.Get("context_second_okay"), "okay")
}
}
func Test_FiberHandler(t *testing.T) {
testFiberToHandlerFunc(t, false)
}
func Test_FiberApp(t *testing.T) {
testFiberToHandlerFunc(t, false, fiber.New())
}
func Test_FiberHandlerDefaultPort(t *testing.T) {
testFiberToHandlerFunc(t, true)
}
func Test_FiberAppDefaultPort(t *testing.T) {
testFiberToHandlerFunc(t, true, fiber.New())
}
func testFiberToHandlerFunc(t *testing.T, checkDefaultPort bool, app ...*fiber.App) {
t.Helper()
expectedMethod := fiber.MethodPost
expectedRequestURI := "/foo/bar?baz=123"
expectedBody := "body 123 foo bar baz"
expectedContentLength := len(expectedBody)
expectedHost := "foobar.com"
expectedRemoteAddr := "1.2.3.4:6789"
if checkDefaultPort {
expectedRemoteAddr = "1.2.3.4:80"
}
expectedHeader := map[string]string{
"Foo-Bar": "baz",
"Abc": "defg",
"XXX-Remote-Addr": "123.43.4543.345",
}
expectedURL, err := url.ParseRequestURI(expectedRequestURI)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
callsCount := 0
fiberH := func(c *fiber.Ctx) error {
callsCount++
if c.Method() != expectedMethod {
t.Fatalf("unexpected method %q. Expecting %q", c.Method(), expectedMethod)
}
if string(c.Context().RequestURI()) != expectedRequestURI {
t.Fatalf("unexpected requestURI %q. Expecting %q", string(c.Context().RequestURI()), expectedRequestURI)
}
contentLength := c.Context().Request.Header.ContentLength()
if contentLength != expectedContentLength {
t.Fatalf("unexpected contentLength %d. Expecting %d", contentLength, expectedContentLength)
}
if c.Hostname() != expectedHost {
t.Fatalf("unexpected host %q. Expecting %q", c.Hostname(), expectedHost)
}
remoteAddr := c.Context().RemoteAddr().String()
if remoteAddr != expectedRemoteAddr {
t.Fatalf("unexpected remoteAddr %q. Expecting %q", remoteAddr, expectedRemoteAddr)
}
body := string(c.Body())
if body != expectedBody {
t.Fatalf("unexpected body %q. Expecting %q", body, expectedBody)
}
if c.OriginalURL() != expectedURL.String() {
t.Fatalf("unexpected URL: %#v. Expecting %#v", c.OriginalURL(), expectedURL)
}
for k, expectedV := range expectedHeader {
v := c.Get(k)
if v != expectedV {
t.Fatalf("unexpected header value %q for key %q. Expecting %q", v, k, expectedV)
}
}
c.Set("Header1", "value1")
c.Set("Header2", "value2")
c.Status(fiber.StatusBadRequest)
_, err := c.Write([]byte(fmt.Sprintf("request body is %q", body)))
return err
}
var handlerFunc http.HandlerFunc
if len(app) > 0 {
app[0].Post("/foo/bar", fiberH)
handlerFunc = FiberApp(app[0])
} else {
handlerFunc = FiberHandlerFunc(fiberH)
}
var r http.Request
r.Method = expectedMethod
r.Body = &netHTTPBody{[]byte(expectedBody)}
r.RequestURI = expectedRequestURI
r.ContentLength = int64(expectedContentLength)
r.Host = expectedHost
r.RemoteAddr = expectedRemoteAddr
if checkDefaultPort {
r.RemoteAddr = "1.2.3.4"
}
hdr := make(http.Header)
for k, v := range expectedHeader {
hdr.Set(k, v)
}
r.Header = hdr
var w netHTTPResponseWriter
handlerFunc.ServeHTTP(&w, &r)
if w.StatusCode() != http.StatusBadRequest {
t.Fatalf("unexpected statusCode: %d. Expecting %d", w.StatusCode(), http.StatusBadRequest)
}
if w.Header().Get("Header1") != "value1" {
t.Fatalf("unexpected header value: %q. Expecting %q", w.Header().Get("Header1"), "value1")
}
if w.Header().Get("Header2") != "value2" {
t.Fatalf("unexpected header value: %q. Expecting %q", w.Header().Get("Header2"), "value2")
}
expectedResponseBody := fmt.Sprintf("request body is %q", expectedBody)
if string(w.body) != expectedResponseBody {
t.Fatalf("unexpected response body %q. Expecting %q", string(w.body), expectedResponseBody)
}
}
func setFiberContextValueMiddleware(next fiber.Handler, key string, value interface{}) fiber.Handler {
return func(c *fiber.Ctx) error {
c.Locals(key, value)
return next(c)
}
}
func Test_FiberHandler_RequestNilBody(t *testing.T) {
expectedMethod := fiber.MethodGet
expectedRequestURI := "/foo/bar"
expectedContentLength := 0
callsCount := 0
fiberH := func(c *fiber.Ctx) error {
callsCount++
if c.Method() != expectedMethod {
t.Fatalf("unexpected method %q. Expecting %q", c.Method(), expectedMethod)
}
if string(c.Request().RequestURI()) != expectedRequestURI {
t.Fatalf("unexpected requestURI %q. Expecting %q", string(c.Request().RequestURI()), expectedRequestURI)
}
contentLength := c.Request().Header.ContentLength()
if contentLength != expectedContentLength {
t.Fatalf("unexpected contentLength %d. Expecting %d", contentLength, expectedContentLength)
}
_, err := c.Write([]byte("request body is nil"))
return err
}
nethttpH := FiberHandler(fiberH)
var r http.Request
r.Method = expectedMethod
r.RequestURI = expectedRequestURI
var w netHTTPResponseWriter
nethttpH.ServeHTTP(&w, &r)
expectedResponseBody := "request body is nil"
if string(w.body) != expectedResponseBody {
t.Fatalf("unexpected response body %q. Expecting %q", string(w.body), expectedResponseBody)
}
}
type netHTTPBody struct {
b []byte
}
func (r *netHTTPBody) Read(p []byte) (int, error) {
if len(r.b) == 0 {
return 0, io.EOF
}
n := copy(p, r.b)
r.b = r.b[n:]
return n, nil
}
func (r *netHTTPBody) Close() error {
r.b = r.b[:0]
return nil
}
type netHTTPResponseWriter struct {
statusCode int
h http.Header
body []byte
}
func (w *netHTTPResponseWriter) StatusCode() int {
if w.statusCode == 0 {
return http.StatusOK
}
return w.statusCode
}
func (w *netHTTPResponseWriter) Header() http.Header {
if w.h == nil {
w.h = make(http.Header)
}
return w.h
}
func (w *netHTTPResponseWriter) WriteHeader(statusCode int) {
w.statusCode = statusCode
}
func (w *netHTTPResponseWriter) Write(p []byte) (int, error) {
w.body = append(w.body, p...)
return len(p), nil
}

154
middleware/helmet/config.go Normal file
View File

@ -0,0 +1,154 @@
package helmet
import (
"github.com/gofiber/fiber/v2"
)
// Config defines the config for middleware.
type Config struct {
// Next defines a function to skip middleware.
// Optional. Default: nil
Next func(*fiber.Ctx) bool
// XSSProtection
// Optional. Default value "0".
XSSProtection string
// ContentTypeNosniff
// Optional. Default value "nosniff".
ContentTypeNosniff string
// XFrameOptions
// Optional. Default value "SAMEORIGIN".
// Possible values: "SAMEORIGIN", "DENY", "ALLOW-FROM uri"
XFrameOptions string
// HSTSMaxAge
// Optional. Default value 0.
HSTSMaxAge int
// HSTSExcludeSubdomains
// Optional. Default value false.
HSTSExcludeSubdomains bool
// ContentSecurityPolicy
// Optional. Default value "".
ContentSecurityPolicy string
// CSPReportOnly
// Optional. Default value false.
CSPReportOnly bool
// HSTSPreloadEnabled
// Optional. Default value false.
HSTSPreloadEnabled bool
// ReferrerPolicy
// Optional. Default value "ReferrerPolicy".
ReferrerPolicy string
// Permissions-Policy
// Optional. Default value "".
PermissionPolicy string
// Cross-Origin-Embedder-Policy
// Optional. Default value "require-corp".
CrossOriginEmbedderPolicy string
// Cross-Origin-Opener-Policy
// Optional. Default value "same-origin".
CrossOriginOpenerPolicy string
// Cross-Origin-Resource-Policy
// Optional. Default value "same-origin".
CrossOriginResourcePolicy string
// Origin-Agent-Cluster
// Optional. Default value "?1".
OriginAgentCluster string
// X-DNS-Prefetch-Control
// Optional. Default value "off".
XDNSPrefetchControl string
// X-Download-Options
// Optional. Default value "noopen".
XDownloadOptions string
// X-Permitted-Cross-Domain-Policies
// Optional. Default value "none".
XPermittedCrossDomain string
}
// ConfigDefault is the default config
var ConfigDefault = Config{
XSSProtection: "0",
ContentTypeNosniff: "nosniff",
XFrameOptions: "SAMEORIGIN",
ReferrerPolicy: "no-referrer",
CrossOriginEmbedderPolicy: "require-corp",
CrossOriginOpenerPolicy: "same-origin",
CrossOriginResourcePolicy: "same-origin",
OriginAgentCluster: "?1",
XDNSPrefetchControl: "off",
XDownloadOptions: "noopen",
XPermittedCrossDomain: "none",
}
// Helper function to set default values
func configDefault(config ...Config) Config {
// Return default config if nothing provided
if len(config) < 1 {
return ConfigDefault
}
// Override default config
cfg := config[0]
// Set default values
if cfg.XSSProtection == "" {
cfg.XSSProtection = ConfigDefault.XSSProtection
}
if cfg.ContentTypeNosniff == "" {
cfg.ContentTypeNosniff = ConfigDefault.ContentTypeNosniff
}
if cfg.XFrameOptions == "" {
cfg.XFrameOptions = ConfigDefault.XFrameOptions
}
if cfg.ReferrerPolicy == "" {
cfg.ReferrerPolicy = ConfigDefault.ReferrerPolicy
}
if cfg.CrossOriginEmbedderPolicy == "" {
cfg.CrossOriginEmbedderPolicy = ConfigDefault.CrossOriginEmbedderPolicy
}
if cfg.CrossOriginOpenerPolicy == "" {
cfg.CrossOriginOpenerPolicy = ConfigDefault.CrossOriginOpenerPolicy
}
if cfg.CrossOriginResourcePolicy == "" {
cfg.CrossOriginResourcePolicy = ConfigDefault.CrossOriginResourcePolicy
}
if cfg.OriginAgentCluster == "" {
cfg.OriginAgentCluster = ConfigDefault.OriginAgentCluster
}
if cfg.XDNSPrefetchControl == "" {
cfg.XDNSPrefetchControl = ConfigDefault.XDNSPrefetchControl
}
if cfg.XDownloadOptions == "" {
cfg.XDownloadOptions = ConfigDefault.XDownloadOptions
}
if cfg.XPermittedCrossDomain == "" {
cfg.XPermittedCrossDomain = ConfigDefault.XPermittedCrossDomain
}
return cfg
}

View File

@ -0,0 +1,94 @@
package helmet
import (
"fmt"
"github.com/gofiber/fiber/v2"
)
// New creates a new middleware handler
func New(config ...Config) fiber.Handler {
// Init config
cfg := configDefault(config...)
// Return middleware handler
return func(c *fiber.Ctx) error {
// Next request to skip middleware
if cfg.Next != nil && cfg.Next(c) {
return c.Next()
}
// Set headers
if cfg.XSSProtection != "" {
c.Set(fiber.HeaderXXSSProtection, cfg.XSSProtection)
}
if cfg.ContentTypeNosniff != "" {
c.Set(fiber.HeaderXContentTypeOptions, cfg.ContentTypeNosniff)
}
if cfg.XFrameOptions != "" {
c.Set(fiber.HeaderXFrameOptions, cfg.XFrameOptions)
}
if cfg.CrossOriginEmbedderPolicy != "" {
c.Set("Cross-Origin-Embedder-Policy", cfg.CrossOriginEmbedderPolicy)
}
if cfg.CrossOriginOpenerPolicy != "" {
c.Set("Cross-Origin-Opener-Policy", cfg.CrossOriginOpenerPolicy)
}
if cfg.CrossOriginResourcePolicy != "" {
c.Set("Cross-Origin-Resource-Policy", cfg.CrossOriginResourcePolicy)
}
if cfg.OriginAgentCluster != "" {
c.Set("Origin-Agent-Cluster", cfg.OriginAgentCluster)
}
if cfg.ReferrerPolicy != "" {
c.Set("Referrer-Policy", cfg.ReferrerPolicy)
}
if cfg.XDNSPrefetchControl != "" {
c.Set("X-DNS-Prefetch-Control", cfg.XDNSPrefetchControl)
}
if cfg.XDownloadOptions != "" {
c.Set("X-Download-Options", cfg.XDownloadOptions)
}
if cfg.XPermittedCrossDomain != "" {
c.Set("X-Permitted-Cross-Domain-Policies", cfg.XPermittedCrossDomain)
}
// Handle HSTS headers
if c.Protocol() == "https" && cfg.HSTSMaxAge != 0 {
subdomains := ""
if !cfg.HSTSExcludeSubdomains {
subdomains = "; includeSubDomains"
}
if cfg.HSTSPreloadEnabled {
subdomains = fmt.Sprintf("%s; preload", subdomains)
}
c.Set(fiber.HeaderStrictTransportSecurity, fmt.Sprintf("max-age=%d%s", cfg.HSTSMaxAge, subdomains))
}
// Handle Content-Security-Policy headers
if cfg.ContentSecurityPolicy != "" {
if cfg.CSPReportOnly {
c.Set(fiber.HeaderContentSecurityPolicyReportOnly, cfg.ContentSecurityPolicy)
} else {
c.Set(fiber.HeaderContentSecurityPolicy, cfg.ContentSecurityPolicy)
}
}
// Handle Permissions-Policy headers
if cfg.PermissionPolicy != "" {
c.Set(fiber.HeaderPermissionsPolicy, cfg.PermissionPolicy)
}
return c.Next()
}
}

View File

@ -0,0 +1,201 @@
package helmet
import (
"net/http/httptest"
"testing"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
)
func Test_Default(t *testing.T) {
app := fiber.New()
app.Use(New())
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "0", resp.Header.Get(fiber.HeaderXXSSProtection))
utils.AssertEqual(t, "nosniff", resp.Header.Get(fiber.HeaderXContentTypeOptions))
utils.AssertEqual(t, "SAMEORIGIN", resp.Header.Get(fiber.HeaderXFrameOptions))
utils.AssertEqual(t, "", resp.Header.Get(fiber.HeaderContentSecurityPolicy))
utils.AssertEqual(t, "no-referrer", resp.Header.Get(fiber.HeaderReferrerPolicy))
utils.AssertEqual(t, "", resp.Header.Get(fiber.HeaderPermissionsPolicy))
utils.AssertEqual(t, "require-corp", resp.Header.Get("Cross-Origin-Embedder-Policy"))
utils.AssertEqual(t, "same-origin", resp.Header.Get("Cross-Origin-Opener-Policy"))
utils.AssertEqual(t, "same-origin", resp.Header.Get("Cross-Origin-Resource-Policy"))
utils.AssertEqual(t, "?1", resp.Header.Get("Origin-Agent-Cluster"))
utils.AssertEqual(t, "off", resp.Header.Get("X-DNS-Prefetch-Control"))
utils.AssertEqual(t, "noopen", resp.Header.Get("X-Download-Options"))
utils.AssertEqual(t, "none", resp.Header.Get("X-Permitted-Cross-Domain-Policies"))
}
func Test_CustomValues_AllHeaders(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
// Custom values for all headers
XSSProtection: "0",
ContentTypeNosniff: "custom-nosniff",
XFrameOptions: "DENY",
HSTSExcludeSubdomains: true,
ContentSecurityPolicy: "default-src 'none'",
CSPReportOnly: true,
HSTSPreloadEnabled: true,
ReferrerPolicy: "origin",
PermissionPolicy: "geolocation=(self)",
CrossOriginEmbedderPolicy: "custom-value",
CrossOriginOpenerPolicy: "custom-value",
CrossOriginResourcePolicy: "custom-value",
OriginAgentCluster: "custom-value",
XDNSPrefetchControl: "custom-control",
XDownloadOptions: "custom-options",
XPermittedCrossDomain: "custom-policies",
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, nil, err)
// Assertions for custom header values
utils.AssertEqual(t, "0", resp.Header.Get(fiber.HeaderXXSSProtection))
utils.AssertEqual(t, "custom-nosniff", resp.Header.Get(fiber.HeaderXContentTypeOptions))
utils.AssertEqual(t, "DENY", resp.Header.Get(fiber.HeaderXFrameOptions))
utils.AssertEqual(t, "default-src 'none'", resp.Header.Get(fiber.HeaderContentSecurityPolicyReportOnly))
utils.AssertEqual(t, "origin", resp.Header.Get(fiber.HeaderReferrerPolicy))
utils.AssertEqual(t, "geolocation=(self)", resp.Header.Get(fiber.HeaderPermissionsPolicy))
utils.AssertEqual(t, "custom-value", resp.Header.Get("Cross-Origin-Embedder-Policy"))
utils.AssertEqual(t, "custom-value", resp.Header.Get("Cross-Origin-Opener-Policy"))
utils.AssertEqual(t, "custom-value", resp.Header.Get("Cross-Origin-Resource-Policy"))
utils.AssertEqual(t, "custom-value", resp.Header.Get("Origin-Agent-Cluster"))
utils.AssertEqual(t, "custom-control", resp.Header.Get("X-DNS-Prefetch-Control"))
utils.AssertEqual(t, "custom-options", resp.Header.Get("X-Download-Options"))
utils.AssertEqual(t, "custom-policies", resp.Header.Get("X-Permitted-Cross-Domain-Policies"))
}
func Test_RealWorldValues_AllHeaders(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
// Real-world values for all headers
XSSProtection: "0",
ContentTypeNosniff: "nosniff",
XFrameOptions: "SAMEORIGIN",
HSTSExcludeSubdomains: false,
ContentSecurityPolicy: "default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests",
CSPReportOnly: false,
HSTSPreloadEnabled: true,
ReferrerPolicy: "no-referrer",
PermissionPolicy: "geolocation=(self)",
CrossOriginEmbedderPolicy: "require-corp",
CrossOriginOpenerPolicy: "same-origin",
CrossOriginResourcePolicy: "same-origin",
OriginAgentCluster: "?1",
XDNSPrefetchControl: "off",
XDownloadOptions: "noopen",
XPermittedCrossDomain: "none",
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, nil, err)
// Assertions for real-world header values
utils.AssertEqual(t, "0", resp.Header.Get(fiber.HeaderXXSSProtection))
utils.AssertEqual(t, "nosniff", resp.Header.Get(fiber.HeaderXContentTypeOptions))
utils.AssertEqual(t, "SAMEORIGIN", resp.Header.Get(fiber.HeaderXFrameOptions))
utils.AssertEqual(t, "default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests", resp.Header.Get(fiber.HeaderContentSecurityPolicy))
utils.AssertEqual(t, "no-referrer", resp.Header.Get(fiber.HeaderReferrerPolicy))
utils.AssertEqual(t, "geolocation=(self)", resp.Header.Get(fiber.HeaderPermissionsPolicy))
utils.AssertEqual(t, "require-corp", resp.Header.Get("Cross-Origin-Embedder-Policy"))
utils.AssertEqual(t, "same-origin", resp.Header.Get("Cross-Origin-Opener-Policy"))
utils.AssertEqual(t, "same-origin", resp.Header.Get("Cross-Origin-Resource-Policy"))
utils.AssertEqual(t, "?1", resp.Header.Get("Origin-Agent-Cluster"))
utils.AssertEqual(t, "off", resp.Header.Get("X-DNS-Prefetch-Control"))
utils.AssertEqual(t, "noopen", resp.Header.Get("X-Download-Options"))
utils.AssertEqual(t, "none", resp.Header.Get("X-Permitted-Cross-Domain-Policies"))
}
func Test_Next(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
Next: func(ctx *fiber.Ctx) bool {
return ctx.Path() == "/next"
},
ReferrerPolicy: "no-referrer",
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Get("/next", func(c *fiber.Ctx) error {
return c.SendString("Skipped!")
})
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "no-referrer", resp.Header.Get(fiber.HeaderReferrerPolicy))
resp, err = app.Test(httptest.NewRequest(fiber.MethodGet, "/next", nil))
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "", resp.Header.Get(fiber.HeaderReferrerPolicy))
}
func Test_ContentSecurityPolicy(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
ContentSecurityPolicy: "default-src 'none'",
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "default-src 'none'", resp.Header.Get(fiber.HeaderContentSecurityPolicy))
}
func Test_ContentSecurityPolicyReportOnly(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
ContentSecurityPolicy: "default-src 'none'",
CSPReportOnly: true,
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "default-src 'none'", resp.Header.Get(fiber.HeaderContentSecurityPolicyReportOnly))
utils.AssertEqual(t, "", resp.Header.Get(fiber.HeaderContentSecurityPolicy))
}
func Test_PermissionsPolicy(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
PermissionPolicy: "microphone=()",
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, "microphone=()", resp.Header.Get(fiber.HeaderPermissionsPolicy))
}

View File

@ -0,0 +1,95 @@
package keyauth
import (
"errors"
"github.com/gofiber/fiber/v2"
)
// Config defines the config for middleware.
type Config struct {
// Next defines a function to skip middleware.
// Optional. Default: nil
Next func(*fiber.Ctx) bool
// SuccessHandler defines a function which is executed for a valid key.
// Optional. Default: nil
SuccessHandler fiber.Handler
// ErrorHandler defines a function which is executed for an invalid key.
// It may be used to define a custom error.
// Optional. Default: 401 Invalid or expired key
ErrorHandler fiber.ErrorHandler
// KeyLookup is a string in the form of "<source>:<name>" that is used
// to extract key from the request.
// Optional. Default value "header:Authorization".
// Possible values:
// - "header:<name>"
// - "query:<name>"
// - "form:<name>"
// - "param:<name>"
// - "cookie:<name>"
KeyLookup string
// AuthScheme to be used in the Authorization header.
// Optional. Default value "Bearer".
AuthScheme string
// Validator is a function to validate key.
Validator func(*fiber.Ctx, string) (bool, error)
// Context key to store the bearertoken from the token into context.
// Optional. Default: "token".
ContextKey string
}
// ConfigDefault is the default config
var ConfigDefault = Config{
SuccessHandler: func(c *fiber.Ctx) error {
return c.Next()
},
ErrorHandler: func(c *fiber.Ctx, err error) error {
if errors.Is(err, ErrMissingOrMalformedAPIKey) {
return c.Status(fiber.StatusUnauthorized).SendString(err.Error())
}
return c.Status(fiber.StatusUnauthorized).SendString("Invalid or expired API Key")
},
KeyLookup: "header:" + fiber.HeaderAuthorization,
AuthScheme: "Bearer",
ContextKey: "token",
}
// Helper function to set default values
func configDefault(config ...Config) Config {
// Return default config if nothing provided
if len(config) < 1 {
return ConfigDefault
}
// Override default config
cfg := config[0]
// Set default values
if cfg.SuccessHandler == nil {
cfg.SuccessHandler = ConfigDefault.SuccessHandler
}
if cfg.ErrorHandler == nil {
cfg.ErrorHandler = ConfigDefault.ErrorHandler
}
if cfg.KeyLookup == "" {
cfg.KeyLookup = ConfigDefault.KeyLookup
// set AuthScheme as "Bearer" only if KeyLookup is set to default.
if cfg.AuthScheme == "" {
cfg.AuthScheme = ConfigDefault.AuthScheme
}
}
if cfg.Validator == nil {
panic("fiber: keyauth middleware requires a validator function")
}
if cfg.ContextKey == "" {
cfg.ContextKey = ConfigDefault.ContextKey
}
return cfg
}

View File

@ -0,0 +1,121 @@
// Special thanks to Echo: https://github.com/labstack/echo/blob/master/middleware/key_auth.go
package keyauth
import (
"errors"
"net/url"
"strings"
"github.com/gofiber/fiber/v2"
)
// When there is no request of the key thrown ErrMissingOrMalformedAPIKey
var ErrMissingOrMalformedAPIKey = errors.New("missing or malformed API Key")
const (
query = "query"
form = "form"
param = "param"
cookie = "cookie"
)
// New creates a new middleware handler
func New(config ...Config) fiber.Handler {
// Init config
cfg := configDefault(config...)
// Initialize
parts := strings.Split(cfg.KeyLookup, ":")
extractor := keyFromHeader(parts[1], cfg.AuthScheme)
switch parts[0] {
case query:
extractor = keyFromQuery(parts[1])
case form:
extractor = keyFromForm(parts[1])
case param:
extractor = keyFromParam(parts[1])
case cookie:
extractor = keyFromCookie(parts[1])
}
// Return middleware handler
return func(c *fiber.Ctx) error {
// Filter request to skip middleware
if cfg.Next != nil && cfg.Next(c) {
return c.Next()
}
// Extract and verify key
key, err := extractor(c)
if err != nil {
return cfg.ErrorHandler(c, err)
}
valid, err := cfg.Validator(c, key)
if err == nil && valid {
c.Locals(cfg.ContextKey, key)
return cfg.SuccessHandler(c)
}
return cfg.ErrorHandler(c, err)
}
}
// keyFromHeader returns a function that extracts api key from the request header.
func keyFromHeader(header, authScheme string) func(c *fiber.Ctx) (string, error) {
return func(c *fiber.Ctx) (string, error) {
auth := c.Get(header)
l := len(authScheme)
if len(auth) > 0 && l == 0 {
return auth, nil
}
if len(auth) > l+1 && auth[:l] == authScheme {
return auth[l+1:], nil
}
return "", ErrMissingOrMalformedAPIKey
}
}
// keyFromQuery returns a function that extracts api key from the query string.
func keyFromQuery(param string) func(c *fiber.Ctx) (string, error) {
return func(c *fiber.Ctx) (string, error) {
key := c.Query(param)
if key == "" {
return "", ErrMissingOrMalformedAPIKey
}
return key, nil
}
}
// keyFromForm returns a function that extracts api key from the form.
func keyFromForm(param string) func(c *fiber.Ctx) (string, error) {
return func(c *fiber.Ctx) (string, error) {
key := c.FormValue(param)
if key == "" {
return "", ErrMissingOrMalformedAPIKey
}
return key, nil
}
}
// keyFromParam returns a function that extracts api key from the url param string.
func keyFromParam(param string) func(c *fiber.Ctx) (string, error) {
return func(c *fiber.Ctx) (string, error) {
key, err := url.PathUnescape(c.Params(param))
if err != nil {
return "", ErrMissingOrMalformedAPIKey
}
return key, nil
}
}
// keyFromCookie returns a function that extracts api key from the named cookie.
func keyFromCookie(name string) func(c *fiber.Ctx) (string, error) {
return func(c *fiber.Ctx) (string, error) {
key := c.Cookies(name)
if key == "" {
return "", ErrMissingOrMalformedAPIKey
}
return key, nil
}
}

View File

@ -0,0 +1,461 @@
//nolint:bodyclose // Much easier to just ignore memory leaks in tests
package keyauth
import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
)
const CorrectKey = "specials: !$%,.#\"!?~`<>@$^*(){}[]|/\\123"
func TestAuthSources(t *testing.T) {
// define test cases
testSources := []string{"header", "cookie", "query", "param", "form"}
tests := []struct {
route string
authTokenName string
description string
APIKey string
expectedCode int
expectedBody string
}{
{
route: "/",
authTokenName: "access_token",
description: "auth with correct key",
APIKey: CorrectKey,
expectedCode: 200,
expectedBody: "Success!",
},
{
route: "/",
authTokenName: "access_token",
description: "auth with no key",
APIKey: "",
expectedCode: 401, // 404 in case of param authentication
expectedBody: "missing or malformed API Key",
},
{
route: "/",
authTokenName: "access_token",
description: "auth with wrong key",
APIKey: "WRONGKEY",
expectedCode: 401,
expectedBody: "missing or malformed API Key",
},
}
for _, authSource := range testSources {
t.Run(authSource, func(t *testing.T) {
for _, test := range tests {
// setup the fiber endpoint
// note that if UnescapePath: false (the default)
// escaped characters (such as `\"`) will not be handled correctly in the tests
app := fiber.New(fiber.Config{UnescapePath: true})
authMiddleware := New(Config{
KeyLookup: authSource + ":" + test.authTokenName,
Validator: func(c *fiber.Ctx, key string) (bool, error) {
if key == CorrectKey {
return true, nil
}
return false, ErrMissingOrMalformedAPIKey
},
})
var route string
if authSource == param {
route = test.route + ":" + test.authTokenName
app.Use(route, authMiddleware)
} else {
route = test.route
app.Use(authMiddleware)
}
app.Get(route, func(c *fiber.Ctx) error {
return c.SendString("Success!")
})
// construct the test HTTP request
var req *http.Request
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, test.route, nil)
utils.AssertEqual(t, err, nil)
// setup the apikey for the different auth schemes
if authSource == "header" {
req.Header.Set(test.authTokenName, test.APIKey)
} else if authSource == "cookie" {
req.Header.Set("Cookie", test.authTokenName+"="+test.APIKey)
} else if authSource == "query" || authSource == "form" {
q := req.URL.Query()
q.Add(test.authTokenName, test.APIKey)
req.URL.RawQuery = q.Encode()
} else if authSource == "param" {
r := req.URL.Path
r += url.PathEscape(test.APIKey)
req.URL.Path = r
}
res, err := app.Test(req, -1)
utils.AssertEqual(t, nil, err, test.description)
// test the body of the request
body, err := io.ReadAll(res.Body)
// for param authentication, the route would be /:access_token
// when the access_token is empty, it leads to a 404 (not found)
// not a 401 (auth error)
if authSource == "param" && test.APIKey == "" {
test.expectedCode = 404
test.expectedBody = "Cannot GET /"
}
utils.AssertEqual(t, test.expectedCode, res.StatusCode, test.description)
// body
utils.AssertEqual(t, nil, err, test.description)
utils.AssertEqual(t, test.expectedBody, string(body), test.description)
err = res.Body.Close()
utils.AssertEqual(t, err, nil)
}
})
}
}
func TestMultipleKeyAuth(t *testing.T) {
// setup the fiber endpoint
app := fiber.New()
// setup keyauth for /auth1
app.Use(New(Config{
Next: func(c *fiber.Ctx) bool {
return c.OriginalURL() != "/auth1"
},
KeyLookup: "header:key",
Validator: func(c *fiber.Ctx, key string) (bool, error) {
if key == "password1" {
return true, nil
}
return false, ErrMissingOrMalformedAPIKey
},
}))
// setup keyauth for /auth2
app.Use(New(Config{
Next: func(c *fiber.Ctx) bool {
return c.OriginalURL() != "/auth2"
},
KeyLookup: "header:key",
Validator: func(c *fiber.Ctx, key string) (bool, error) {
if key == "password2" {
return true, nil
}
return false, ErrMissingOrMalformedAPIKey
},
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("No auth needed!")
})
app.Get("/auth1", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated for auth1!")
})
app.Get("/auth2", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated for auth2!")
})
// define test cases
tests := []struct {
route string
description string
APIKey string
expectedCode int
expectedBody string
}{
// No auth needed for /
{
route: "/",
description: "No password needed",
APIKey: "",
expectedCode: 200,
expectedBody: "No auth needed!",
},
// auth needed for auth1
{
route: "/auth1",
description: "Normal Authentication Case",
APIKey: "password1",
expectedCode: 200,
expectedBody: "Successfully authenticated for auth1!",
},
{
route: "/auth1",
description: "Wrong API Key",
APIKey: "WRONG KEY",
expectedCode: 401,
expectedBody: "missing or malformed API Key",
},
{
route: "/auth1",
description: "Wrong API Key",
APIKey: "", // NO KEY
expectedCode: 401,
expectedBody: "missing or malformed API Key",
},
// Auth 2 has a different password
{
route: "/auth2",
description: "Normal Authentication Case for auth2",
APIKey: "password2",
expectedCode: 200,
expectedBody: "Successfully authenticated for auth2!",
},
{
route: "/auth2",
description: "Wrong API Key",
APIKey: "WRONG KEY",
expectedCode: 401,
expectedBody: "missing or malformed API Key",
},
{
route: "/auth2",
description: "Wrong API Key",
APIKey: "", // NO KEY
expectedCode: 401,
expectedBody: "missing or malformed API Key",
},
}
// run the tests
for _, test := range tests {
var req *http.Request
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, test.route, nil)
utils.AssertEqual(t, err, nil)
if test.APIKey != "" {
req.Header.Set("key", test.APIKey)
}
res, err := app.Test(req, -1)
utils.AssertEqual(t, nil, err, test.description)
// test the body of the request
body, err := io.ReadAll(res.Body)
utils.AssertEqual(t, test.expectedCode, res.StatusCode, test.description)
// body
utils.AssertEqual(t, nil, err, test.description)
utils.AssertEqual(t, test.expectedBody, string(body), test.description)
}
}
func TestCustomSuccessAndFailureHandlers(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
SuccessHandler: func(c *fiber.Ctx) error {
return c.Status(fiber.StatusOK).SendString("API key is valid and request was handled by custom success handler")
},
ErrorHandler: func(c *fiber.Ctx, err error) error {
return c.Status(fiber.StatusUnauthorized).SendString("API key is invalid and request was handled by custom error handler")
},
Validator: func(c *fiber.Ctx, key string) (bool, error) {
if key == CorrectKey {
return true, nil
}
return false, ErrMissingOrMalformedAPIKey
},
}))
// Define a test handler that should not be called
app.Get("/", func(c *fiber.Ctx) error {
t.Error("Test handler should not be called")
return nil
})
// Create a request without an API key and send it to the app
res, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, err, nil)
// Read the response body into a string
body, err := io.ReadAll(res.Body)
utils.AssertEqual(t, err, nil)
// Check that the response has the expected status code and body
utils.AssertEqual(t, res.StatusCode, http.StatusUnauthorized)
utils.AssertEqual(t, string(body), "API key is invalid and request was handled by custom error handler")
// Create a request with a valid API key in the Authorization header
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", CorrectKey))
// Send the request to the app
res, err = app.Test(req)
utils.AssertEqual(t, err, nil)
// Read the response body into a string
body, err = io.ReadAll(res.Body)
utils.AssertEqual(t, err, nil)
// Check that the response has the expected status code and body
utils.AssertEqual(t, res.StatusCode, http.StatusOK)
utils.AssertEqual(t, string(body), "API key is valid and request was handled by custom success handler")
}
func TestCustomNextFunc(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
Next: func(c *fiber.Ctx) bool {
return c.Path() == "/allowed"
},
Validator: func(c *fiber.Ctx, key string) (bool, error) {
if key == CorrectKey {
return true, nil
}
return false, ErrMissingOrMalformedAPIKey
},
}))
// Define a test handler
app.Get("/allowed", func(c *fiber.Ctx) error {
return c.SendString("API key is valid and request was allowed by custom filter")
})
// Create a request with the "/allowed" path and send it to the app
req := httptest.NewRequest(fiber.MethodGet, "/allowed", nil)
res, err := app.Test(req)
utils.AssertEqual(t, err, nil)
// Read the response body into a string
body, err := io.ReadAll(res.Body)
utils.AssertEqual(t, err, nil)
// Check that the response has the expected status code and body
utils.AssertEqual(t, res.StatusCode, http.StatusOK)
utils.AssertEqual(t, string(body), "API key is valid and request was allowed by custom filter")
// Create a request with a different path and send it to the app without correct key
req = httptest.NewRequest(fiber.MethodGet, "/not-allowed", nil)
res, err = app.Test(req)
utils.AssertEqual(t, err, nil)
// Read the response body into a string
body, err = io.ReadAll(res.Body)
utils.AssertEqual(t, err, nil)
// Check that the response has the expected status code and body
utils.AssertEqual(t, res.StatusCode, http.StatusUnauthorized)
utils.AssertEqual(t, string(body), ErrMissingOrMalformedAPIKey.Error())
// Create a request with a different path and send it to the app with correct key
req = httptest.NewRequest(fiber.MethodGet, "/not-allowed", nil)
req.Header.Add("Authorization", fmt.Sprintf("Basic %s", CorrectKey))
res, err = app.Test(req)
utils.AssertEqual(t, err, nil)
// Read the response body into a string
body, err = io.ReadAll(res.Body)
utils.AssertEqual(t, err, nil)
// Check that the response has the expected status code and body
utils.AssertEqual(t, res.StatusCode, http.StatusUnauthorized)
utils.AssertEqual(t, string(body), ErrMissingOrMalformedAPIKey.Error())
}
func TestAuthSchemeToken(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
AuthScheme: "Token",
Validator: func(c *fiber.Ctx, key string) (bool, error) {
if key == CorrectKey {
return true, nil
}
return false, ErrMissingOrMalformedAPIKey
},
}))
// Define a test handler
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("API key is valid")
})
// Create a request with a valid API key in the "Token" Authorization header
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Add("Authorization", fmt.Sprintf("Token %s", CorrectKey))
// Send the request to the app
res, err := app.Test(req)
utils.AssertEqual(t, err, nil)
// Read the response body into a string
body, err := io.ReadAll(res.Body)
utils.AssertEqual(t, err, nil)
// Check that the response has the expected status code and body
utils.AssertEqual(t, res.StatusCode, http.StatusOK)
utils.AssertEqual(t, string(body), "API key is valid")
}
func TestAuthSchemeBasic(t *testing.T) {
app := fiber.New()
app.Use(New(Config{
KeyLookup: "header:Authorization",
AuthScheme: "Basic",
Validator: func(c *fiber.Ctx, key string) (bool, error) {
if key == CorrectKey {
return true, nil
}
return false, ErrMissingOrMalformedAPIKey
},
}))
// Define a test handler
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("API key is valid")
})
// Create a request without an API key and Send the request to the app
res, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil))
utils.AssertEqual(t, err, nil)
// Read the response body into a string
body, err := io.ReadAll(res.Body)
utils.AssertEqual(t, err, nil)
// Check that the response has the expected status code and body
utils.AssertEqual(t, res.StatusCode, http.StatusUnauthorized)
utils.AssertEqual(t, string(body), ErrMissingOrMalformedAPIKey.Error())
// Create a request with a valid API key in the "Authorization" header using the "Basic" scheme
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
req.Header.Add("Authorization", fmt.Sprintf("Basic %s", CorrectKey))
// Send the request to the app
res, err = app.Test(req)
utils.AssertEqual(t, err, nil)
// Read the response body into a string
body, err = io.ReadAll(res.Body)
utils.AssertEqual(t, err, nil)
// Check that the response has the expected status code and body
utils.AssertEqual(t, res.StatusCode, http.StatusOK)
utils.AssertEqual(t, string(body), "API key is valid")
}

View File

@ -0,0 +1,53 @@
package redirect
import (
"regexp"
"github.com/gofiber/fiber/v2"
)
// Config defines the config for middleware.
type Config struct {
// Filter defines a function to skip middleware.
// Optional. Default: nil
Next func(*fiber.Ctx) bool
// Rules defines the URL path rewrite rules. The values captured in asterisk can be
// retrieved by index e.g. $1, $2 and so on.
// Required. Example:
// "/old": "/new",
// "/api/*": "/$1",
// "/js/*": "/public/javascripts/$1",
// "/users/*/orders/*": "/user/$1/order/$2",
Rules map[string]string
// The status code when redirecting
// This is ignored if Redirect is disabled
// Optional. Default: 302 Temporary Redirect
StatusCode int
rulesRegex map[*regexp.Regexp]string
}
// ConfigDefault is the default config
var ConfigDefault = Config{
StatusCode: fiber.StatusFound,
}
// Helper function to set default values
func configDefault(config ...Config) Config {
// Return default config if nothing provided
if len(config) < 1 {
return ConfigDefault
}
// Override default config
cfg := config[0]
// Set default values
if cfg.StatusCode == 0 {
cfg.StatusCode = ConfigDefault.StatusCode
}
return cfg
}

View File

@ -0,0 +1,57 @@
package redirect
import (
"regexp"
"strconv"
"strings"
"github.com/gofiber/fiber/v2"
)
// New creates a new middleware handler
func New(config ...Config) fiber.Handler {
cfg := configDefault(config...)
// Initialize
cfg.rulesRegex = map[*regexp.Regexp]string{}
for k, v := range cfg.Rules {
k = strings.ReplaceAll(k, "*", "(.*)")
k += "$"
cfg.rulesRegex[regexp.MustCompile(k)] = v
}
// Middleware function
return func(c *fiber.Ctx) error {
// Next request to skip middleware
if cfg.Next != nil && cfg.Next(c) {
return c.Next()
}
// Rewrite
for k, v := range cfg.rulesRegex {
replacer := captureTokens(k, c.Path())
if replacer != nil {
return c.Redirect(replacer.Replace(v), cfg.StatusCode)
}
}
return c.Next()
}
}
// https://github.com/labstack/echo/blob/master/middleware/rewrite.go
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
if len(input) > 1 {
input = strings.TrimSuffix(input, "/")
}
groups := pattern.FindAllStringSubmatch(input, -1)
if groups == nil {
return nil
}
values := groups[0][1:]
replace := make([]string, 2*len(values))
for i, v := range values {
j := 2 * i
replace[j] = "$" + strconv.Itoa(i+1)
replace[j+1] = v
}
return strings.NewReplacer(replace...)
}

View File

@ -0,0 +1,283 @@
//nolint:bodyclose // Much easier to just ignore memory leaks in tests
package redirect
import (
"context"
"net/http"
"testing"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
)
func Test_Redirect(t *testing.T) {
app := *fiber.New()
app.Use(New(Config{
Rules: map[string]string{
"/default": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))
app.Use(New(Config{
Rules: map[string]string{
"/default/*": "fiber.wiki",
},
StatusCode: fiber.StatusTemporaryRedirect,
}))
app.Use(New(Config{
Rules: map[string]string{
"/redirect/*": "$1",
},
StatusCode: fiber.StatusSeeOther,
}))
app.Use(New(Config{
Rules: map[string]string{
"/pattern/*": "golang.org",
},
StatusCode: fiber.StatusFound,
}))
app.Use(New(Config{
Rules: map[string]string{
"/": "/swagger",
},
StatusCode: fiber.StatusMovedPermanently,
}))
app.Get("/api/*", func(c *fiber.Ctx) error {
return c.SendString("API")
})
app.Get("/new", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
tests := []struct {
name string
url string
redirectTo string
statusCode int
}{
{
name: "should be returns status StatusFound without a wildcard",
url: "/default",
redirectTo: "google.com",
statusCode: fiber.StatusMovedPermanently,
},
{
name: "should be returns status StatusTemporaryRedirect using wildcard",
url: "/default/xyz",
redirectTo: "fiber.wiki",
statusCode: fiber.StatusTemporaryRedirect,
},
{
name: "should be returns status StatusSeeOther without set redirectTo to use the default",
url: "/redirect/github.com/gofiber/redirect",
redirectTo: "github.com/gofiber/redirect",
statusCode: fiber.StatusSeeOther,
},
{
name: "should return the status code default",
url: "/pattern/xyz",
redirectTo: "golang.org",
statusCode: fiber.StatusFound,
},
{
name: "access URL without rule",
url: "/new",
statusCode: fiber.StatusOK,
},
{
name: "redirect to swagger route",
url: "/",
redirectTo: "/swagger",
statusCode: fiber.StatusMovedPermanently,
},
{
name: "no redirect to swagger route",
url: "/api/",
statusCode: fiber.StatusOK,
},
{
name: "no redirect to swagger route #2",
url: "/api/test",
statusCode: fiber.StatusOK,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, tt.url, nil)
utils.AssertEqual(t, err, nil)
req.Header.Set("Location", "github.com/gofiber/redirect")
resp, err := app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, tt.statusCode, resp.StatusCode)
utils.AssertEqual(t, tt.redirectTo, resp.Header.Get("Location"))
})
}
}
func Test_Next(t *testing.T) {
// Case 1 : Next function always returns true
app := *fiber.New()
app.Use(New(Config{
Next: func(*fiber.Ctx) bool {
return true
},
Rules: map[string]string{
"/default": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))
app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/default", nil)
utils.AssertEqual(t, err, nil)
resp, err := app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
// Case 2 : Next function always returns false
app = *fiber.New()
app.Use(New(Config{
Next: func(*fiber.Ctx) bool {
return false
},
Rules: map[string]string{
"/default": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/default", nil)
utils.AssertEqual(t, err, nil)
resp, err = app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusMovedPermanently, resp.StatusCode)
utils.AssertEqual(t, "google.com", resp.Header.Get("Location"))
}
func Test_NoRules(t *testing.T) {
// Case 1: No rules with default route defined
app := *fiber.New()
app.Use(New(Config{
StatusCode: fiber.StatusMovedPermanently,
}))
app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/default", nil)
utils.AssertEqual(t, err, nil)
resp, err := app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
// Case 2: No rules and no default route defined
app = *fiber.New()
app.Use(New(Config{
StatusCode: fiber.StatusMovedPermanently,
}))
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/default", nil)
utils.AssertEqual(t, err, nil)
resp, err = app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode)
}
func Test_DefaultConfig(t *testing.T) {
// Case 1: Default config and no default route
app := *fiber.New()
app.Use(New())
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/default", nil)
utils.AssertEqual(t, err, nil)
resp, err := app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode)
// Case 2: Default config and default route
app = *fiber.New()
app.Use(New())
app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/default", nil)
utils.AssertEqual(t, err, nil)
resp, err = app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
}
func Test_RegexRules(t *testing.T) {
// Case 1: Rules regex is empty
app := *fiber.New()
app.Use(New(Config{
Rules: map[string]string{},
StatusCode: fiber.StatusMovedPermanently,
}))
app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/default", nil)
utils.AssertEqual(t, err, nil)
resp, err := app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
// Case 2: Rules regex map contains valid regex and well-formed replacement URLs
app = *fiber.New()
app.Use(New(Config{
Rules: map[string]string{
"/default": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))
app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/default", nil)
utils.AssertEqual(t, err, nil)
resp, err = app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusMovedPermanently, resp.StatusCode)
utils.AssertEqual(t, "google.com", resp.Header.Get("Location"))
// Case 3: Test invalid regex throws panic
defer func() {
if r := recover(); r != nil {
t.Log("Recovered from invalid regex: ", r)
}
}()
app = *fiber.New()
app.Use(New(Config{
Rules: map[string]string{
"(": "google.com",
},
StatusCode: fiber.StatusMovedPermanently,
}))
t.Error("Expected panic, got nil")
}

View File

@ -0,0 +1,38 @@
package rewrite
import (
"regexp"
"github.com/gofiber/fiber/v2"
)
// Config defines the config for middleware.
type Config struct {
// Next defines a function to skip middleware.
// Optional. Default: nil
Next func(*fiber.Ctx) bool
// Rules defines the URL path rewrite rules. The values captured in asterisk can be
// retrieved by index e.g. $1, $2 and so on.
// Required. Example:
// "/old": "/new",
// "/api/*": "/$1",
// "/js/*": "/public/javascripts/$1",
// "/users/*/orders/*": "/user/$1/order/$2",
Rules map[string]string
rulesRegex map[*regexp.Regexp]string
}
// Helper function to set default values
func configDefault(config ...Config) Config {
// Return default config if nothing provided
if len(config) < 1 {
return Config{}
}
// Override default config
cfg := config[0]
return cfg
}

View File

@ -0,0 +1,54 @@
package rewrite
import (
"regexp"
"strconv"
"strings"
"github.com/gofiber/fiber/v2"
)
// New creates a new middleware handler
func New(config ...Config) fiber.Handler {
cfg := configDefault(config...)
// Initialize
cfg.rulesRegex = map[*regexp.Regexp]string{}
for k, v := range cfg.Rules {
k = strings.ReplaceAll(k, "*", "(.*)")
k += "$"
cfg.rulesRegex[regexp.MustCompile(k)] = v
}
// Middleware function
return func(c *fiber.Ctx) error {
// Next request to skip middleware
if cfg.Next != nil && cfg.Next(c) {
return c.Next()
}
// Rewrite
for k, v := range cfg.rulesRegex {
replacer := captureTokens(k, c.Path())
if replacer != nil {
c.Path(replacer.Replace(v))
break
}
}
return c.Next()
}
}
// https://github.com/labstack/echo/blob/master/middleware/rewrite.go
func captureTokens(pattern *regexp.Regexp, input string) *strings.Replacer {
groups := pattern.FindAllStringSubmatch(input, -1)
if groups == nil {
return nil
}
values := groups[0][1:]
replace := make([]string, 2*len(values))
for i, v := range values {
j := 2 * i
replace[j] = "$" + strconv.Itoa(i+1)
replace[j+1] = v
}
return strings.NewReplacer(replace...)
}

View File

@ -0,0 +1,173 @@
//nolint:bodyclose // Much easier to just ignore memory leaks in tests
package rewrite
import (
"context"
"fmt"
"io"
"net/http"
"testing"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
)
func Test_New(t *testing.T) {
// Test with no config
m := New()
if m == nil {
t.Error("Expected middleware to be returned, got nil")
}
// Test with config
m = New(Config{
Rules: map[string]string{
"/old": "/new",
},
})
if m == nil {
t.Error("Expected middleware to be returned, got nil")
}
// Test with full config
m = New(Config{
Next: func(*fiber.Ctx) bool {
return true
},
Rules: map[string]string{
"/old": "/new",
},
})
if m == nil {
t.Error("Expected middleware to be returned, got nil")
}
}
func Test_Rewrite(t *testing.T) {
// Case 1: Next function always returns true
app := fiber.New()
app.Use(New(Config{
Next: func(*fiber.Ctx) bool {
return true
},
Rules: map[string]string{
"/old": "/new",
},
}))
app.Get("/old", func(c *fiber.Ctx) error {
return c.SendString("Rewrite Successful")
})
req, err := http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/old", nil)
utils.AssertEqual(t, err, nil)
resp, err := app.Test(req)
utils.AssertEqual(t, err, nil)
body, err := io.ReadAll(resp.Body)
utils.AssertEqual(t, err, nil)
bodyString := string(body)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
utils.AssertEqual(t, "Rewrite Successful", bodyString)
// Case 2: Next function always returns false
app = fiber.New()
app.Use(New(Config{
Next: func(*fiber.Ctx) bool {
return false
},
Rules: map[string]string{
"/old": "/new",
},
}))
app.Get("/new", func(c *fiber.Ctx) error {
return c.SendString("Rewrite Successful")
})
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/old", nil)
utils.AssertEqual(t, err, nil)
resp, err = app.Test(req)
utils.AssertEqual(t, err, nil)
body, err = io.ReadAll(resp.Body)
utils.AssertEqual(t, err, nil)
bodyString = string(body)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
utils.AssertEqual(t, "Rewrite Successful", bodyString)
// Case 3: check for captured tokens in rewrite rule
app = fiber.New()
app.Use(New(Config{
Rules: map[string]string{
"/users/*/orders/*": "/user/$1/order/$2",
},
}))
app.Get("/user/:userID/order/:orderID", func(c *fiber.Ctx) error {
return c.SendString(fmt.Sprintf("User ID: %s, Order ID: %s", c.Params("userID"), c.Params("orderID")))
})
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/users/123/orders/456", nil)
utils.AssertEqual(t, err, nil)
resp, err = app.Test(req)
utils.AssertEqual(t, err, nil)
body, err = io.ReadAll(resp.Body)
utils.AssertEqual(t, err, nil)
bodyString = string(body)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
utils.AssertEqual(t, "User ID: 123, Order ID: 456", bodyString)
// Case 4: Send non-matching request, handled by default route
app = fiber.New()
app.Use(New(Config{
Rules: map[string]string{
"/users/*/orders/*": "/user/$1/order/$2",
},
}))
app.Get("/user/:userID/order/:orderID", func(c *fiber.Ctx) error {
return c.SendString(fmt.Sprintf("User ID: %s, Order ID: %s", c.Params("userID"), c.Params("orderID")))
})
app.Use(func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/not-matching-any-rule", nil)
utils.AssertEqual(t, err, nil)
resp, err = app.Test(req)
utils.AssertEqual(t, err, nil)
body, err = io.ReadAll(resp.Body)
utils.AssertEqual(t, err, nil)
bodyString = string(body)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
utils.AssertEqual(t, "OK", bodyString)
// Case 4: Send non-matching request, with no default route
app = fiber.New()
app.Use(New(Config{
Rules: map[string]string{
"/users/*/orders/*": "/user/$1/order/$2",
},
}))
app.Get("/user/:userID/order/:orderID", func(c *fiber.Ctx) error {
return c.SendString(fmt.Sprintf("User ID: %s, Order ID: %s", c.Params("userID"), c.Params("orderID")))
})
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/not-matching-any-rule", nil)
utils.AssertEqual(t, err, nil)
resp, err = app.Test(req)
utils.AssertEqual(t, err, nil)
utils.AssertEqual(t, fiber.StatusNotFound, resp.StatusCode)
}