mirror of
https://github.com/zap-proto/fiber.git
synced 2026-10-30 15:06:23 +00:00
Fork of gofiber/fiber v3 based on the v3.2.0 tag. Rewrites all self-imports github.com/gofiber/fiber/v3 -> github.com/zap-proto/fiber/v3. Upstream gofiber/schema and gofiber/utils/v2 dependencies are left untouched. Co-authored-by: Hanzo Dev <[email protected]>
126 lines
2.9 KiB
Go
126 lines
2.9 KiB
Go
package compress
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/zap-proto/fiber/v3"
|
|
"github.com/zap-proto/fiber/v3/middleware/etag"
|
|
"github.com/gofiber/utils/v2"
|
|
"github.com/valyala/fasthttp"
|
|
)
|
|
|
|
func hasToken(header, token string) bool {
|
|
for part := range strings.SplitSeq(header, ",") {
|
|
if utils.EqualFold(utils.TrimSpace(part), token) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func shouldSkip(c fiber.Ctx) bool {
|
|
if c.Method() == fiber.MethodHead {
|
|
return true
|
|
}
|
|
|
|
status := c.Response().StatusCode()
|
|
if status < 200 ||
|
|
status == fiber.StatusNoContent ||
|
|
status == fiber.StatusResetContent ||
|
|
status == fiber.StatusNotModified ||
|
|
status == fiber.StatusPartialContent ||
|
|
len(c.Response().Body()) == 0 ||
|
|
c.Get(fiber.HeaderRange) != "" ||
|
|
hasToken(c.Get(fiber.HeaderCacheControl), "no-transform") ||
|
|
hasToken(c.GetRespHeader(fiber.HeaderCacheControl), "no-transform") {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func appendVaryAcceptEncoding(c fiber.Ctx) {
|
|
vary := c.GetRespHeader(fiber.HeaderVary)
|
|
if vary == "" {
|
|
c.Set(fiber.HeaderVary, fiber.HeaderAcceptEncoding)
|
|
return
|
|
}
|
|
if hasToken(vary, "*") || hasToken(vary, fiber.HeaderAcceptEncoding) {
|
|
return
|
|
}
|
|
c.Set(fiber.HeaderVary, vary+", "+fiber.HeaderAcceptEncoding)
|
|
}
|
|
|
|
// New creates a new middleware handler
|
|
func New(config ...Config) fiber.Handler {
|
|
// Set default config
|
|
cfg := configDefault(config...)
|
|
|
|
// Setup request handlers
|
|
var (
|
|
fctx = func(_ *fasthttp.RequestCtx) {}
|
|
compressor fasthttp.RequestHandler
|
|
)
|
|
|
|
// Setup compression algorithm
|
|
switch cfg.Level {
|
|
case LevelDefault:
|
|
// LevelDefault
|
|
compressor = fasthttp.CompressHandlerBrotliLevel(fctx,
|
|
fasthttp.CompressBrotliDefaultCompression,
|
|
fasthttp.CompressDefaultCompression,
|
|
)
|
|
case LevelBestSpeed:
|
|
// LevelBestSpeed
|
|
compressor = fasthttp.CompressHandlerBrotliLevel(fctx,
|
|
fasthttp.CompressBrotliBestSpeed,
|
|
fasthttp.CompressBestSpeed,
|
|
)
|
|
case LevelBestCompression:
|
|
// LevelBestCompression
|
|
compressor = fasthttp.CompressHandlerBrotliLevel(fctx,
|
|
fasthttp.CompressBrotliBestCompression,
|
|
fasthttp.CompressBestCompression,
|
|
)
|
|
default:
|
|
// LevelDisabled
|
|
return func(c fiber.Ctx) error {
|
|
return c.Next()
|
|
}
|
|
}
|
|
|
|
// Return new handler
|
|
return func(c fiber.Ctx) error {
|
|
// Don't execute middleware if Next returns true
|
|
if cfg.Next != nil && cfg.Next(c) {
|
|
return c.Next()
|
|
}
|
|
|
|
// Continue stack
|
|
if err := c.Next(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if shouldSkip(c) {
|
|
appendVaryAcceptEncoding(c)
|
|
return nil
|
|
}
|
|
|
|
if c.GetRespHeader(fiber.HeaderContentEncoding) != "" {
|
|
appendVaryAcceptEncoding(c)
|
|
return nil
|
|
}
|
|
|
|
compressor(c.RequestCtx())
|
|
|
|
if tag := c.GetRespHeader(fiber.HeaderETag); tag != "" && !strings.HasPrefix(tag, "W/") {
|
|
if c.GetRespHeader(fiber.HeaderContentEncoding) != "" {
|
|
c.Set(fiber.HeaderETag, string(etag.Generate(c.Response().Body())))
|
|
}
|
|
}
|
|
|
|
appendVaryAcceptEncoding(c)
|
|
|
|
return nil
|
|
}
|
|
}
|