Refine logic

This commit is contained in:
binwiederhier 2023-09-24 17:59:23 -04:00
parent 4818ee57b6
commit d9387dac99
4 changed files with 57 additions and 33 deletions

View file

@ -8,11 +8,14 @@ import (
"mime"
"net/http"
"net/netip"
"strings"
"regexp"
"strings"
)
var mimeDecoder mime.WordDecoder
var (
mimeDecoder mime.WordDecoder
priorityHeaderIgnoreRegex = regexp.MustCompile(`^u=\d,\s*(i|\d)$|^u=\d$`)
)
func readBoolParam(r *http.Request, defaultValue bool, names ...string) bool {
value := strings.ToLower(readParam(r, names...))
@ -51,9 +54,9 @@ func readParam(r *http.Request, names ...string) string {
func readHeaderParam(r *http.Request, names ...string) string {
for _, name := range names {
value := maybeDecodeHeader(r.Header.Get(name), name)
value := strings.TrimSpace(maybeDecodeHeader(name, r.Header.Get(name)))
if value != "" {
return strings.TrimSpace(value)
return value
}
}
return ""
@ -127,29 +130,25 @@ func fromContext[T any](r *http.Request, key contextKey) (T, error) {
return t, nil
}
func maybeDecodeHeader(header string, name string) string {
decoded, err := mimeDecoder.DecodeHeader(header)
// maybeDecodeHeader decodes the given header value if it is MIME encoded, e.g. "=?utf-8?q?Hello_World?=",
// or returns the original header value if it is not MIME encoded. It also calls maybeIgnoreSpecialHeader
// to ignore new HTTP "Priority" header.
func maybeDecodeHeader(name, value string) string {
decoded, err := mimeDecoder.DecodeHeader(value)
if err != nil {
if name == "priority"{
return cloudflarePriorityIgnore(header)
}
return header
return maybeIgnoreSpecialHeader(name, value)
}
if name == "priority"{
return cloudflarePriorityIgnore(decoded)
}
return decoded
return maybeIgnoreSpecialHeader(name, decoded)
}
// 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 the Priority header is set to "u=*, i" or "u=*" (by cloudflare), the header will be ignored.
// And continue searching for another header (x-priority, prio, p) or in the Query parameters.
func cloudflarePriorityIgnore(value string) string {
pattern := `^u=\d,\s(i|\d)$|^u=\d$`
regex := regexp.MustCompile(pattern)
if regex.MatchString(value) {
// maybeIgnoreSpecialHeader ignores new HTTP "Priority" header (see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-priority)
//
// Cloudflare (and potentially other providers) add this to requests when forwarding to the backend (ntfy),
// so we just ignore it. If the "Priority" header is set to "u=*, i" or "u=*" (by Cloudflare), the header will be ignored.
// Returning an empty string will allow the rest of the logic to continue searching for another header (x-priority, prio, p),
// or in the Query parameters.
func maybeIgnoreSpecialHeader(name, value string) string {
if strings.ToLower(name) == "priority" && priorityHeaderIgnoreRegex.MatchString(strings.TrimSpace(value)) {
return ""
}
return value