diff --git a/github/repos_hooks_deliveries.go b/github/repos_hooks_deliveries.go index c8029f626b9..bcd4b336e53 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 @@ -39,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 { @@ -46,6 +57,11 @@ 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 { + return getHeader(r.Headers, key) +} + func (r HookRequest) String() string { return Stringify(r) } @@ -57,6 +73,11 @@ 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 { + return getHeader(r.Headers, key) +} + 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..91ff3ad7113 100644 --- a/github/repos_hooks_deliveries_test.go +++ b/github/repos_hooks_deliveries_test.go @@ -294,6 +294,41 @@ 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, + } + + // Checking positive cases + 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) + } + } + } + + // 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) { t.Parallel() testJSONMarshal(t, &HookResponse{}, "{}") @@ -320,6 +355,41 @@ 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, + } + + // Checking positive cases + 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) + } + } + } + + // 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) { t.Parallel() testJSONMarshal(t, &HookDelivery{}, "{}")