mirror of
https://github.com/minio/minio.git
synced 2024-12-25 06:35:56 -05:00
object: checkETag compares quoted ETags properly (#1997)
Previously, checkETag didn't handle ETags with leading and trailing double quotes. e.g "abcdef1234" == "\"abcdef1234\"" would return false. Now, checkETag function canonicalizes the ETags passed as arguments by removing one leading/trailing double quote.
This commit is contained in:
parent
1e52759c3c
commit
d0be09fdd3
@ -107,16 +107,6 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req
|
||||
return
|
||||
}
|
||||
|
||||
// Verify 'If-Modified-Since' and 'If-Unmodified-Since'.
|
||||
lastModified := objInfo.ModTime
|
||||
if checkLastModified(w, r, lastModified) {
|
||||
return
|
||||
}
|
||||
// Verify 'If-Match' and 'If-None-Match'.
|
||||
if checkETag(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
var hrange *httpRange
|
||||
hrange, err = getRequestedRange(r.Header.Get("Range"), objInfo.Size)
|
||||
if err != nil {
|
||||
@ -130,6 +120,16 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req
|
||||
// Set any additional requested response headers.
|
||||
setGetRespHeaders(w, r.URL.Query())
|
||||
|
||||
// Verify 'If-Modified-Since' and 'If-Unmodified-Since'.
|
||||
lastModified := objInfo.ModTime
|
||||
if checkLastModified(w, r, lastModified) {
|
||||
return
|
||||
}
|
||||
// Verify 'If-Match' and 'If-None-Match'.
|
||||
if checkETag(w, r) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get the object.
|
||||
startOffset := hrange.start
|
||||
length := hrange.length
|
||||
@ -191,25 +191,40 @@ func checkLastModified(w http.ResponseWriter, r *http.Request, modtime time.Time
|
||||
return false
|
||||
}
|
||||
|
||||
// canonicalizeETag returns ETag with leading and trailing double-quotes removed,
|
||||
// if any present
|
||||
func canonicalizeETag(etag string) string {
|
||||
canonicalETag := strings.TrimPrefix(etag, "\"")
|
||||
return strings.TrimSuffix(canonicalETag, "\"")
|
||||
}
|
||||
|
||||
// isETagEqual return true if the canonical representations of two ETag strings
|
||||
// are equal, false otherwise
|
||||
func isETagEqual(left, right string) bool {
|
||||
return canonicalizeETag(left) == canonicalizeETag(right)
|
||||
}
|
||||
|
||||
// checkETag implements If-None-Match and If-Match checks.
|
||||
//
|
||||
// The ETag must have been previously set in the ResponseWriter's
|
||||
// headers. The return value is whether this request is now considered
|
||||
// done.
|
||||
func checkETag(w http.ResponseWriter, r *http.Request) bool {
|
||||
// writer always has quoted string
|
||||
// transform reader's etag to
|
||||
if r.Method != "GET" && r.Method != "HEAD" {
|
||||
return false
|
||||
}
|
||||
etag := w.Header().Get("ETag")
|
||||
// Must know ETag.
|
||||
if etag == "" {
|
||||
return false
|
||||
}
|
||||
if inm := r.Header.Get("If-None-Match"); inm != "" {
|
||||
if inm := r.Header.Get("If-None-Match"); !isETagEqual(inm, "") {
|
||||
// Return the object only if its entity tag (ETag) is
|
||||
// different from the one specified; otherwise, return a 304
|
||||
// (not modified).
|
||||
if r.Method != "GET" && r.Method != "HEAD" {
|
||||
return false
|
||||
}
|
||||
if inm == etag || inm == "*" {
|
||||
if isETagEqual(inm, etag) || isETagEqual(inm, "*") {
|
||||
h := w.Header()
|
||||
// Remove following headers if already set.
|
||||
delete(h, "Content-Type")
|
||||
@ -218,13 +233,10 @@ func checkETag(w http.ResponseWriter, r *http.Request) bool {
|
||||
w.WriteHeader(http.StatusNotModified)
|
||||
return true
|
||||
}
|
||||
} else if im := r.Header.Get("If-Match"); im != "" {
|
||||
} else if im := r.Header.Get("If-Match"); !isETagEqual(im, "") {
|
||||
// Return the object only if its entity tag (ETag) is the same
|
||||
// as the one specified; otherwise, return a 412 (precondition failed).
|
||||
if r.Method != "GET" && r.Method != "HEAD" {
|
||||
return false
|
||||
}
|
||||
if im != etag {
|
||||
if !isETagEqual(im, etag) {
|
||||
h := w.Header()
|
||||
// Remove following headers if already set.
|
||||
delete(h, "Content-Type")
|
||||
@ -275,6 +287,9 @@ func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Re
|
||||
return
|
||||
}
|
||||
|
||||
// Set standard object headers.
|
||||
setObjectHeaders(w, objInfo, nil)
|
||||
|
||||
// Verify 'If-Modified-Since' and 'If-Unmodified-Since'.
|
||||
lastModified := objInfo.ModTime
|
||||
if checkLastModified(w, r, lastModified) {
|
||||
@ -286,9 +301,6 @@ func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Re
|
||||
return
|
||||
}
|
||||
|
||||
// Set standard object headers.
|
||||
setObjectHeaders(w, objInfo, nil)
|
||||
|
||||
// Successfull response.
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user