| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- package compress
- import (
- "strings"
- "github.com/gofiber/fiber/v3"
- "github.com/gofiber/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
- }
- }
|