Skip to content

Commit

Permalink
✨ Etag middleware support to custom etags
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandobandeira committed Apr 19, 2021
1 parent ec42f3c commit 72c8463
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 2 deletions.
4 changes: 4 additions & 0 deletions middleware/etag/etag.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func New(config ...Config) fiber.Handler {
if len(body) <= 0 {
return
}
// Skip ETag if header is already present
if c.Response().Header.PeekBytes(normalizedHeaderETag) != nil {
return
}

// Generate ETag for response
bb := bytebufferpool.Get()
Expand Down
77 changes: 75 additions & 2 deletions middleware/etag/etag_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package etag

import (
"bytes"
"io/ioutil"
"net/http/httptest"
"testing"

"github.com/valyala/fasthttp"

"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/utils"
"github.com/valyala/fasthttp"
)

// go test -run Test_ETag_Next
Expand Down Expand Up @@ -166,6 +166,79 @@ func testETagWeakEtag(t *testing.T, headerIfNoneMatch, matched bool) {
}
}

// go test -run Test_ETag_CustomEtag
func Test_ETag_CustomEtag(t *testing.T) {
t.Run("without HeaderIfNoneMatch", func(t *testing.T) {
testETagCustomEtag(t, false, false)
})
t.Run("with HeaderIfNoneMatch and not matched", func(t *testing.T) {
testETagCustomEtag(t, true, false)
})
t.Run("with HeaderIfNoneMatch and matched", func(t *testing.T) {
testETagCustomEtag(t, true, true)
})
}

func testETagCustomEtag(t *testing.T, headerIfNoneMatch, matched bool) {
app := fiber.New()

app.Use(New())

app.Get("/", func(c *fiber.Ctx) error {
c.Set(fiber.HeaderETag, `"custom"`)
if bytes.Equal(c.Request().Header.Peek(fiber.HeaderIfNoneMatch), []byte(`"custom"`)) {
return c.SendStatus(fiber.StatusNotModified)
}
return c.SendString("Hello, World!")
})

req := httptest.NewRequest("GET", "/", nil)
if headerIfNoneMatch {
etag := `"non-match"`
if matched {
etag = `"custom"`
}
req.Header.Set(fiber.HeaderIfNoneMatch, etag)
}

resp, err := app.Test(req)
utils.AssertEqual(t, nil, err)

if !headerIfNoneMatch || !matched {
utils.AssertEqual(t, fiber.StatusOK, resp.StatusCode)
utils.AssertEqual(t, `"custom"`, resp.Header.Get(fiber.HeaderETag))
return
}

if matched {
utils.AssertEqual(t, fiber.StatusNotModified, resp.StatusCode)
b, err := ioutil.ReadAll(resp.Body)
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, 0, len(b))
}
}

// go test -run Test_ETag_CustomEtagPut
func Test_ETag_CustomEtagPut(t *testing.T) {
app := fiber.New()

app.Use(New())

app.Put("/", func(c *fiber.Ctx) error {
c.Set(fiber.HeaderETag, `"custom"`)
if !bytes.Equal(c.Request().Header.Peek(fiber.HeaderIfMatch), []byte(`"custom"`)) {
return c.SendStatus(fiber.StatusPreconditionFailed)
}
return c.SendString("Hello, World!")
})

req := httptest.NewRequest("PUT", "/", nil)
req.Header.Set(fiber.HeaderIfMatch, `"non-match"`)
resp, err := app.Test(req)
utils.AssertEqual(t, nil, err)
utils.AssertEqual(t, fiber.StatusPreconditionFailed, resp.StatusCode)
}

// go test -v -run=^$ -bench=Benchmark_Etag -benchmem -count=4
func Benchmark_Etag(b *testing.B) {
app := fiber.New()
Expand Down

0 comments on commit 72c8463

Please sign in to comment.