Skip to content

Commit

Permalink
support If-Match
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidCai1111 committed Nov 24, 2016
1 parent 29d7c02 commit 1ff832c
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 8 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
test:
go test -v

cover:
rm -rf *.coverprofile
go test -coverprofile=fresh.coverprofile
gover
go tool cover -html=fresh.coverprofile
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ fresh.IsFresh(reqHeader, resHeader)
```go
reqHeader, resHeader := make(http.Header), make(http.Header)

reqHeader.Set(headers.IfMatch, "foo")
resHeader.Set(headers.ETag, "bar")

fresh.IsFresh(reqHeader, resHeader)
// -> true
```

```go
reqHeader, resHeader := make(http.Header), make(http.Header)

reqHeader.Set(headers.IfModifiedSince, "Mon, 14 Nov 2016 22:05:49 GMT")
resHeader.Set(headers.LastModified, "Mon, 14 Nov 2016 22:05:47 GMT")

Expand Down
40 changes: 40 additions & 0 deletions fresh.coverprofile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
mode: set
github.com/go-http-utils/fresh/fresh.go:15.65,30.17 9 1
github.com/go-http-utils/fresh/fresh.go:34.2,34.48 1 1
github.com/go-http-utils/fresh/fresh.go:38.2,38.37 1 1
github.com/go-http-utils/fresh/fresh.go:42.2,42.58 1 1
github.com/go-http-utils/fresh/fresh.go:46.2,46.49 1 1
github.com/go-http-utils/fresh/fresh.go:50.2,50.80 1 1
github.com/go-http-utils/fresh/fresh.go:54.2,54.43 1 1
github.com/go-http-utils/fresh/fresh.go:30.17,32.3 1 1
github.com/go-http-utils/fresh/fresh.go:34.48,36.3 1 1
github.com/go-http-utils/fresh/fresh.go:38.37,40.3 1 1
github.com/go-http-utils/fresh/fresh.go:42.58,44.3 1 1
github.com/go-http-utils/fresh/fresh.go:46.49,48.3 1 1
github.com/go-http-utils/fresh/fresh.go:50.80,52.3 1 1
github.com/go-http-utils/fresh/fresh.go:57.39,60.27 2 1
github.com/go-http-utils/fresh/fresh.go:64.2,64.19 1 1
github.com/go-http-utils/fresh/fresh.go:60.27,62.3 1 1
github.com/go-http-utils/fresh/fresh.go:67.70,68.51 1 1
github.com/go-http-utils/fresh/fresh.go:74.2,74.14 1 1
github.com/go-http-utils/fresh/fresh.go:68.51,69.88 1 1
github.com/go-http-utils/fresh/fresh.go:69.88,71.4 1 1
github.com/go-http-utils/fresh/fresh.go:77.62,78.43 1 1
github.com/go-http-utils/fresh/fresh.go:94.2,94.13 1 1
github.com/go-http-utils/fresh/fresh.go:78.43,79.25 1 1
github.com/go-http-utils/fresh/fresh.go:83.3,83.43 1 1
github.com/go-http-utils/fresh/fresh.go:79.25,81.4 1 1
github.com/go-http-utils/fresh/fresh.go:83.43,84.32 1 1
github.com/go-http-utils/fresh/fresh.go:84.32,86.5 1 1
github.com/go-http-utils/fresh/fresh.go:87.4,88.27 1 1
github.com/go-http-utils/fresh/fresh.go:88.27,90.5 1 1
github.com/go-http-utils/fresh/fresh.go:97.67,98.78 1 1
github.com/go-http-utils/fresh/fresh.go:102.2,102.14 1 0
github.com/go-http-utils/fresh/fresh.go:98.78,100.3 1 1
github.com/go-http-utils/fresh/fresh.go:105.71,106.80 1 1
github.com/go-http-utils/fresh/fresh.go:110.2,110.14 1 0
github.com/go-http-utils/fresh/fresh.go:106.80,108.3 1 1
github.com/go-http-utils/fresh/fresh.go:113.74,114.60 1 1
github.com/go-http-utils/fresh/fresh.go:120.2,120.22 1 0
github.com/go-http-utils/fresh/fresh.go:114.60,115.61 1 1
github.com/go-http-utils/fresh/fresh.go:115.61,117.4 1 1
44 changes: 36 additions & 8 deletions fresh.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

// Version is this package's verison
const Version = "0.3.1"
const Version = "0.4.0"

// IsFresh check whether cache can be used in this HTTP request
func IsFresh(reqHeader http.Header, resHeader http.Header) bool {
Expand All @@ -18,28 +18,36 @@ func IsFresh(reqHeader http.Header, resHeader http.Header) bool {
ifModifiedSince := reqHeader.Get(headers.IfModifiedSince)
ifUnmodifiedSince := reqHeader.Get(headers.IfUnmodifiedSince)
ifNoneMatch := reqHeader.Get(headers.IfNoneMatch)
ifMatch := reqHeader.Get(headers.IfMatch)
cacheControl := reqHeader.Get(headers.CacheControl)

etag := resHeader.Get(headers.ETag)
lastModified := resHeader.Get(headers.LastModified)

if ifModifiedSince == "" && ifUnmodifiedSince == "" && ifNoneMatch == "" {
if ifModifiedSince == "" &&
ifUnmodifiedSince == "" &&
ifNoneMatch == "" &&
ifMatch == "" {
return false
}

if strings.Contains(cacheControl, "no-cache") {
return false
}

if etag != "" {
isEtagMatched = checkEtagMatch(trimTags(strings.Split(ifNoneMatch, ",")), etag)
if etag != "" && ifNoneMatch != "" {
isEtagMatched = checkEtagNoneMatch(trimTags(strings.Split(ifNoneMatch, ",")), etag)
}

if etag != "" && ifMatch != "" && isEtagMatched != true {
isEtagMatched = checkEtagMatch(trimTags(strings.Split(ifMatch, ",")), etag)
}

if lastModified != "" && ifModifiedSince != "" {
isModifiedMatched = checkModifedMatch(lastModified, ifModifiedSince)
}

if lastModified != "" && ifUnmodifiedSince != "" {
if lastModified != "" && ifUnmodifiedSince != "" && isModifiedMatched != true {
isModifiedMatched = checkUnmodifedMatch(lastModified, ifUnmodifiedSince)
}

Expand All @@ -56,16 +64,36 @@ func trimTags(tags []string) []string {
return trimedTags
}

func checkEtagMatch(etagsToMatch []string, etag string) bool {
for _, etagToMatch := range etagsToMatch {
if etagToMatch == "*" || etagToMatch == etag || etagToMatch == "W/"+etag {
func checkEtagNoneMatch(etagsToNoneMatch []string, etag string) bool {
for _, etagToNoneMatch := range etagsToNoneMatch {
if etagToNoneMatch == "*" || etagToNoneMatch == etag || etagToNoneMatch == "W/"+etag {
return true
}
}

return false
}

func checkEtagMatch(etagsToMatch []string, etag string) bool {
for _, etagToMatch := range etagsToMatch {
if etagToMatch == "*" {
return false
}

if strings.HasPrefix(etagToMatch, "W/") {
if etagToMatch == "W/"+etag {
return false
}
} else {
if etagToMatch == etag {
return false
}
}
}

return true
}

func checkModifedMatch(lastModified, ifModifiedSince string) bool {
if lm, ims, ok := parseTimePairs(lastModified, ifModifiedSince); ok == true {
return lm.Before(ims)
Expand Down
42 changes: 42 additions & 0 deletions fresh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ func (s *FreshSuite) SetupTest() {
s.resHeader = make(http.Header)
}

func (s FreshSuite) TestNoCache() {
s.reqHeader.Set(headers.CacheControl, "no-cache")
s.reqHeader.Set(headers.IfNoneMatch, "foo")

s.False(IsFresh(s.reqHeader, s.resHeader))
}

func (s FreshSuite) TestEtagEmpty() {
s.False(IsFresh(s.reqHeader, s.resHeader))
}
Expand Down Expand Up @@ -59,6 +66,41 @@ func (s FreshSuite) TestEtagStrongMatch() {
s.True(IsFresh(s.reqHeader, s.resHeader))
}

func (s FreshSuite) TestEtagIfMatch() {
s.reqHeader.Set(headers.IfMatch, "foo")
s.resHeader.Set(headers.ETag, "bar")

s.True(IsFresh(s.reqHeader, s.resHeader))
}

func (s FreshSuite) TestWeakEtagIfMatch() {
s.reqHeader.Set(headers.IfMatch, "W/foo")
s.resHeader.Set(headers.ETag, "W/bar")

s.True(IsFresh(s.reqHeader, s.resHeader))
}

func (s FreshSuite) TestStarEtagIfMatch() {
s.reqHeader.Set(headers.IfMatch, "*")
s.resHeader.Set(headers.ETag, "W/bar")

s.False(IsFresh(s.reqHeader, s.resHeader))
}

func (s FreshSuite) TestWeakEtagIfMatchMatched() {
s.reqHeader.Set(headers.IfMatch, "W/bar")
s.resHeader.Set(headers.ETag, "bar")

s.False(IsFresh(s.reqHeader, s.resHeader))
}

func (s FreshSuite) TestEtagIfMatchMatched() {
s.reqHeader.Set(headers.IfMatch, "bar")
s.resHeader.Set(headers.ETag, "bar")

s.False(IsFresh(s.reqHeader, s.resHeader))
}

func (s FreshSuite) TestStaleOnEtagWeakMatch() {
s.reqHeader.Set(headers.IfNoneMatch, `"foo"`)
s.resHeader.Set(headers.ETag, `W/"foo"`)
Expand Down
40 changes: 40 additions & 0 deletions gover.coverprofile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
mode: set
github.com/go-http-utils/fresh/fresh.go:15.65,30.17 9 1
github.com/go-http-utils/fresh/fresh.go:34.2,34.48 1 1
github.com/go-http-utils/fresh/fresh.go:38.2,38.37 1 1
github.com/go-http-utils/fresh/fresh.go:42.2,42.58 1 1
github.com/go-http-utils/fresh/fresh.go:46.2,46.49 1 1
github.com/go-http-utils/fresh/fresh.go:50.2,50.80 1 1
github.com/go-http-utils/fresh/fresh.go:54.2,54.43 1 1
github.com/go-http-utils/fresh/fresh.go:30.17,32.3 1 1
github.com/go-http-utils/fresh/fresh.go:34.48,36.3 1 1
github.com/go-http-utils/fresh/fresh.go:38.37,40.3 1 1
github.com/go-http-utils/fresh/fresh.go:42.58,44.3 1 1
github.com/go-http-utils/fresh/fresh.go:46.49,48.3 1 1
github.com/go-http-utils/fresh/fresh.go:50.80,52.3 1 1
github.com/go-http-utils/fresh/fresh.go:57.39,60.27 2 1
github.com/go-http-utils/fresh/fresh.go:64.2,64.19 1 1
github.com/go-http-utils/fresh/fresh.go:60.27,62.3 1 1
github.com/go-http-utils/fresh/fresh.go:67.70,68.51 1 1
github.com/go-http-utils/fresh/fresh.go:74.2,74.14 1 1
github.com/go-http-utils/fresh/fresh.go:68.51,69.88 1 1
github.com/go-http-utils/fresh/fresh.go:69.88,71.4 1 1
github.com/go-http-utils/fresh/fresh.go:77.62,78.43 1 1
github.com/go-http-utils/fresh/fresh.go:94.2,94.13 1 1
github.com/go-http-utils/fresh/fresh.go:78.43,79.25 1 1
github.com/go-http-utils/fresh/fresh.go:83.3,83.43 1 1
github.com/go-http-utils/fresh/fresh.go:79.25,81.4 1 1
github.com/go-http-utils/fresh/fresh.go:83.43,84.32 1 1
github.com/go-http-utils/fresh/fresh.go:84.32,86.5 1 1
github.com/go-http-utils/fresh/fresh.go:87.4,88.27 1 1
github.com/go-http-utils/fresh/fresh.go:88.27,90.5 1 1
github.com/go-http-utils/fresh/fresh.go:97.67,98.78 1 1
github.com/go-http-utils/fresh/fresh.go:102.2,102.14 1 0
github.com/go-http-utils/fresh/fresh.go:98.78,100.3 1 1
github.com/go-http-utils/fresh/fresh.go:105.71,106.80 1 1
github.com/go-http-utils/fresh/fresh.go:110.2,110.14 1 0
github.com/go-http-utils/fresh/fresh.go:106.80,108.3 1 1
github.com/go-http-utils/fresh/fresh.go:113.74,114.60 1 1
github.com/go-http-utils/fresh/fresh.go:120.2,120.22 1 0
github.com/go-http-utils/fresh/fresh.go:114.60,115.61 1 1
github.com/go-http-utils/fresh/fresh.go:115.61,117.4 1 1

0 comments on commit 1ff832c

Please sign in to comment.