1. Project Overview & Quickstart (gofiber/xml.go)
xml.go
Open-source repository gofiber/xml.go
Repository Details
- Repository: gofiber/xml.go
- Primary Language: Code
Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.
2. Official Technical Reference & Guides (gofiber/docs)
File: contrib_versioned_docs/version-websocket_v1.x.x/paseto/README.md
id: paseto
Paseto
PASETO returns a Web Token (PASETO) auth middleware.
- For valid token, it sets the payload data in Ctx.Locals and calls next handler.
- For invalid token, it returns "401 - Unauthorized" error.
- For missing token, it returns "400 - BadRequest" error.
Note: Requires Go 1.18 and above
Install
This middleware supports Fiber v2.
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/paseto
go get -u github.com/o1egl/pasetoSignature
pasetoware.New(config ...pasetoware.Config) func(*fiber.Ctx) errorConfig
| Property | Type | Description | Default |
|---|---|---|---|
| Next | func(*Ctx) bool |
Defines a function to skip middleware | nil |
| SuccessHandler | func(*fiber.Ctx) error |
SuccessHandler defines a function which is executed for a valid token. | c.Next() |
| ErrorHandler | func(*fiber.Ctx, error) error |
ErrorHandler defines a function which is executed for an invalid token. | 401 Invalid or expired PASETO |
| Validate | PayloadValidator |
Defines a function to validate if payload is valid. Optional. In case payload used is created using CreateToken function. If token is created using another function, this function must be provided. |
nil |
| SymmetricKey | []byte |
Secret key to encrypt token. If present the middleware will generate local tokens. | nil |
| PrivateKey | ed25519.PrivateKey |
Secret key to sign the tokens. If present (along with its PublicKey) the middleware will generate public tokens. |
nil |
| PublicKey | crypto.PublicKey |
Public key to verify the tokens. If present (along with PrivateKey) the middleware will generate public tokens. |
nil |
| ContextKey | string |
Context key to store user information from the token into context. | "auth-token" |
| TokenLookup | [2]string |
TokenLookup is a string slice with size 2, that is used to extract token from the request | ["header","Authorization"] |
Instructions
When using this middleware, and creating a token for authentication, you can use the function pasetoware.CreateToken,
that will create a token, encrypt or sign it and returns the PASETO token.
Passing a SymmetricKey in the Config results in a local (encrypted) token, while passing a PublicKey
and PrivateKey results in a public (signed) token.
In case you want to use your own data structure, is needed to provide the Validate function in paseware.Config, that
will return the data stored in the token, and a error.
Examples
Below have a list of some examples that can help you start to use this middleware. In case of any additional example
that doesn't show here, please take a look at the test file.
SymmetricKey
package main
import (
"time"
"github.com/gofiber/fiber/v2"
"github.com/o1egl/paseto"
pasetoware "github.com/gofiber/contrib/paseto"
)
const secretSymmetricKey = "symmetric-secret-key (size = 32)"
func main() {
app := fiber.New()
// Login route
app.Post("/login", login)
// Unauthenticated route
app.Get("/", accessible)
// Paseto Middleware with local (encrypted) token
apiGroup := app.Group("api", pasetoware.New(pasetoware.Config{
SymmetricKey: []byte(secretSymmetricKey),
TokenPrefix: "Bearer",
}))
// Restricted Routes
apiGroup.Get("/restricted", restricted)
err := app.Listen(":8088")
if err != nil {
return
}
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// Throws Unauthorized error
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// Create token and encrypt it
encryptedToken, err := pasetoware.CreateToken([]byte(secretSymmetricKey), user, 12*time.Hour, pasetoware.PurposeLocal)
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": encryptedToken})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("Accessible")
}
func restricted(c *fiber.Ctx) error {
payload := c.Locals(pasetoware.DefaultContextKey).(string)
return c.SendString("Welcome " + payload)
}Test it
Login using username and password to retrieve a token.
curl --data "user=john&pass=doe" http://localhost:8088/loginResponse
{
"token": "v2.local.eY7o9YAJ7Uqyo0JdyfHXKVARj3HgBhqIHckPgNIJOU6u489CXYL6bpOXbEtTB_nNM7nTFpcRVi7YAtJToxbxkkraHmE39pqjnBgkca-URgE-jhZGuhGu7ablmK-8tVoe5iY8mQqWFuJHAznTASUHh4AG55AMUcIALi6pEG28lAgVfw2azvnvbg4JOVZnjutcOVswd-ErsAuGtuEZkTmX7BfaLaO9ZvEX9cHahYPajuRjwU2TQrcpqITg-eYMNA1NuO8OVdnGf0mkUk6ElJUTZqhx4CSSylNXr7IlOwzTbUotEDAQTcNP7IRZI3VfpnRgnmtnZ5s.bnVsbAY"
}Request a restricted resource using the token in Authorization request header.
curl localhost:8088/api/restricted -H "Authorization: Bearer v2.local.eY7o9YAJ7Uqyo0JdyfHXKVARj3HgBhqIHckPgNIJOU6u489CXYL6bpOXbEtTB_nNM7nTFpcRVi7YAtJToxbxkkraHmE39pqjnBgkca-URgE-jhZGuhGu7ablmK-8tVoe5iY8mQqWFuJHAznTASUHh4AG55AMUcIALi6pEG28lAgVfw2azvnvbg4JOVZnjutcOVswd-ErsAuGtuEZkTmX7BfaLaO9ZvEX9cHahYPajuRjwU2TQrcpqITg-eYMNA1NuO8OVdnGf0mkUk6ElJUTZqhx4CSSylNXr7IlOwzTbUotEDAQTcNP7IRZI3VfpnRgnmtnZ5s.bnVsbA"Response
Welcome johnSymmetricKey + Custom Validator callback
package main
import (
"encoding/json"
"time"
"github.com/o1egl/paseto"
pasetoware "github.com/gofiber/contrib/paseto"
)
const secretSymmetricKey = "symmetric-secret-key (size = 32)"
type customPayloadStruct struct {
Name string `json:"name"`
ExpiresAt time.Time `json:"expiresAt"`
}
func main() {
app := fiber.New()
// Login route
app.Post("/login", login)
// Unauthenticated route
app.Get("/", accessible)
// Paseto Middleware with local (encrypted) token
apiGroup := app.Group("api", pasetoware.New(pasetoware.Config{
SymmetricKey: []byte(secretSymmetricKey),
TokenPrefix: "Bearer",
Validate: func(decrypted []byte) (any, error) {
var payload customPayloadStruct
err := json.Unmarshal(decrypted, &payload)
return payload, err
},
}))
// Restricted Routes
apiGroup.Get("/restricted", restricted)
err := app.Listen(":8088")
if err != nil {
return
}
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// Throws Unauthorized error
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// Create the payload
payload := customPayloadStruct{
Name: "John Doe",
ExpiresAt: time.Now().Add(12 * time.Hour),
}
// Create token and encrypt it
encryptedToken, err := paseto.NewV2().Encrypt([]byte(secretSymmetricKey), payload, nil)
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": encryptedToken})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("Accessible")
}
func restricted(c *fiber.Ctx) error {
payload := c.Locals(pasetoware.DefaultContextKey).(customPayloadStruct)
return c.SendString("Welcome " + payload.Name)
}Test it
Login using username and password to retrieve a token.
curl --data "user=john&pass=doe" http://localhost:8088/loginResponse
{
"token": "v2.local.OSnDEMUndq8JpRdCD8yX-mr-Z0-Mi85Jw0ftxseiNLCbRc44Mxl5dnn-SV9Qew1n9Y44wXZwm_FG279cILJk7lYc_B_IoMCRBudJE7qMgctkD9UBM-ZRZgCX9ekJh3S1Oo6Erp7bO-omPra5.bnVsbA"
}Request a restricted resource using the token in Authorization request header.
curl localhost:8088/api/restricted -H "Authorization: Bearer v2.local.OSnDEMUndq8JpRdCD8yX-mr-Z0-Mi85Jw0ftxseiNLCbRc44Mxl5dnn-SV9Qew1n9Y44wXZwm_FG279cILJk7lYc_B_IoMCRBudJE7qMgctkD9UBM-ZRZgCX9ekJh3S1Oo6Erp7bO-omPra5.bnVsbA"Response
Welcome John DoePublicPrivate Key
package main
import (
"crypto/ed25519"
"encoding/hex"
"time"
"github.com/gofiber/fiber/v2"
pasetoware "github.com/gofiber/contrib/paseto"
)
const privateKeySeed = "e9c67fe2433aa4110caf029eba70df2c822cad226b6300ead3dcae443ac3810f"
var seed, _ = hex.DecodeString(privateKeySeed)
var privateKey = ed25519.NewKeyFromSeed(seed)
type customPayloadStruct struct {
Name string `json:"name"`
ExpiresAt time.Time `json:"expiresAt"`
}
func main() {
app := fiber.New()
// Login route
app.Post("/login", login)
// Unauthenticated route
app.Get("/", accessible)
// Paseto Middleware with local (encrypted) token
apiGroup := app.Group("api", pasetoware.New(pasetoware.Config{
TokenPrefix: "Bearer",
PrivateKey: privateKey,
PublicKey: privateKey.Public(),
}))
// Restricted Routes
apiGroup.Get("/restricted", restricted)
err := app.Listen(":8088")
if err != nil {
return
}
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// Throws Unauthorized error
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// Create token and encrypt it
encryptedToken, err := pasetoware.CreateToken(privateKey, user, 12*time.Hour, pasetoware.PurposePublic)
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": encryptedToken})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("Accessible")
}
func restricted(c *fiber.Ctx) error {
payload := c.Locals(pasetoware.DefaultContextKey).(string)
return c.SendString("Welcome " + payload)
}Test it
Login using username and password to retrieve a token.
curl --data "user=john&pass=doe" http://localhost:8088/loginResponse
{
"token": "v2.public.eyJhdWQiOiJnb2ZpYmVyLmdvcGhlcnMiLCJkYXRhIjoiam9obiIsImV4cCI6IjIwMjMtMDctMTNUMDg6NDk6MzctMDM6MDAiLCJpYXQiOiIyMDIzLTA3LTEyVDIwOjQ5OjM3LTAzOjAwIiwianRpIjoiMjIzYjM0MjQtNWNkZS00NDFhLWJiZWEtZjBjYWFhYTdiYWFlIiwibmJmIjoiMjAyMy0wNy0xMlQyMDo0OTozNy0wMzowMCIsInN1YiI6InVzZXItdG9rZW4ifWiqK_yg0eJbIs2hnup4NuBYg7v4lxh33zEhEljsH7QUaZXAdtbCPK7cN-NSfSxrw68owwgo-dOlPrD7lc5M_AU.bnVsbA"
}Request a restricted resource using the token in Authorization request header.
curl localhost:8088/api/restricted -H "Authorization: Bearer v2.public.eyJhdWQiOiJnb2ZpYmVyLmdvcGhlcnMiLCJkYXRhIjoiam9obiIsImV4cCI6IjIwMjMtMDctMTNUMDg6NDk6MzctMDM6MDAiLCJpYXQiOiIyMDIzLTA3LTEyVDIwOjQ5OjM3LTAzOjAwIiwianRpIjoiMjIzYjM0MjQtNWNkZS00NDFhLWJiZWEtZjBjYWFhYTdiYWFlIiwibmJmIjoiMjAyMy0wNy0xMlQyMDo0OTozNy0wMzowMCIsInN1YiI6InVzZXItdG9rZW4ifWiqK_yg0eJbIs2hnup4NuBYg7v4lxh33zEhEljsH7QUaZXAdtbCPK7cN-NSfSxrw68owwgo-dOlPrD7lc5M_AU.bnVsbA"Response
Welcome John DoeFile: contrib_versioned_docs/version-websocket_v1.x.x/otelfiber/example/README.md
id: otelfiber-example
Example
An HTTP server using gofiber fiber and instrumentation. The server has a/users/:id endpoint. The server generates span information tostdout.
These instructions expect you have
docker-compose installed.
Bring up the fiber-server and fiber-client services to run the
example:
docker-compose up --detach fiber-server fiber-clientThe fiber-client service sends just one HTTP request to fiber-server
and then exits. View the span generated by fiber-server in the logs:
docker-compose logs fiber-serverShut down the services when you are finished with the example:
docker-compose downFile: contrib_versioned_docs/version-websocket_v1.x.x/otelfiber/README.md
id: otelfiber
Otelfiber
OpenTelemetry support for Fiber.
Can be found on OpenTelemetry Registry.
Note: Requires Go 1.19 and above
Install
This middleware supports Fiber v2.
go get -u github.com/gofiber/contrib/otelfiber/v2Signature
otelfiber.Middleware(opts ...otelfiber.Option) fiber.HandlerConfig
You can configure the middleware using functional parameters
| Function | Argument Type | Description | Default |
|---|---|---|---|
WithNext |
func(*fiber.Ctx) bool |
Define a function to skip this middleware when returned true . | nil |
WithTracerProvider |
oteltrace.TracerProvider |
Specifies a tracer provider to use for creating a tracer. | nil - the global tracer provider is used |
WithMeterProvider |
otelmetric.MeterProvider |
Specifies a meter provider to use for reporting. | nil - the global meter provider is used |
WithPort |
int |
Specifies the value to use when setting the net.host.port attribute on metrics/spans. |
Defaults to (80 for http, 443 for https) |
WithPropagators |
propagation.TextMapPropagator |
Specifies propagators to use for extracting information from the HTTP requests. | If none are specified, global ones will be used |
WithServerName |
string |
Specifies the value to use when setting the http.server_name attribute on metrics/spans. |
- |
WithSpanNameFormatter |
func(*fiber.Ctx) string |
Takes a function that will be called on every request and the returned string will become the span Name. | Default formatter returns the route pathRaw |
WithCustomAttributes |
func(*fiber.Ctx) []attribute.KeyValue |
Define a function to add custom attributes to the span. | nil |
WithCustomMetricAttributes |
func(*fiber.Ctx) []attribute.KeyValue |
Define a function to add custom attributes to the metrics. | nil |
WithCollectClientIP |
bool |
Specifies whether to collect the client's IP address from the request. | true |
Usage
Please refer to example
Example
package main
import (
"context"
"errors"
"log"
"go.opentelemetry.io/otel/sdk/resource"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/otelfiber"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
//"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
oteltrace "go.opentelemetry.io/otel/trace"
)
var tracer = otel.Tracer("fiber-server")
func main() {
tp := initTracer()
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Printf("Error shutting down tracer provider: %v", err)
}
}()
app := fiber.New()
app.Use(otelfiber.Middleware())
app.Get("/error", func(ctx *fiber.Ctx) error {
return errors.New("abc")
})
app.Get("/users/:id", func(c *fiber.Ctx) error {
id := c.Params("id")
name := getUser(c.UserContext(), id)
return c.JSON(fiber.Map{"id": id, name: name})
})
log.Fatal(app.Listen(":3000"))
}
func initTracer() *sdktrace.TracerProvider {
exporter, err := stdout.New(stdout.WithPrettyPrint())
if err != nil {
log.Fatal(err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String("my-service"),
)),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
return tp
}
func getUser(ctx context.Context, id string) string {
_, span := tracer.Start(ctx, "getUser", oteltrace.WithAttributes(attribute.String("id", id)))
defer span.End()
if id == "123" {
return "otelfiber tester"
}
return "unknown"
}File: contrib_versioned_docs/version-websocket_v1.x.x/opafiber/README.md
id: opafiber
Opafiber
Open Policy Agent support for Fiber.
Note: Requires Go 1.19 and above
Install
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/opafiber/v2Signature
opafiber.New(config opafiber.Config) fiber.HandlerConfig
| Property | Type | Description | Default |
|---|---|---|---|
| RegoQuery | string |
Required - Rego query | - |
| RegoPolicy | io.Reader |
Required - Rego policy | - |
| IncludeQueryString | bool |
Include query string as input to rego policy | false |
| DeniedStatusCode | int |
Http status code to return when policy denies request | 400 |
| DeniedResponseMessage | string |
Http response body text to return when policy denies request | "" |
| IncludeHeaders | []string |
Include headers as input to rego policy | - |
| InputCreationMethod | InputCreationFunc |
Use your own function to provide input for OPA | func defaultInput(ctx *fiber.Ctx) (map[string]interface{}, error) |
Types
type InputCreationFunc func(c *fiber.Ctx) (map[string]interface{}, error)Usage
OPA Fiber middleware sends the following example data to the policy engine as input:
{
"method": "GET",
"path": "/somePath",
"query": {
"name": ["John Doe"]
},
"headers": {
"Accept": "application/json",
"Content-Type": "application/json"
}
}package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/opafiber/v2"
)
func main() {
app := fiber.New()
module := `
package example.authz
default allow := false
allow {
input.method == "GET"
}
`
cfg := opafiber.Config{
RegoQuery: "data.example.authz.allow",
RegoPolicy: bytes.NewBufferString(module),
IncludeQueryString: true,
DeniedStatusCode: fiber.StatusForbidden,
DeniedResponseMessage: "status forbidden",
IncludeHeaders: []string{"Authorization"},
InputCreationMethod: func (ctx *fiber.Ctx) (map[string]interface{}, error) {
return map[string]interface{}{
"method": ctx.Method(),
"path": ctx.Path(),
}, nil
},
}
app.Use(opafiber.New(cfg))
app.Get("/", func(ctx *fiber.Ctx) error {
return ctx.SendStatus(200)
})
app.Listen(":8080")
}File: contrib_versioned_docs/version-websocket_v1.x.x/monitor/README.md
id: monitor
Monitor
Monitor middleware for Fiber that reports server metrics, inspired by express-status-monitor
Install
This middleware supports Fiber v3.
go get -u github.com/gofiber/fiber/v3
go get -u github.com/gofiber/contrib/monitorSignature
monitor.New(config ...monitor.Config) fiber.HandlerConfig
| Property | Type | Description | Default |
|---|---|---|---|
| Title | string |
Metrics page title. | Fiber Monitor |
| Refresh | time.Duration |
Refresh period. | 3 seconds |
| APIOnly | bool |
Whether the service should expose only the montioring API. | false |
| Next | func(c *fiber.Ctx) bool |
Define a function to add custom fields. | nil |
| CustomHead | string |
Custom HTML code to Head Section(Before End). | empty |
| FontURL | string |
FontURL for specilt font resource path or URL. also you can use relative path. | https://fonts.googleapis.com/css2?family=Roboto:wght@400;900&display=swap |
| ChartJsURL | string |
ChartJsURL for specilt chartjs library, path or URL, also you can use relative path. | https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.bundle.min.js |
Example
package main
import (
"log"
"github.com/gofiber/fiber/v3"
"github.com/gofiber/contrib/monitor"
)
func main() {
app := fiber.New()
// Initialize default config (Assign the middleware to /metrics)
app.Get("/metrics", monitor.New())
// Or extend your config for customization
// Assign the middleware to /metrics
// and change the Title to `MyService Metrics Page`
app.Get("/metrics", monitor.New(monitor.Config{Title: "MyService Metrics Page"}))
log.Fatal(app.Listen(":3000"))
}Default Config
var ConfigDefault = Config{
Title: defaultTitle,
Refresh: defaultRefresh,
FontURL: defaultFontURL,
ChartJsURL: defaultChartJSURL,
CustomHead: defaultCustomHead,
APIOnly: false,
Next: nil,
}File: contrib_versioned_docs/version-websocket_v1.x.x/loadshed/README.md
id: loadshed
LoadShed
The LoadShed middleware for Fiber is designed to help manage server load by shedding requests based on certain load criteria.
Note: Requires Go 1.19 and above
Install
This middleware supports Fiber v2
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/loadshedSignatures
loadshed.New(config ...loadshed.Config) fiber.HandlerExamples
To use the LoadShed middleware in your Fiber application, import it and apply it to your Fiber app. Here's an example:
package main
import (
"github.com/gofiber/fiber/v2"
loadshed "github.com/gofiber/contrib/loadshed"
)
func main() {
app := fiber.New()
// Configure and use LoadShed middleware
app.Use(loadshed.New(loadshed.Config{
Criteria: &loadshed.CPULoadCriteria{
LowerThreshold: 0.75, // Set your own lower threshold
UpperThreshold: 0.90, // Set your own upper threshold
Interval: 10 * time.Second,
Getter: &loadshed.DefaultCPUPercentGetter{},
},
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome!")
})
app.Listen(":3000")
}Config
The LoadShed middleware in Fiber offers various configuration options to tailor the load shedding behavior according to the needs of your application.
| Property | Type | Description | Default |
|---|---|---|---|
| Next | func(*fiber.Ctx) bool |
Function to skip this middleware when returned true. | nil |
| Criteria | LoadCriteria |
Interface for defining load shedding criteria. | &CPULoadCriteria{...} |
LoadCriteria
LoadCriteria is an interface in the LoadShed middleware that defines the criteria for determining when to shed load in the system. Different implementations of this interface can use various metrics and algorithms to decide when and how to shed incoming requests to maintain system performance.
CPULoadCriteria
CPULoadCriteria is an implementation of the LoadCriteria interface, using CPU load as the metric for determining whether to shed requests.
Properties
| Property | Type | Description |
|---|---|---|
| LowerThreshold | float64 |
The lower CPU usage threshold as a fraction (0.0 to 1.0). Requests are considered for shedding when CPU usage exceeds this threshold. |
| UpperThreshold | float64 |
The upper CPU usage threshold as a fraction (0.0 to 1.0). All requests are shed when CPU usage exceeds this threshold. |
| Interval | time.Duration |
The time interval over which the CPU usage is averaged for decision making. |
| Getter | CPUPercentGetter |
Interface to retrieve CPU usage percentages. |
How It Works
CPULoadCriteria determines the load on the system based on CPU usage and decides whether to shed incoming requests. It operates on the following principles:
- CPU Usage Measurement: It measures the CPU usage over a specified interval.
- Thresholds: Utilizes
LowerThresholdandUpperThresholdvalues to decide when to start shedding requests. - Proportional Rejection Probability:
- Below
LowerThreshold: No requests are rejected, as the system is considered under acceptable load. - Between
LowerThresholdandUpperThreshold: The probability of rejecting a request increases as the CPU usage approaches theUpperThreshold. This is calculated using the formula:plaintextrejectionProbability := (cpuUsage - LowerThreshold*100) / (UpperThreshold - LowerThreshold) - Above
UpperThreshold: All requests are rejected to prevent system overload.
- Below
This mechanism ensures that the system can adaptively manage its load, maintaining stability and performance under varying traffic conditions.
Default Config
This is the default configuration for LoadCriteria in the LoadShed middleware.
var ConfigDefault = Config{
Next: nil,
Criteria: &CPULoadCriteria{
LowerThreshold: 0.90, // 90% CPU usage as the start point for considering shedding
UpperThreshold: 0.95, // 95% CPU usage as the point where all requests are shed
Interval: 10 * time.Second, // CPU usage is averaged over 10 seconds
Getter: &DefaultCPUPercentGetter{}, // Default method for getting CPU usage
},
}File: contrib_versioned_docs/version-websocket_v1.x.x/jwt/README.md
id: jwt
JWT
JWT returns a JSON Web Token (JWT) auth middleware.
For valid token, it sets the user in Ctx.Locals and calls next handler.
For invalid token, it returns "401 - Unauthorized" error.
For missing token, it returns "400 - Bad Request" error.
Special thanks and credits to Echo
Note: Requires Go 1.19 and above
Install
This middleware supports Fiber v1 & v2, install accordingly.
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/jwt
go get -u github.com/golang-jwt/jwt/v5Signature
jwtware.New(config ...jwtware.Config) func(*fiber.Ctx) errorConfig
| Property | Type | Description | Default |
|---|---|---|---|
| Filter | func(*fiber.Ctx) bool |
Function to skip middleware execution for specific requests. Optional. | nil |
| SuccessHandler | fiber.Handler |
Handler executed when a token is successfully validated. Optional. | nil |
| ErrorHandler | fiber.ErrorHandler |
Handler executed when token validation fails. Allows customization of JWT error responses. Optional. | 401 Invalid or expired JWT |
| SigningKey | SigningKey |
Primary key used to validate tokens. Used as a fallback if SigningKeys is empty. At least one of KeyFunc, JWKSetURLs, SigningKeys, or SigningKey is required. | nil |
| SigningKeys | map[string]SigningKey |
Map of keys used to validate tokens with the "kid" field. At least one of KeyFunc, JWKSetURLs, SigningKeys, or SigningKey is required. | nil |
| ContextKey | string |
Key used to store user information in the context. Optional. | "user" |
| Claims | jwt.Claims |
Defines the structure of token claims. Extendable for custom claims data. Optional. | jwt.MapClaims{} |
| TokenLookup | string |
Specifies how to extract the token from the request. Format: ":<name>" (e.g., "header:Authorization", "query:token", "param:token", "cookie:token"). Optional. |
"header:Authorization" |
| TokenProcessorFunc | func(token string) (string, error) |
Processes the token extracted using TokenLookup. Optional. |
nil |
| AuthScheme | string |
Scheme used in the Authorization header. Only used with the default TokenLookup. Optional. | "Bearer" |
| KeyFunc | func() jwt.Keyfunc |
Provides the public key for JWT verification, handling algorithm verification and key selection. At least one of KeyFunc, JWKSetURLs, SigningKeys, or SigningKey is required. | jwtKeyFunc |
| JWKSetURLs | []string |
List of URLs containing JSON Web Key Sets (JWKS) for signature verification. HTTPS is recommended. The "kid" field is mandatory in both the JWT header and the JWKS. Default behavior includes hourly refresh, auto-refresh on new "kid", rate limiting, and timeouts. | nil |
HS256 Example
package main
import (
"time"
"github.com/gofiber/fiber/v2"
jwtware "github.com/gofiber/contrib/jwt"
"github.com/golang-jwt/jwt/v5"
)
func main() {
app := fiber.New()
// Login route
app.Post("/login", login)
// Unauthenticated route
app.Get("/", accessible)
// JWT Middleware
app.Use(jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{Key: []byte("secret")},
}))
// Restricted Routes
app.Get("/restricted", restricted)
app.Listen(":3000")
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// Throws Unauthorized error
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// Create the Claims
claims := jwt.MapClaims{
"name": "John Doe",
"admin": true,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
// Create token
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// Generate encoded token and send it as response.
t, err := token.SignedString([]byte("secret"))
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": t})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("Accessible")
}
func restricted(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
name := claims["name"].(string)
return c.SendString("Welcome " + name)
}HS256 Test
Login using username and password to retrieve a token.
curl --data "user=john&pass=doe" http://localhost:3000/loginResponse
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"
}Request a restricted resource using the token in Authorization request header.
curl localhost:3000/restricted -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"Response
Welcome John DoeRS256 Example
package main
import (
"crypto/rand"
"crypto/rsa"
"log"
"time"
"github.com/gofiber/fiber/v2"
"github.com/golang-jwt/jwt/v5"
jwtware "github.com/gofiber/contrib/jwt"
)
var (
// Obviously, this is just a test example. Do not do this in production.
// In production, you would have the private key and public key pair generated
// in advance. NEVER add a private key to any GitHub repo.
privateKey *rsa.PrivateKey
)
func main() {
app := fiber.New()
// Just as a demo, generate a new private/public key pair on each run. See note above.
rng := rand.Reader
var err error
privateKey, err = rsa.GenerateKey(rng, 2048)
if err != nil {
log.Fatalf("rsa.GenerateKey: %v", err)
}
// Login route
app.Post("/login", login)
// Unauthenticated route
app.Get("/", accessible)
// JWT Middleware
app.Use(jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{
JWTAlg: jwtware.RS256,
Key: privateKey.Public(),
},
}))
// Restricted Routes
app.Get("/restricted", restricted)
app.Listen(":3000")
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// Throws Unauthorized error
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// Create the Claims
claims := jwt.MapClaims{
"name": "John Doe",
"admin": true,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
// Create token
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
// Generate encoded token and send it as response.
t, err := token.SignedString(privateKey)
if err != nil {
log.Printf("token.SignedString: %v", err)
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": t})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("Accessible")
}
func restricted(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
name := claims["name"].(string)
return c.SendString("Welcome " + name)
}RS256 Test
The RS256 is actually identical to the HS256 test above.
JWK Set Test
The tests are identical to basic JWT tests above, with exception that JWKSetURLs to valid public keys collection in JSON Web Key (JWK) Set format should be supplied. See RFC 7517.
Custom KeyFunc example
KeyFunc defines a user-defined function that supplies the public key for a token validation.
The function shall take care of verifying the signing algorithm and selecting the proper key.
A user-defined KeyFunc can be useful if tokens are issued by an external party.
When a user-defined KeyFunc is provided, SigningKey, SigningKeys, and SigningMethod are ignored.
This is one of the three options to provide a token validation key.
The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
Required if neither SigningKeys nor SigningKey is provided.
Default to an internal implementation verifying the signing algorithm and selecting the proper key.
package main
import (
"fmt"
"github.com/gofiber/fiber/v2"
jwtware "github.com/gofiber/contrib/jwt"
"github.com/golang-jwt/jwt/v5"
)
func main() {
app := fiber.New()
app.Use(jwtware.New(jwtware.Config{
KeyFunc: customKeyFunc(),
}))
app.Get("/ok", func(c *fiber.Ctx) error {
return c.SendString("OK")
})
}
func customKeyFunc() jwt.Keyfunc {
return func(t *jwt.Token) (interface{}, error) {
// Always check the signing method
if t.Method.Alg() != jwtware.HS256 {
return nil, fmt.Errorf("Unexpected jwt signing method=%v", t.Header["alg"])
}
// TODO custom implementation of loading signing key like from a database
signingKey := "secret"
return []byte(signingKey), nil
}
}File: contrib_versioned_docs/version-websocket_v1.x.x/hcaptcha/README.md
id: hcaptcha
HCaptcha
A simple HCaptcha middleware to prevent bot attacks.
:::note
Requires Go 1.21 and above
:::
Install
:::caution
This middleware only supports Fiber v3.
:::
go get -u github.com/gofiber/fiber/v3
go get -u github.com/gofiber/contrib/hcaptchaSignature
hcaptcha.New(config hcaptcha.Config) fiber.HandlerConfig
| Property | Type | Description | Default |
|---|---|---|---|
| SecretKey | string |
The secret key you obtained from the HCaptcha admin panel. This field must not be empty. | "" |
| ResponseKeyFunc | func(fiber.Ctx) (string, error) |
ResponseKeyFunc should return the token that captcha provides upon successful solving. By default, it gets the token from the body by parsing a JSON request and returns the hcaptcha_token field. |
hcaptcha.DefaultResponseKeyFunc |
| SiteVerifyURL | string |
This property specifies the API resource used for token authentication. | https://api.hcaptcha.com/siteverify |
Example
package main
import (
"github.com/gofiber/contrib/hcaptcha"
"github.com/gofiber/fiber/v3"
"log"
)
const (
TestSecretKey = "0x0000000000000000000000000000000000000000"
TestSiteKey = "20000000-ffff-ffff-ffff-000000000002"
)
func main() {
app := fiber.New()
captcha := hcaptcha.New(hcaptcha.Config{
// Must set the secret key
SecretKey: TestSecretKey,
})
app.Get("/api/", func(c fiber.Ctx) error {
return c.JSON(fiber.Map{
"hcaptcha_site_key": TestSiteKey,
})
})
app.Post("/api/robots-excluded", func(c fiber.Ctx) error {
return c.SendString("You are not a robot")
}, captcha)
log.Fatal(app.Listen(":3000"))
}File: contrib_versioned_docs/version-websocket_v1.x.x/fiberzerolog/README.md
id: fiberzerolog
Fiberzerolog
Zerolog logging support for Fiber.
Note: Requires Go 1.18 and above
Install
This middleware supports Fiber v2.
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/fiberzerolog
go get -u github.com/rs/zerolog/logSignature
fiberzerolog.New(config ...fiberzerolog.Config) fiber.HandlerConfig
| Property | Type | Description | Default |
|---|---|---|---|
| Next | func(*Ctx) bool |
Define a function to skip this middleware when returned true | nil |
| Logger | *zerolog.Logger |
Add custom zerolog logger. | zerolog.New(os.Stderr).With().Timestamp().Logger() |
| GetLogger | func(*fiber.Ctx) zerolog.Logger |
Get custom zerolog logger, if it's defined the returned logger will replace the Logger value. |
nil |
| Fields | []string |
Add fields what you want see. | []string{"latency", "status", "method", "url", "error"} |
| WrapHeaders | bool | Wrap headers to dictionary.If false: {"method":"POST", "header-key":"header value"}If true: {"method":"POST", "reqHeaders": {"header-key":"header value"}} |
false |
| FieldsSnakeCase | bool | Use snake case for fields: FieldResBody, FieldQueryParams, FieldBytesReceived, FieldBytesSent, FieldRequestId, FieldReqHeaders, FieldResHeaders.If false: {"method":"POST", "resBody":"v", "queryParams":"v"}If true: {"method":"POST", "res_body":"v", "query_params":"v"} |
false |
| Messages | []string |
Custom response messages. | []string{"Server error", "Client error", "Success"} |
| Levels | []zerolog.Level |
Custom response levels. | []zerolog.Level{zerolog.ErrorLevel, zerolog.WarnLevel, zerolog.InfoLevel} |
| SkipURIs | []string |
Skip logging these URI. | []string{} |
| GetResBody | func(c *fiber.Ctx) []byte | Define a function to get response body when return non-nil.eg: When use compress middleware, resBody is unreadable. you can set GetResBody func to get readable resBody. | nil |
Example
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/fiberzerolog"
"github.com/rs/zerolog"
)
func main() {
app := fiber.New()
logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
app.Use(fiberzerolog.New(fiberzerolog.Config{
Logger: &logger,
}))
app.Get("/", func (c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
if err := app.Listen(":3000"); err != nil {
logger.Fatal().Err(err).Msg("Fiber app error")
}
}File: contrib_versioned_docs/version-websocket_v1.x.x/fiberzap/README.md
id: fiberzap
Fiberzap
Zap logging support for Fiber.
Note: Requires Go 1.19 and above
Install
This middleware supports Fiber v2.
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/fiberzap/v2
go get -u go.uber.org/zapSignature
fiberzap.New(config ...fiberzap.Config) fiber.HandlerConfig
| Property | Type | Description | Default |
|---|---|---|---|
| Next | func(*Ctx) bool |
Define a function to skip this middleware when returned true | nil |
| Logger | *zap.Logger |
Add custom zap logger. | zap.NewDevelopment() |
| Fields | []string |
Add fields what you want see. | []string{"latency", "status", "method", "url"} |
| FieldsFunc | []zap.Field |
Define a function to add custom fields. | nil |
| Messages | []string |
Custom response messages. | []string{"Server error", "Client error", "Success"} |
| Levels | []zapcore.Level |
Custom response levels. | []zapcore.Level{zapcore.ErrorLevel, zapcore.WarnLevel, zapcore.InfoLevel} |
| SkipURIs | []string |
Skip logging these URI. | []string{} |
| GetResBody | func(c *fiber.Ctx) []byte | Define a function to get response body when return non-nil.eg: When use compress middleware, resBody is unreadable. you can set GetResBody func to get readable resBody. | nil |
Example
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/fiberzap/v2"
"go.uber.org/zap"
)
func main() {
app := fiber.New()
logger, _ := zap.NewProduction()
defer logger.Sync()
app.Use(fiberzap.New(fiberzap.Config{
Logger: logger,
}))
app.Get("/", func (c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
log.Fatal(app.Listen(":3000"))
}NewLogger
Signature
fiberzap.NewLogger(config ...fiberzap.LoggerConfig) *fiberzap.LoggerConfigLoggerConfig
| Property | Type | Description | Default |
|---|---|---|---|
| CoreConfigs | []CoreConfig |
Define Config for zapcore | fiberzap.LoggerConfigDefault |
| SetLogger | *zap.Logger |
Add custom zap logger. if not nil, ZapOptions, CoreConfigs, SetLevel, SetOutput will be ignored. |
nil |
| ExtraKeys | []string |
Allow users log extra values from context. | []string{} |
| ZapOptions | []zap.Option |
Allow users to configure the zap.Option supplied by zap. | []zap.Option{} |
Example
package main
import (
"context"
"github.com/gofiber/contrib/fiberzap/v2"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/log"
)
func main() {
app := fiber.New()
logger := fiberzap.NewLogger(fiberzap.LoggerConfig{
ExtraKeys: []string{"request_id"},
})
log.SetLogger(logger)
defer logger.Sync()
app.Use(func(c *fiber.Ctx) error {
ctx := context.WithValue(c.UserContext(), "request_id", "123")
c.SetUserContext(ctx)
return c.Next()
})
app.Get("/", func(c *fiber.Ctx) error {
log.WithContext(c.UserContext()).Info("Hello, World!")
return c.SendString("Hello, World!")
})
log.Fatal(app.Listen(":3000"))
}File: contrib_versioned_docs/version-websocket_v1.x.x/fibersentry/README.md
id: fibersentry
Fibersentry
Sentry support for Fiber.
Note: Requires Go 1.18 and above
Install
This middleware supports Fiber v2.
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/fibersentry
go get -u github.com/getsentry/sentry-goSignature
fibersentry.New(config ...fibersentry.Config) fiber.HandlerConfig
| Property | Type | Description | Default |
|---|---|---|---|
| Repanic | bool |
Repanic configures whether Sentry should repanic after recovery. Set to true, if Recover middleware is used. | false |
| WaitForDelivery | bool |
WaitForDelivery configures whether you want to block the request before moving forward with the response. If Recover middleware is used, it's safe to either skip this option or set it to false. | false |
| Timeout | time.Duration |
Timeout for the event delivery requests. | time.Second * 2 |
Usage
fibersentry attaches an instance of *sentry.Hub (https://godoc.org/github.com/getsentry/sentry-go#Hub) to the request's context, which makes it available throughout the rest of the request's lifetime.
You can access it by using the fibersentry.GetHubFromContext() or fibersentry.MustGetHubFromContext() method on the context itself in any of your proceeding middleware and routes.
Keep in mind that *sentry.Hub should be used instead of the global sentry.CaptureMessage, sentry.CaptureException, or any other calls, as it keeps the separation of data between the requests.
- Keep in mind that
*sentry.Hubwon't be available in middleware attached beforefibersentry. In this case,GetHubFromContext()returns nil, andMustGetHubFromContext()will panic.
package main
import (
"fmt"
"log"
"github.com/getsentry/sentry-go"
"github.com/gofiber/contrib/fibersentry"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
)
func main() {
_ = sentry.Init(sentry.ClientOptions{
Dsn: "",
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
if hint.Context != nil {
if c, ok := hint.Context.Value(sentry.RequestContextKey).(*fiber.Ctx); ok {
// You have access to the original Context if it panicked
fmt.Println(utils.ImmutableString(c.Hostname()))
}
}
fmt.Println(event)
return event
},
Debug: true,
AttachStacktrace: true,
})
app := fiber.New()
app.Use(fibersentry.New(fibersentry.Config{
Repanic: true,
WaitForDelivery: true,
}))
enhanceSentryEvent := func(c *fiber.Ctx) error {
if hub := fibersentry.GetHubFromContext(c); hub != nil {
hub.Scope().SetTag("someRandomTag", "maybeYouNeedIt")
}
return c.Next()
}
app.All("/foo", enhanceSentryEvent, func(c *fiber.Ctx) error {
panic("y tho")
})
app.All("/", func(c *fiber.Ctx) error {
if hub := fibersentry.GetHubFromContext(c); hub != nil {
hub.WithScope(func(scope *sentry.Scope) {
scope.SetExtra("unwantedQuery", "someQueryDataMaybe")
hub.CaptureMessage("User provided unwanted query string, but we recovered just fine")
})
}
return c.SendStatus(fiber.StatusOK)
})
log.Fatal(app.Listen(":3000"))
}Accessing Context in `BeforeSend` callback
sentry.Init(sentry.ClientOptions{
Dsn: "your-public-dsn",
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
if hint.Context != nil {
if c, ok := hint.Context.Value(sentry.RequestContextKey).(*fiber.Ctx); ok {
// You have access to the original Context if it panicked
fmt.Println(c.Hostname())
}
}
return event
},
})File: contrib_versioned_docs/version-websocket_v1.x.x/fibernewrelic/README.md
id: fibernewrelic
Fibernewrelic
NewRelic support for Fiber.
Note: Requires Go 1.18 and above
Install
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/fibernewrelicSignature
fibernewrelic.New(config fibernewrelic.Config) fiber.HandlerConfig
| Property | Type | Description | Default |
|---|---|---|---|
| License | string |
Required - New Relic License Key | "" |
| AppName | string |
New Relic Application Name | fiber-api |
| Enabled | bool |
Enable/Disable New Relic | false |
string |
"HTTP" |
||
| Application | Application |
Existing New Relic App | nil |
| ErrorStatusCodeHandler | func(c *fiber.Ctx, err error) int |
If you want to change newrelic status code, you can use it. | DefaultErrorStatusCodeHandler |
| Next | func(c *fiber.Ctx) bool |
Next defines a function to skip this middleware when returned true. | nil |
Usage
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/fibernewrelic"
)
func main() {
app := fiber.New()
app.Get("/", func(ctx *fiber.Ctx) error {
return ctx.SendStatus(200)
})
cfg := fibernewrelic.Config{
License: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
AppName: "MyCustomApi",
Enabled: true,
}
app.Use(fibernewrelic.New(cfg))
app.Listen(":8080")
}Usage with existing New Relic application
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/fibernewrelic"
"github.com/newrelic/go-agent/v3/newrelic"
)
func main() {
newrelicApp, err := newrelic.NewApplication(
newrelic.ConfigAppName("MyCustomApi"),
newrelic.ConfigLicense("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
newrelic.ConfigEnabled(true),
)
app := fiber.New()
app.Get("/", func(ctx *fiber.Ctx) error {
return ctx.SendStatus(200)
})
app.Get("/foo", func(ctx *fiber.Ctx) error {
txn := newrelic.FromContext(ctx)
segment := txn.StartSegment("foo segment")
defer segment.End()
// do foo
return nil
})
cfg := fibernewrelic.Config{
Application: newrelicApp,
}
app.Use(fibernewrelic.New(cfg))
app.Listen(":8080")
}