From 95bd876be21fbff56fc0082725a69d6cb5a18a7c Mon Sep 17 00:00:00 2001
From: Philipp Heckel <pheckel@datto.com>
Date: Fri, 1 Jul 2022 09:28:42 -0400
Subject: [PATCH] Fix HTTP Spec priority header parsing

---
 server/types.go   |  2 +-
 util/util.go      |  8 +++++++-
 util/util_test.go | 12 +++++++++++-
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/server/types.go b/server/types.go
index bb8e32a3..44fe9e9e 100644
--- a/server/types.go
+++ b/server/types.go
@@ -174,7 +174,7 @@ func parseQueryFilters(r *http.Request) (*queryFilter, error) {
 	for _, p := range util.SplitNoEmpty(readParam(r, "x-priority", "priority", "prio", "p"), ",") {
 		priority, err := util.ParsePriority(p)
 		if err != nil {
-			return nil, err
+			return nil, errHTTPBadRequestPriorityInvalid
 		}
 		priorityFilter = append(priorityFilter, priority)
 	}
diff --git a/util/util.go b/util/util.go
index dab291ac..ce18f093 100644
--- a/util/util.go
+++ b/util/util.go
@@ -123,7 +123,8 @@ func ValidRandomString(s string, length int) bool {
 
 // ParsePriority parses a priority string into its equivalent integer value
 func ParsePriority(priority string) (int, error) {
-	switch strings.TrimSpace(strings.ToLower(priority)) {
+	p := strings.TrimSpace(strings.ToLower(priority))
+	switch p {
 	case "":
 		return 0, nil
 	case "1", "min":
@@ -137,6 +138,11 @@ func ParsePriority(priority string) (int, error) {
 	case "5", "max", "urgent":
 		return 5, nil
 	default:
+		// Ignore new HTTP Priority header (see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-priority)
+		// Cloudflare adds this to requests when forwarding to the backend (ntfy), so we just ignore it.
+		if strings.HasPrefix(p, "u=") {
+			return 3, nil
+		}
 		return 0, errInvalidPriority
 	}
 }
diff --git a/util/util_test.go b/util/util_test.go
index 9b716a35..8cecd00f 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -60,13 +60,23 @@ func TestParsePriority(t *testing.T) {
 }
 
 func TestParsePriority_Invalid(t *testing.T) {
-	priorities := []string{"-1", "6", "aa", "-"}
+	priorities := []string{"-1", "6", "aa", "-", "o=1"}
 	for _, priority := range priorities {
 		_, err := ParsePriority(priority)
 		require.Equal(t, errInvalidPriority, err)
 	}
 }
 
+func TestParsePriority_HTTPSpecPriority(t *testing.T) {
+	priorities := []string{"u=1", "u=3", "u=7, i"} // see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-priority
+	for _, priority := range priorities {
+		_, err := ParsePriority(priority)
+		actual, err := ParsePriority(priority)
+		require.Nil(t, err)
+		require.Equal(t, 3, actual) // Always expect 3!
+	}
+}
+
 func TestPriorityString(t *testing.T) {
 	priorities := []int{0, 1, 2, 3, 4, 5}
 	expected := []string{"default", "min", "low", "default", "high", "max"}