mirror of
https://github.com/jech/galene.git
synced 2024-11-22 16:45: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
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// RFC 7232 section 4.1:
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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},
|
||||
{"GET", `"123"`, ``, `"124"`, 0},
|
||||
{"GET", `"123"`, ``, `*`, 304},
|
||||
{"POST", `"123"`, ``, `"124"`, 0},
|
||||
{"POST", `"123"`, ``, `*`, 412},
|
||||
}
|
||||
|
||||
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