Cache middleware for Fiber that intercepts responses and stores the body, Content-Type, and status code under a key derived from the request path and method. Special thanks to @codemicro for contributing this middleware to Fiber core.
By default, cached responses expire after five minutes and the middleware stores up to 1 MB of response bodies.
Request Directives
Cache-Control: no-cache returns the latest response while still caching it, so the status is always miss
Cache-Control: no-store skips caching and always forwards a fresh response
If the response includes a Cache-Control: max-age directive, its value sets the cache entry’s expiration.
Cacheable Status Codes
The middleware caches these RFC 7231 status codes:
200: OK
203: Non-Authoritative Information
204: No Content
206: Partial Content
300: Multiple Choices
301: Moved Permanently
404: Not Found
405: Method Not Allowed
410: Gone
414: URI Too Long
501: Not Implemented
Responses with other status codes result in an unreachable cache status.
Signatures
func New(config ...Config) fiber.Handler
Usage
import (
"github.com/gofiber/fiber/v3"
"github.com/gofiber/fiber/v3/middleware/cache"
"github.com/gofiber/utils/v2"
)
Basic Example
// Initialize default config
app.Use(cache.New())
// Or extend the config for customization
app.Use(cache.New(cache.Config{
Next: func(c fiber.Ctx) bool {
return fiber.Query[bool](c, "noCache")
},
Expiration: 30 * time.Minute,
DisableCacheControl: true,
}))
Custom Key and Expiration
Customize the cache key and expiration; the HTTP method is appended automatically:
app.Use(cache.New(cache.Config{
ExpirationGenerator: func(c fiber.Ctx, cfg *cache.Config) time.Duration {
newCacheTime, _ := strconv.Atoi(c.GetRespHeader("Cache-Time", "600"))
return time.Second * time.Duration(newCacheTime)
},
KeyGenerator: func(c fiber.Ctx) string {
return utils.CopyString(c.Path())
},
}))
app.Get("/", func(c fiber.Ctx) error {
c.Response().Header.Add("Cache-Time", "6000")
return c.SendString("hi")
})
Cache Invalidation
Use CacheInvalidator to invalidate entries programmatically:
app.Use(cache.New(cache.Config{
CacheInvalidator: func(c fiber.Ctx) bool {
return fiber.Query[bool](c, "invalidateCache")
},
}))
Configuration
Next
func(fiber.Ctx) bool
default:"nil"
Executed before creating the cache entry. Can be used to execute the request without cache creation. If an entry already exists, it will be used. To completely bypass the cache functionality in certain cases, use the skip middleware.
Expiration
time.Duration
default:"5 * time.Minute"
Time that a cached response will live.
Header on the response that indicates the cache status, with possible return values “hit,” “miss,” or “unreachable.”
Omits the Cache-Control header when set to true.
CacheInvalidator
func(fiber.Ctx) bool
default:"nil"
Executed before checking the cache entry. Can be used to invalidate the existing cache manually by returning true.
Turns off cache key redaction in logs and error messages when set to true.
Allows you to generate custom keys. The HTTP method is appended automatically.
ExpirationGenerator
func(fiber.Ctx, *cache.Config) time.Duration
default:"nil"
Allows you to generate custom expiration keys based on the request.
Storage
fiber.Storage
default:"In-memory store"
Used to store the state of the middleware.
Allows you to store additional headers generated by next middlewares & handler.
MaxBytes
uint
default:"1 * 1024 * 1024"
Maximum number of bytes of response bodies simultaneously stored in cache (~1 MB).
Methods
[]string
default:"[]string{fiber.MethodGet, fiber.MethodHead}"
Specifies the HTTP methods to cache.
Default Config
var ConfigDefault = Config{
Next: nil,
Expiration: 5 * time.Minute,
CacheHeader: "X-Cache",
DisableCacheControl: false,
CacheInvalidator: nil,
DisableValueRedaction: false,
KeyGenerator: func(c fiber.Ctx) string {
return utils.CopyString(c.Path())
},
ExpirationGenerator: nil,
StoreResponseHeaders: false,
Storage: nil,
MaxBytes: 1 * 1024 * 1024,
Methods: []string{fiber.MethodGet, fiber.MethodHead},
}
Common Use Cases
API Response Caching
api := app.Group("/api")
api.Use(cache.New(cache.Config{
Expiration: 10 * time.Minute,
KeyGenerator: func(c fiber.Ctx) string {
return c.Path() + "?" + c.Request().URI().QueryArgs().String()
},
}))
Per-Route Cache Duration
app.Get("/static", cache.New(cache.Config{
Expiration: 1 * time.Hour,
}), staticHandler)
app.Get("/dynamic", cache.New(cache.Config{
Expiration: 30 * time.Second,
}), dynamicHandler)
Conditional Caching
app.Use(cache.New(cache.Config{
Next: func(c fiber.Ctx) bool {
// Don't cache authenticated requests
return c.Get("Authorization") != ""
},
}))