run 'go get -u; make revendor'

Signed-off-by: Stephan Renatus <srenatus@chef.io>
This commit is contained in:
Stephan Renatus
2019-07-31 08:09:38 +02:00
parent 7c1b4b3005
commit 076cd77469
975 changed files with 347835 additions and 77390 deletions

View File

@@ -5,6 +5,6 @@ install:
- go get -u github.com/stretchr/testify/require
go:
- 1.5
- 1.6
- 1.7
- 1.8
- tip

View File

@@ -1,8 +1,7 @@
# cachecontrol: HTTP Caching Parser and Interpretation
[![GoDoc][1]][2][![Build Status](https://travis-ci.org/pquerna/cachecontrol.svg?branch=master)](https://travis-ci.org/pquerna/cachecontrol)
[1]: https://godoc.org/github.com/pquerna/cachecontrol?status.svg
[2]: https://godoc.org/github.com/pquerna/cachecontrol
[![GoDoc](https://godoc.org/github.com/pquerna/cachecontrol?status.svg)](https://godoc.org/github.com/pquerna/cachecontrol)[![Build Status](https://travis-ci.org/pquerna/cachecontrol.svg?branch=master)](https://travis-ci.org/pquerna/cachecontrol)
`cachecontrol` implements [RFC 7234](http://tools.ietf.org/html/rfc7234) __Hypertext Transfer Protocol (HTTP/1.1): Caching__. It does this by parsing the `Cache-Control` and other headers, providing information about requests and responses -- but `cachecontrol` does not implement an actual cache backend, just the control plane to make decisions about if a particular response is cachable.

View File

@@ -41,6 +41,10 @@ var (
ErrMustRevalidateNoArgs = errors.New("Unexpected argument to `must-revalidate`")
ErrPublicNoArgs = errors.New("Unexpected argument to `public`")
ErrProxyRevalidateNoArgs = errors.New("Unexpected argument to `proxy-revalidate`")
// Experimental
ErrImmutableNoArgs = errors.New("Unexpected argument to `immutable`")
ErrStaleIfErrorDeltaSeconds = errors.New("Failed to parse delta-seconds in `stale-if-error`")
ErrStaleWhileRevalidateDeltaSeconds = errors.New("Failed to parse delta-seconds in `stale-while-revalidate`")
)
func whitespace(b byte) bool {
@@ -70,7 +74,8 @@ func parse(value string, cd cacheDirective) error {
j++
}
token := value[i:j]
token := strings.ToLower(value[i:j])
tokenHasFields := hasFieldNames(token)
/*
println("GOT TOKEN:")
println(" i -> ", i)
@@ -92,15 +97,21 @@ func parse(value string, cd cacheDirective) error {
} else {
z := k
for z < len(value) {
if whitespace(value[z]) {
break
if tokenHasFields {
if whitespace(value[z]) {
break
}
} else {
if whitespace(value[z]) || value[z] == ',' {
break
}
}
z++
}
i = z
result := value[k:z]
if result[len(result)-1] == ',' {
if result != "" && result[len(result)-1] == ',' {
result = result[:len(result)-1]
}
@@ -253,10 +264,19 @@ func (cd *RequestCacheDirectives) addPair(token string, v string) error {
switch token {
case "max-age":
cd.MaxAge, err = parseDeltaSeconds(v)
if err != nil {
err = ErrMaxAgeDeltaSeconds
}
case "max-stale":
cd.MaxStale, err = parseDeltaSeconds(v)
if err != nil {
err = ErrMaxStaleDeltaSeconds
}
case "min-fresh":
cd.MinFresh, err = parseDeltaSeconds(v)
if err != nil {
err = ErrMinFreshDeltaSeconds
}
case "no-cache":
err = ErrNoCacheNoArgs
case "no-store":
@@ -387,6 +407,21 @@ type ResponseCacheDirectives struct {
// proxy-revalidate response directive.
SMaxAge DeltaSeconds
////
// Experimental features
// - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Extension_Cache-Control_directives
// - https://www.fastly.com/blog/stale-while-revalidate-stale-if-error-available-today
////
// immutable(cast-to-bool): experimental feature
Immutable bool
// stale-if-error(delta seconds): experimental feature
StaleIfError DeltaSeconds
// stale-while-revalidate(delta seconds): experimental feature
StaleWhileRevalidate DeltaSeconds
// Extensions: http://tools.ietf.org/html/rfc7234#section-5.2.3
//
// The Cache-Control header field can be extended through the use of one
@@ -400,6 +435,9 @@ func ParseResponseCacheControl(value string) (*ResponseCacheDirectives, error) {
cd := &ResponseCacheDirectives{
MaxAge: -1,
SMaxAge: -1,
// Exerimantal stale timeouts
StaleIfError: -1,
StaleWhileRevalidate: -1,
}
err := parse(value, cd)
@@ -430,12 +468,29 @@ func (cd *ResponseCacheDirectives) addToken(token string) error {
err = ErrMaxAgeDeltaSeconds
case "s-maxage":
err = ErrSMaxAgeDeltaSeconds
// Experimental
case "immutable":
cd.Immutable = true
case "stale-if-error":
err = ErrMaxAgeDeltaSeconds
case "stale-while-revalidate":
err = ErrMaxAgeDeltaSeconds
default:
cd.Extensions = append(cd.Extensions, token)
}
return err
}
func hasFieldNames(token string) bool {
switch token {
case "no-cache":
return true
case "private":
return true
}
return false
}
func (cd *ResponseCacheDirectives) addPair(token string, v string) error {
var err error = nil
@@ -474,6 +529,13 @@ func (cd *ResponseCacheDirectives) addPair(token string, v string) error {
cd.MaxAge, err = parseDeltaSeconds(v)
case "s-maxage":
cd.SMaxAge, err = parseDeltaSeconds(v)
// Experimental
case "immutable":
err = ErrImmutableNoArgs
case "stale-if-error":
cd.StaleIfError, err = parseDeltaSeconds(v)
case "stale-while-revalidate":
cd.StaleWhileRevalidate, err = parseDeltaSeconds(v)
default:
// TODO(pquerna): this sucks, making user re-parse, and its technically not 'quoted' like the original,
// but this is still easier, just a SplitN on "="

View File

@@ -243,20 +243,29 @@ func UsingRequestResponse(req *http.Request,
statusCode int,
respHeaders http.Header,
privateCache bool) ([]Reason, time.Time, error) {
reasons, time, _, _, err := UsingRequestResponseWithObject(req, statusCode, respHeaders, privateCache)
return reasons, time, err
}
// Evaluate cachability based on an HTTP request, and parts of the response.
// Returns the parsed Object as well.
func UsingRequestResponseWithObject(req *http.Request,
statusCode int,
respHeaders http.Header,
privateCache bool) ([]Reason, time.Time, []Warning, *Object, error) {
var reqHeaders http.Header
var reqMethod string
var reqDir *RequestCacheDirectives = nil
respDir, err := ParseResponseCacheControl(respHeaders.Get("Cache-Control"))
if err != nil {
return nil, time.Time{}, err
return nil, time.Time{}, nil, nil, err
}
if req != nil {
reqDir, err = ParseRequestCacheControl(req.Header.Get("Cache-Control"))
if err != nil {
return nil, time.Time{}, err
return nil, time.Time{}, nil, nil, err
}
reqHeaders = req.Header
reqMethod = req.Method
@@ -269,7 +278,9 @@ func UsingRequestResponse(req *http.Request,
if respHeaders.Get("Expires") != "" {
expiresHeader, err = http.ParseTime(respHeaders.Get("Expires"))
if err != nil {
return nil, time.Time{}, err
// sometimes servers will return `Expires: 0` or `Expires: -1` to
// indicate expired content
expiresHeader = time.Time{}
}
expiresHeader = expiresHeader.UTC()
}
@@ -277,7 +288,7 @@ func UsingRequestResponse(req *http.Request,
if respHeaders.Get("Date") != "" {
dateHeader, err = http.ParseTime(respHeaders.Get("Date"))
if err != nil {
return nil, time.Time{}, err
return nil, time.Time{}, nil, nil, err
}
dateHeader = dateHeader.UTC()
}
@@ -285,7 +296,7 @@ func UsingRequestResponse(req *http.Request,
if respHeaders.Get("Last-Modified") != "" {
lastModifiedHeader, err = http.ParseTime(respHeaders.Get("Last-Modified"))
if err != nil {
return nil, time.Time{}, err
return nil, time.Time{}, nil, nil, err
}
lastModifiedHeader = lastModifiedHeader.UTC()
}
@@ -310,15 +321,15 @@ func UsingRequestResponse(req *http.Request,
CachableObject(&obj, &rv)
if rv.OutErr != nil {
return nil, time.Time{}, rv.OutErr
return nil, time.Time{}, nil, nil, rv.OutErr
}
ExpirationObject(&obj, &rv)
if rv.OutErr != nil {
return nil, time.Time{}, rv.OutErr
return nil, time.Time{}, nil, nil, rv.OutErr
}
return rv.OutReasons, rv.OutExpirationTime, nil
return rv.OutReasons, rv.OutExpirationTime, rv.OutWarnings, &obj, nil
}
// calculate if a freshness directive is present: http://tools.ietf.org/html/rfc7234#section-4.2.1