chore: establish local platform baseline
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package concurrency
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrPreconditionRequired = errors.New("If-Match header is required")
|
||||
ErrInvalidETag = errors.New("invalid ETag")
|
||||
ErrVersionConflict = errors.New("resource version conflict")
|
||||
)
|
||||
|
||||
func FormatETag(version int64) string { return fmt.Sprintf("\"v%d\"", version) }
|
||||
|
||||
func ParseIfMatch(request *http.Request) (int64, error) {
|
||||
value := strings.TrimSpace(request.Header.Get("If-Match"))
|
||||
if value == "" {
|
||||
return 0, ErrPreconditionRequired
|
||||
}
|
||||
if value == "*" || strings.HasPrefix(value, "W/") || !strings.HasPrefix(value, "\"v") || !strings.HasSuffix(value, "\"") {
|
||||
return 0, ErrInvalidETag
|
||||
}
|
||||
version, err := strconv.ParseInt(strings.TrimSuffix(strings.TrimPrefix(value, "\"v"), "\""), 10, 64)
|
||||
if err != nil || version < 1 {
|
||||
return 0, ErrInvalidETag
|
||||
}
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func RequireVersion(expected, current int64) error {
|
||||
if expected != current {
|
||||
return ErrVersionConflict
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package concurrency
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseIfMatch(t *testing.T) {
|
||||
request := httptest.NewRequest("PATCH", "/resource", nil)
|
||||
if _, err := ParseIfMatch(request); !errors.Is(err, ErrPreconditionRequired) {
|
||||
t.Fatalf("missing header error = %v", err)
|
||||
}
|
||||
request.Header.Set("If-Match", FormatETag(3))
|
||||
if version, err := ParseIfMatch(request); err != nil || version != 3 {
|
||||
t.Fatalf("version = %d, err = %v", version, err)
|
||||
}
|
||||
for _, invalid := range []string{"*", "W/\"v3\"", "\"3\"", "\"v0\""} {
|
||||
request.Header.Set("If-Match", invalid)
|
||||
if _, err := ParseIfMatch(request); !errors.Is(err, ErrInvalidETag) {
|
||||
t.Fatalf("expected %q to be invalid, got %v", invalid, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRequireVersion(t *testing.T) {
|
||||
if err := RequireVersion(2, 2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := RequireVersion(1, 2); !errors.Is(err, ErrVersionConflict) {
|
||||
t.Fatalf("error = %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user