From e55b07c58f2b774980a82c60daf98889ad6da769 Mon Sep 17 00:00:00 2001 From: Sergei Parshev Date: Fri, 18 Apr 2025 13:17:49 -0400 Subject: [PATCH 1/3] Added case-instensitive GetHeader for HookRequest & HookResponse --- github/repos_hooks_deliveries.go | 21 ++++++++++++ github/repos_hooks_deliveries_test.go | 48 +++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/github/repos_hooks_deliveries.go b/github/repos_hooks_deliveries.go index c8029f626b9..23d447d3b18 100644 --- a/github/repos_hooks_deliveries.go +++ b/github/repos_hooks_deliveries.go @@ -9,6 +9,7 @@ import ( "context" "encoding/json" "fmt" + "strings" ) // HookDelivery represents the data that is received from GitHub's Webhook Delivery API @@ -46,6 +47,16 @@ type HookRequest struct { RawPayload *json.RawMessage `json:"payload,omitempty"` } +// GetHeader gets the value associated with the given key (ignoring key case). +func (r *HookRequest) GetHeader(key string) string { + for k, v := range r.Headers { + if strings.EqualFold(k, key) { + return v + } + } + return "" +} + func (r HookRequest) String() string { return Stringify(r) } @@ -57,6 +68,16 @@ type HookResponse struct { RawPayload *json.RawMessage `json:"payload,omitempty"` } +// GetHeader gets the value associated with the given key (ignoring key case). +func (r *HookResponse) GetHeader(key string) string { + for k, v := range r.Headers { + if strings.EqualFold(k, key) { + return v + } + } + return "" +} + func (r HookResponse) String() string { return Stringify(r) } diff --git a/github/repos_hooks_deliveries_test.go b/github/repos_hooks_deliveries_test.go index 6acb7a81e69..9b73433dfd5 100644 --- a/github/repos_hooks_deliveries_test.go +++ b/github/repos_hooks_deliveries_test.go @@ -294,6 +294,30 @@ func TestHookRequest_Marshal(t *testing.T) { testJSONMarshal(t, r, want) } +func TestHookRequest_GetHeader(t *testing.T) { + t.Parallel() + + header := make(map[string]string) + header["key1"] = "value1" + header["Key+2"] = "value2" + header["kEy-3"] = "value3" + header["KEY_4"] = "value4" + + r := &HookRequest{ + Headers: header, + } + + testPrefixes := []string{"key", "Key", "kEy", "KEY"} + for hdrKey, hdrValue := range header { + for _, prefix := range testPrefixes { + key := prefix + hdrKey[3:] + if val := r.GetHeader(key); val != hdrValue { + t.Errorf("GetHeader(%q) is not working: %q != %q", key, val, hdrValue) + } + } + } +} + func TestHookResponse_Marshal(t *testing.T) { t.Parallel() testJSONMarshal(t, &HookResponse{}, "{}") @@ -320,6 +344,30 @@ func TestHookResponse_Marshal(t *testing.T) { testJSONMarshal(t, r, want) } +func TestHookResponse_GetHeader(t *testing.T) { + t.Parallel() + + header := make(map[string]string) + header["key1"] = "value1" + header["Key+2"] = "value2" + header["kEy-3"] = "value3" + header["KEY_4"] = "value4" + + r := &HookResponse{ + Headers: header, + } + + testPrefixes := []string{"key", "Key", "kEy", "KEY"} + for hdrKey, hdrValue := range header { + for _, prefix := range testPrefixes { + key := prefix + hdrKey[3:] + if val := r.GetHeader(key); val != hdrValue { + t.Errorf("GetHeader(%q) is not working: %q != %q", key, val, hdrValue) + } + } + } +} + func TestHookDelivery_Marshal(t *testing.T) { t.Parallel() testJSONMarshal(t, &HookDelivery{}, "{}") From d324b497aef22f3499fa05a0e23da6c9e91cd638 Mon Sep 17 00:00:00 2001 From: Sergei Parshev Date: Fri, 18 Apr 2025 13:58:11 -0400 Subject: [PATCH 2/3] Added negative cases as well --- github/repos_hooks_deliveries_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/github/repos_hooks_deliveries_test.go b/github/repos_hooks_deliveries_test.go index 9b73433dfd5..91ff3ad7113 100644 --- a/github/repos_hooks_deliveries_test.go +++ b/github/repos_hooks_deliveries_test.go @@ -307,6 +307,7 @@ func TestHookRequest_GetHeader(t *testing.T) { Headers: header, } + // Checking positive cases testPrefixes := []string{"key", "Key", "kEy", "KEY"} for hdrKey, hdrValue := range header { for _, prefix := range testPrefixes { @@ -316,6 +317,16 @@ func TestHookRequest_GetHeader(t *testing.T) { } } } + + // Checking negative case + key := "asd" + if val := r.GetHeader(key); val != "" { + t.Errorf("GetHeader(%q) should return empty value: %q != %q", key, val, "") + } + key = "kay1" + if val := r.GetHeader(key); val != "" { + t.Errorf("GetHeader(%q) should return empty value: %q != %q", key, val, "") + } } func TestHookResponse_Marshal(t *testing.T) { @@ -357,6 +368,7 @@ func TestHookResponse_GetHeader(t *testing.T) { Headers: header, } + // Checking positive cases testPrefixes := []string{"key", "Key", "kEy", "KEY"} for hdrKey, hdrValue := range header { for _, prefix := range testPrefixes { @@ -366,6 +378,16 @@ func TestHookResponse_GetHeader(t *testing.T) { } } } + + // Checking negative case + key := "asd" + if val := r.GetHeader(key); val != "" { + t.Errorf("GetHeader(%q) should return empty value: %q != %q", key, val, "") + } + key = "kay1" + if val := r.GetHeader(key); val != "" { + t.Errorf("GetHeader(%q) should return empty value: %q != %q", key, val, "") + } } func TestHookDelivery_Marshal(t *testing.T) { From 2d0b5cce4396a07fb2be51df2001a03368c1fad3 Mon Sep 17 00:00:00 2001 From: Sergei Parshev Date: Fri, 18 Apr 2025 15:03:15 -0400 Subject: [PATCH 3/3] Unified functions body for simplicity --- github/repos_hooks_deliveries.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/github/repos_hooks_deliveries.go b/github/repos_hooks_deliveries.go index 23d447d3b18..bcd4b336e53 100644 --- a/github/repos_hooks_deliveries.go +++ b/github/repos_hooks_deliveries.go @@ -40,6 +40,16 @@ func (d HookDelivery) String() string { return Stringify(d) } +// getHeader common function for GetHeader funcs of HookRequest & HookResponse. +func getHeader(headers map[string]string, key string) string { + for k, v := range headers { + if strings.EqualFold(k, key) { + return v + } + } + return "" +} + // HookRequest is a part of HookDelivery that contains // the HTTP headers and the JSON payload of the webhook request. type HookRequest struct { @@ -49,12 +59,7 @@ type HookRequest struct { // GetHeader gets the value associated with the given key (ignoring key case). func (r *HookRequest) GetHeader(key string) string { - for k, v := range r.Headers { - if strings.EqualFold(k, key) { - return v - } - } - return "" + return getHeader(r.Headers, key) } func (r HookRequest) String() string { @@ -70,12 +75,7 @@ type HookResponse struct { // GetHeader gets the value associated with the given key (ignoring key case). func (r *HookResponse) GetHeader(key string) string { - for k, v := range r.Headers { - if strings.EqualFold(k, key) { - return v - } - } - return "" + return getHeader(r.Headers, key) } func (r HookResponse) String() string {