mirror of
https://github.com/jech/galene.git
synced 2024-11-23 00:55:58 +01:00
Implement precondition checking for objects with no ETag.
This commit is contained in:
parent
a3f894a31e
commit
e20a3a829e
2 changed files with 95 additions and 0 deletions
|
@ -70,6 +70,34 @@ func etagMatch(etag, header string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// etagMatchNoEtag evaluates preconditions for an object with no ETag.
|
||||||
|
func etagMatchNoEtag(exists bool, header string) bool {
|
||||||
|
if header == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
header = strings.TrimLeft(header, " \t\n\r")
|
||||||
|
if len(header) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if header[0] == ',' {
|
||||||
|
header = header[1:]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if header[0] == '*' {
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
e, remain := scanETag(header)
|
||||||
|
if e == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
header = remain
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func writeNotModified(w http.ResponseWriter) {
|
func writeNotModified(w http.ResponseWriter) {
|
||||||
// RFC 7232 section 4.1:
|
// RFC 7232 section 4.1:
|
||||||
// a sender SHOULD NOT generate representation metadata other than the
|
// a sender SHOULD NOT generate representation metadata other than the
|
||||||
|
@ -108,3 +136,25 @@ func checkPreconditions(w http.ResponseWriter, r *http.Request, etag string) (do
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkPreconditions evaluates request preconditions for an object with no ETag.
|
||||||
|
// exists indicates whether the object exists.
|
||||||
|
func checkPreconditionsNoEtag(w http.ResponseWriter, r *http.Request, exists bool) (done bool) {
|
||||||
|
im := r.Header.Get("If-Match")
|
||||||
|
if im != "" && !etagMatchNoEtag(exists, im) {
|
||||||
|
w.WriteHeader(http.StatusPreconditionFailed)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
inm := r.Header.Get("If-None-Match")
|
||||||
|
if inm != "" && etagMatchNoEtag(exists, inm) {
|
||||||
|
if r.Method == "GET" || r.Method == "HEAD" {
|
||||||
|
writeNotModified(w)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusPreconditionFailed)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -89,6 +89,8 @@ func TestCheckPreconditions(t *testing.T) {
|
||||||
{"POST", `"123"`, ``, `"123"`, 412},
|
{"POST", `"123"`, ``, `"123"`, 412},
|
||||||
{"GET", `"123"`, ``, `"124"`, 0},
|
{"GET", `"123"`, ``, `"124"`, 0},
|
||||||
{"GET", `"123"`, ``, `*`, 304},
|
{"GET", `"123"`, ``, `*`, 304},
|
||||||
|
{"POST", `"123"`, ``, `"124"`, 0},
|
||||||
|
{"POST", `"123"`, ``, `*`, 412},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tst := range tests {
|
for _, tst := range tests {
|
||||||
|
@ -112,3 +114,46 @@ func TestCheckPreconditions(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckPreconditionsNoEtag(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
method string
|
||||||
|
exists bool
|
||||||
|
im, inm string
|
||||||
|
result int
|
||||||
|
}{
|
||||||
|
{"GET", false, ``, ``, 0},
|
||||||
|
{"GET", false, `*`, ``, 412},
|
||||||
|
{"GET", false, ``, `*`, 0},
|
||||||
|
{"POST", false, `*`, ``, 412},
|
||||||
|
{"POST", false, ``, `*`, 0},
|
||||||
|
{"GET", true, ``, ``, 0},
|
||||||
|
{"GET", true, `"124"`, ``, 412},
|
||||||
|
{"POST", true, `"124"`, ``, 412},
|
||||||
|
{"GET", true, `*`, ``, 0},
|
||||||
|
{"GET", true, ``, `*`, 304},
|
||||||
|
{"POST", true, `*`, ``, 0},
|
||||||
|
{"POST", true, ``, `*`, 412},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tst := range tests {
|
||||||
|
var w testWriter
|
||||||
|
h := make(http.Header)
|
||||||
|
if tst.im != "" {
|
||||||
|
h.Set("If-Match", tst.im)
|
||||||
|
}
|
||||||
|
if tst.inm != "" {
|
||||||
|
h.Set("If-None-Match", tst.inm)
|
||||||
|
}
|
||||||
|
r := http.Request{
|
||||||
|
Method: tst.method,
|
||||||
|
Header: h,
|
||||||
|
}
|
||||||
|
done := checkPreconditionsNoEtag(&w, &r, tst.exists)
|
||||||
|
if done != (tst.result != 0) || w.statusCode != tst.result {
|
||||||
|
t.Errorf("%v %#v %#v: got %v, expected %v",
|
||||||
|
tst.exists, tst.im, tst.inm,
|
||||||
|
w.statusCode, tst.result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue