File: custom_query.go

package info (click to toggle)
golang-github-nicholas-fedor-shoutrrr 0.12.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,680 kB
  • sloc: sh: 74; makefile: 58
file content (84 lines) | stat: -rw-r--r-- 2,633 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package generic

import (
	"net/url"
	"strings"
)

// Constants for character values and offsets used in header normalization and query parsing.
const (
	ExtraPrefixChar      = '$'       // Prefix for extra data in query parameters
	HeaderPrefixChar     = '@'       // Prefix for header values in query parameters
	CaseOffset           = 'a' - 'A' // Offset between lowercase and uppercase letters
	UppercaseA           = 'A'       // ASCII value for uppercase A
	UppercaseZ           = 'Z'       // ASCII value for uppercase Z
	DashChar             = '-'       // Dash character for header formatting
	HeaderCapacityFactor = 2         // Estimated capacity multiplier for header string builder
)

// normalizedHeaderKey converts a header key to HTTP header format (e.g., "ContentType" -> "content-type").
func normalizedHeaderKey(key string) string {
	stringBuilder := strings.Builder{}
	// Pre-allocate capacity for efficiency
	stringBuilder.Grow(len(key) * HeaderCapacityFactor)

	for i, c := range key {
		if UppercaseA <= c && c <= UppercaseZ {
			// If character is uppercase
			if i > 0 && key[i-1] != DashChar {
				// Add dash before uppercase if not after dash
				stringBuilder.WriteRune(DashChar)
			}
		} else if i == 0 || key[i-1] == DashChar {
			// First char or after dash: convert to lowercase
			c -= CaseOffset
		}

		stringBuilder.WriteRune(c)
	}

	return stringBuilder.String()
}

// appendCustomQueryValues adds headers and extra data to URL query parameters with prefixes.
func appendCustomQueryValues(
	query url.Values,
	headers map[string]string,
	extraData map[string]string,
) {
	for key, value := range headers {
		// Add headers with @ prefix
		query.Set(string(HeaderPrefixChar)+key, value)
	}

	for key, value := range extraData {
		// Add extra data with $ prefix
		query.Set(string(ExtraPrefixChar)+key, value)
	}
}

// stripCustomQueryValues extracts headers and extra data from query parameters and removes them from the query.
func stripCustomQueryValues(query url.Values) (map[string]string, map[string]string) {
	// Map for extracted headers
	headers := make(map[string]string)
	// Map for extracted extra data
	extraData := make(map[string]string)

	for key, values := range query {
		switch key[0] {
		case HeaderPrefixChar: // Header prefixed with @
			// Normalize header key
			headerKey := normalizedHeaderKey(key[1:])
			headers[headerKey] = values[0]
		case ExtraPrefixChar: // Extra data prefixed with $
			extraData[key[1:]] = values[0]
		default: // Skip non-prefixed keys
			continue
		}

		// Remove the custom key from query
		delete(query, key)
	}

	return headers, extraData
}