From 86bffa0844ad70927b4bf0d004ef3523f211dfc0 Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Thu, 20 Mar 2025 08:41:21 +0530 Subject: [PATCH 01/15] feat: req preprocessor --- .../requestPreProcessor/reqpreprocessor.go | 100 ++++++++++++ .../reqpreprocessor_test.go | 143 ++++++++++++++++++ 2 files changed, 243 insertions(+) create mode 100644 shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go create mode 100644 shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go new file mode 100644 index 0000000..177aecc --- /dev/null +++ b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go @@ -0,0 +1,100 @@ +package reqpreprocessor + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + + "github.com/google/uuid" +) + +type Config struct { + checkKeys []string +} + +const contextKey = "context" + +func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { + if err := validateConfig(cfg); err != nil { + return nil, err + } + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + + var data map[string]any + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Failed to read request body", http.StatusInternalServerError) + return + } + if err := json.Unmarshal(body, &data); err != nil { + http.Error(w, "Failed to decode request body", http.StatusBadRequest) + return + } + contextRaw := data[contextKey] + if contextRaw == nil { + http.Error(w, fmt.Sprintf("%s field not found.", contextKey), http.StatusBadRequest) + return + } + contextData, ok := contextRaw.(map[string]any) + if !ok { + http.Error(w, fmt.Sprintf("%s field is not a map.", contextKey), http.StatusBadRequest) + return + } + ctx := r.Context() + for _, key := range cfg.checkKeys { + value := uuid.NewString() + updatedValue := update(contextData, key, value) + ctx = context.WithValue(ctx, key, updatedValue) + } + data[contextKey] = contextData + updatedBody, err := json.Marshal(data) + if err != nil { + http.Error(w, "Failed to marshal updated JSON", http.StatusInternalServerError) + return + } + r.Body = io.NopCloser(bytes.NewBuffer(updatedBody)) + r.ContentLength = int64(len(updatedBody)) + r = r.WithContext(ctx) + next.ServeHTTP(w, r) + }) + }, nil +} + +func update(wrapper map[string]any, key string, value any) any { + field, exists := wrapper[key] + if !exists || isEmpty(field) { + wrapper[key] = value + return value + } + return field +} +func isEmpty(v any) bool { + switch v := v.(type) { + case string: + return v == "" + case nil: + return true + default: + return false + } +} + +func validateConfig(cfg *Config) error { + if cfg == nil { + return errors.New("config cannot be nil") + } + if len(cfg.checkKeys) == 0 { + return errors.New("checkKeys cannot be empty") + } + for _, key := range cfg.checkKeys { + if key == "" { + return errors.New("checkKeys cannot contain empty strings") + } + } + return nil +} diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go new file mode 100644 index 0000000..47e46e0 --- /dev/null +++ b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go @@ -0,0 +1,143 @@ +package reqpreprocessor + +import ( + "bytes" + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "testing" +) + +func TestNewUUIDSetter(t *testing.T) { + tests := []struct { + name string + config *Config + requestBody map[string]any + expectedCode int + expectedKeys []string + }{ + { + name: "Valid keys, update missing keys", + config: &Config{ + checkKeys: []string{"transaction_id", "message_id"}, + }, + requestBody: map[string]any{ + "context": map[string]any{ + "transaction_id": "", + "message_id": nil, + }, + }, + expectedCode: http.StatusOK, + expectedKeys: []string{"transaction_id", "message_id"}, + }, + { + name: "Valid keys, do not update existing keys", + config: &Config{ + checkKeys: []string{"transaction_id", "message_id"}, + }, + requestBody: map[string]any{ + "context": map[string]any{ + "transaction_id": "existing-transaction", + "message_id": "existing-message", + }, + }, + expectedCode: http.StatusOK, + expectedKeys: []string{"transaction_id", "message_id"}, + }, + { + name: "Missing context key", + config: &Config{ + checkKeys: []string{"transaction_id"}, + }, + requestBody: map[string]any{ + "otherKey": "value", + }, + expectedCode: http.StatusBadRequest, + }, + { + name: "Invalid context type", + config: &Config{ + checkKeys: []string{"transaction_id"}, + }, + requestBody: map[string]any{ + "context": "not-a-map", + }, + expectedCode: http.StatusBadRequest, + }, + { + name: "Empty checkKeys in config", + config: &Config{ + checkKeys: []string{}, + }, + requestBody: map[string]any{ + "context": map[string]any{ + "transaction_id": "", + }, + }, + expectedCode: http.StatusInternalServerError, + }, + { + name: "Nil config", + config: nil, + requestBody: map[string]any{}, + expectedCode: http.StatusInternalServerError, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + middleware, err := NewUUIDSetter(tt.config) + if tt.config == nil || len(tt.config.checkKeys) == 0 { + if err == nil { + t.Fatal("Expected an error, but got none") + } + return + } + if err != nil { + t.Fatalf("Unexpected error while creating middleware: %v", err) + } + + // Prepare request + bodyBytes, _ := json.Marshal(tt.requestBody) + req := httptest.NewRequest(http.MethodPost, "/test", bytes.NewReader(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + rec := httptest.NewRecorder() + + // Define a dummy handler + dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + io.Copy(w, r.Body) + }) + + // Apply middleware + middleware(dummyHandler).ServeHTTP(rec, req) + + // Check status code + if rec.Code != tt.expectedCode { + t.Errorf("Expected status code %d, but got %d", tt.expectedCode, rec.Code) + } + + // If success, check updated keys + if rec.Code == http.StatusOK { + var responseBody map[string]any + if err := json.Unmarshal(rec.Body.Bytes(), &responseBody); err != nil { + t.Fatal("Failed to unmarshal response body:", err) + } + + // Validate updated keys + contextData, ok := responseBody[contextKey].(map[string]any) + if !ok { + t.Fatalf("Expected context to be a map, got %T", responseBody[contextKey]) + } + + for _, key := range tt.expectedKeys { + value, exists := contextData[key] + if !exists || isEmpty(value) { + t.Errorf("Expected key %s to be set, but it's missing or empty", key) + } + } + } + }) + } +} From bc316ed39fa6f9f0f9d58074f83dc9bcb247432b Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Thu, 20 Mar 2025 08:47:30 +0530 Subject: [PATCH 02/15] feat: req preprocessor --- go.mod | 2 ++ go.sum | 2 ++ 2 files changed, 4 insertions(+) diff --git a/go.mod b/go.mod index 67f3590..5a545b8 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,8 @@ toolchain go1.23.7 require golang.org/x/crypto v0.36.0 +require github.com/google/uuid v1.6.0 // indirect + require ( golang.org/x/sys v0.31.0 // indirect gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index d05e730..54090b4 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= From aa10fcceaf254144621bff794ba4089028a1467a Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Thu, 20 Mar 2025 09:03:44 +0530 Subject: [PATCH 03/15] feat: req preprocessor --- .../implementation/requestPreProcessor/reqpreprocessor.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go index 177aecc..8dcb231 100644 --- a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go +++ b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go @@ -16,6 +16,8 @@ type Config struct { checkKeys []string } +type contextKeyType string + const contextKey = "context" func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { @@ -49,7 +51,7 @@ func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { for _, key := range cfg.checkKeys { value := uuid.NewString() updatedValue := update(contextData, key, value) - ctx = context.WithValue(ctx, key, updatedValue) + ctx = context.WithValue(ctx, contextKeyType(key), updatedValue) } data[contextKey] = contextData updatedBody, err := json.Marshal(data) From 5e3422fb24ef4d65b1b218248f80f818c6570bdc Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Thu, 20 Mar 2025 09:07:43 +0530 Subject: [PATCH 04/15] feat: req preprocessor --- .../requestPreProcessor/reqpreprocessor_test.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go index 47e46e0..483714d 100644 --- a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go +++ b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go @@ -24,8 +24,8 @@ func TestNewUUIDSetter(t *testing.T) { }, requestBody: map[string]any{ "context": map[string]any{ - "transaction_id": "", - "message_id": nil, + "transaction_id": "", + "message_id": nil, }, }, expectedCode: http.StatusOK, @@ -38,8 +38,8 @@ func TestNewUUIDSetter(t *testing.T) { }, requestBody: map[string]any{ "context": map[string]any{ - "transaction_id": "existing-transaction", - "message_id": "existing-message", + "transaction_id": "existing-transaction", + "message_id": "existing-message", }, }, expectedCode: http.StatusOK, @@ -107,7 +107,10 @@ func TestNewUUIDSetter(t *testing.T) { // Define a dummy handler dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) - io.Copy(w, r.Body) + if _, err := io.Copy(w, r.Body); err != nil { + http.Error(w, "Failed to copy request body", http.StatusInternalServerError) + return + } }) // Apply middleware From 02fb7c0897c83971bdc6ecfcb53605ff967ae0b9 Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Fri, 21 Mar 2025 04:44:58 +0530 Subject: [PATCH 05/15] feat: added role for bap and bpp --- .../requestPreProcessor/reqpreprocessor.go | 15 +++-- .../reqpreprocessor_test.go | 66 ++++++++----------- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go index 8dcb231..f5964c2 100644 --- a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go +++ b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go @@ -14,11 +14,12 @@ import ( type Config struct { checkKeys []string + Role string } - type contextKeyType string const contextKey = "context" +const subscriberIDKey contextKeyType = "subscriber_id" func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { if err := validateConfig(cfg); err != nil { @@ -47,7 +48,14 @@ func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { http.Error(w, fmt.Sprintf("%s field is not a map.", contextKey), http.StatusBadRequest) return } - ctx := r.Context() + var subID any + switch cfg.Role { + case "bap": + subID = contextData["bap_id"] + case "bpp": + subID = contextData["bpp_id"] + } + ctx := context.WithValue(r.Context(), subscriberIDKey, subID) for _, key := range cfg.checkKeys { value := uuid.NewString() updatedValue := update(contextData, key, value) @@ -90,9 +98,6 @@ func validateConfig(cfg *Config) error { if cfg == nil { return errors.New("config cannot be nil") } - if len(cfg.checkKeys) == 0 { - return errors.New("checkKeys cannot be empty") - } for _, key := range cfg.checkKeys { if key == "" { return errors.New("checkKeys cannot contain empty strings") diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go index 483714d..85001df 100644 --- a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go +++ b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go @@ -3,7 +3,6 @@ package reqpreprocessor import ( "bytes" "encoding/json" - "io" "net/http" "net/http/httptest" "testing" @@ -16,34 +15,41 @@ func TestNewUUIDSetter(t *testing.T) { requestBody map[string]any expectedCode int expectedKeys []string + role string }{ { - name: "Valid keys, update missing keys", + name: "Valid keys, update missing keys with bap role", config: &Config{ checkKeys: []string{"transaction_id", "message_id"}, + Role: "bap", }, requestBody: map[string]any{ "context": map[string]any{ "transaction_id": "", "message_id": nil, + "bap_id": "bap-123", }, }, expectedCode: http.StatusOK, - expectedKeys: []string{"transaction_id", "message_id"}, + expectedKeys: []string{"transaction_id", "message_id", "bap_id"}, + role: "bap", }, { - name: "Valid keys, do not update existing keys", + name: "Valid keys, do not update existing keys with bpp role", config: &Config{ checkKeys: []string{"transaction_id", "message_id"}, + Role: "bpp", }, requestBody: map[string]any{ "context": map[string]any{ "transaction_id": "existing-transaction", "message_id": "existing-message", + "bpp_id": "bpp-456", }, }, expectedCode: http.StatusOK, - expectedKeys: []string{"transaction_id", "message_id"}, + expectedKeys: []string{"transaction_id", "message_id", "bpp_id"}, + role: "bpp", }, { name: "Missing context key", @@ -65,18 +71,6 @@ func TestNewUUIDSetter(t *testing.T) { }, expectedCode: http.StatusBadRequest, }, - { - name: "Empty checkKeys in config", - config: &Config{ - checkKeys: []string{}, - }, - requestBody: map[string]any{ - "context": map[string]any{ - "transaction_id": "", - }, - }, - expectedCode: http.StatusInternalServerError, - }, { name: "Nil config", config: nil, @@ -97,48 +91,44 @@ func TestNewUUIDSetter(t *testing.T) { if err != nil { t.Fatalf("Unexpected error while creating middleware: %v", err) } - - // Prepare request bodyBytes, _ := json.Marshal(tt.requestBody) req := httptest.NewRequest(http.MethodPost, "/test", bytes.NewReader(bodyBytes)) req.Header.Set("Content-Type", "application/json") rec := httptest.NewRecorder() - - // Define a dummy handler dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() w.WriteHeader(http.StatusOK) - if _, err := io.Copy(w, r.Body); err != nil { - http.Error(w, "Failed to copy request body", http.StatusInternalServerError) + if subID, ok := ctx.Value(subscriberIDKey).(string); ok { + response := map[string]any{ + "subscriber_id": subID, + } + json.NewEncoder(w).Encode(response) + } else { + http.Error(w, "Subscriber ID not found", http.StatusInternalServerError) return } }) - - // Apply middleware middleware(dummyHandler).ServeHTTP(rec, req) - - // Check status code if rec.Code != tt.expectedCode { t.Errorf("Expected status code %d, but got %d", tt.expectedCode, rec.Code) } - - // If success, check updated keys if rec.Code == http.StatusOK { var responseBody map[string]any if err := json.Unmarshal(rec.Body.Bytes(), &responseBody); err != nil { t.Fatal("Failed to unmarshal response body:", err) } - - // Validate updated keys - contextData, ok := responseBody[contextKey].(map[string]any) - if !ok { - t.Fatalf("Expected context to be a map, got %T", responseBody[contextKey]) + expectedSubIDKey := "bap_id" + if tt.role == "bpp" { + expectedSubIDKey = "bpp_id" } - for _, key := range tt.expectedKeys { - value, exists := contextData[key] - if !exists || isEmpty(value) { - t.Errorf("Expected key %s to be set, but it's missing or empty", key) + if subID, ok := responseBody["subscriber_id"].(string); ok { + expectedSubID := tt.requestBody["context"].(map[string]any)[expectedSubIDKey] + if subID != expectedSubID { + t.Errorf("Expected subscriber_id %v, but got %v", expectedSubID, subID) } + } else { + t.Error("subscriber_id not found in response") } } }) From d4b2c95df89d2e17de40d22093bc39907eea758d Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Fri, 21 Mar 2025 10:16:51 +0530 Subject: [PATCH 06/15] feat: req preprocessor --- .../requestPreProcessor/reqpreprocessor_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go index 85001df..6c51307 100644 --- a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go +++ b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go @@ -102,8 +102,11 @@ func TestNewUUIDSetter(t *testing.T) { response := map[string]any{ "subscriber_id": subID, } - json.NewEncoder(w).Encode(response) - } else { + if err := json.NewEncoder(w).Encode(response); err != nil { + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } + } else { http.Error(w, "Subscriber ID not found", http.StatusInternalServerError) return } From 97db5cf6e7d760bdbb49cabee899a1dcd9709979 Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Mon, 24 Mar 2025 02:35:25 +0530 Subject: [PATCH 07/15] fix: reqpreprocessor --- .../requestPreProcessor/reqpreprocessor.go | 107 -------------- .../reqpreprocessor_test.go | 139 ------------------ 2 files changed, 246 deletions(-) delete mode 100644 shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go delete mode 100644 shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go deleted file mode 100644 index f5964c2..0000000 --- a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor.go +++ /dev/null @@ -1,107 +0,0 @@ -package reqpreprocessor - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - - "github.com/google/uuid" -) - -type Config struct { - checkKeys []string - Role string -} -type contextKeyType string - -const contextKey = "context" -const subscriberIDKey contextKeyType = "subscriber_id" - -func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { - if err := validateConfig(cfg); err != nil { - return nil, err - } - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - - var data map[string]any - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "Failed to read request body", http.StatusInternalServerError) - return - } - if err := json.Unmarshal(body, &data); err != nil { - http.Error(w, "Failed to decode request body", http.StatusBadRequest) - return - } - contextRaw := data[contextKey] - if contextRaw == nil { - http.Error(w, fmt.Sprintf("%s field not found.", contextKey), http.StatusBadRequest) - return - } - contextData, ok := contextRaw.(map[string]any) - if !ok { - http.Error(w, fmt.Sprintf("%s field is not a map.", contextKey), http.StatusBadRequest) - return - } - var subID any - switch cfg.Role { - case "bap": - subID = contextData["bap_id"] - case "bpp": - subID = contextData["bpp_id"] - } - ctx := context.WithValue(r.Context(), subscriberIDKey, subID) - for _, key := range cfg.checkKeys { - value := uuid.NewString() - updatedValue := update(contextData, key, value) - ctx = context.WithValue(ctx, contextKeyType(key), updatedValue) - } - data[contextKey] = contextData - updatedBody, err := json.Marshal(data) - if err != nil { - http.Error(w, "Failed to marshal updated JSON", http.StatusInternalServerError) - return - } - r.Body = io.NopCloser(bytes.NewBuffer(updatedBody)) - r.ContentLength = int64(len(updatedBody)) - r = r.WithContext(ctx) - next.ServeHTTP(w, r) - }) - }, nil -} - -func update(wrapper map[string]any, key string, value any) any { - field, exists := wrapper[key] - if !exists || isEmpty(field) { - wrapper[key] = value - return value - } - return field -} -func isEmpty(v any) bool { - switch v := v.(type) { - case string: - return v == "" - case nil: - return true - default: - return false - } -} - -func validateConfig(cfg *Config) error { - if cfg == nil { - return errors.New("config cannot be nil") - } - for _, key := range cfg.checkKeys { - if key == "" { - return errors.New("checkKeys cannot contain empty strings") - } - } - return nil -} diff --git a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go b/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go deleted file mode 100644 index 6c51307..0000000 --- a/shared/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package reqpreprocessor - -import ( - "bytes" - "encoding/json" - "net/http" - "net/http/httptest" - "testing" -) - -func TestNewUUIDSetter(t *testing.T) { - tests := []struct { - name string - config *Config - requestBody map[string]any - expectedCode int - expectedKeys []string - role string - }{ - { - name: "Valid keys, update missing keys with bap role", - config: &Config{ - checkKeys: []string{"transaction_id", "message_id"}, - Role: "bap", - }, - requestBody: map[string]any{ - "context": map[string]any{ - "transaction_id": "", - "message_id": nil, - "bap_id": "bap-123", - }, - }, - expectedCode: http.StatusOK, - expectedKeys: []string{"transaction_id", "message_id", "bap_id"}, - role: "bap", - }, - { - name: "Valid keys, do not update existing keys with bpp role", - config: &Config{ - checkKeys: []string{"transaction_id", "message_id"}, - Role: "bpp", - }, - requestBody: map[string]any{ - "context": map[string]any{ - "transaction_id": "existing-transaction", - "message_id": "existing-message", - "bpp_id": "bpp-456", - }, - }, - expectedCode: http.StatusOK, - expectedKeys: []string{"transaction_id", "message_id", "bpp_id"}, - role: "bpp", - }, - { - name: "Missing context key", - config: &Config{ - checkKeys: []string{"transaction_id"}, - }, - requestBody: map[string]any{ - "otherKey": "value", - }, - expectedCode: http.StatusBadRequest, - }, - { - name: "Invalid context type", - config: &Config{ - checkKeys: []string{"transaction_id"}, - }, - requestBody: map[string]any{ - "context": "not-a-map", - }, - expectedCode: http.StatusBadRequest, - }, - { - name: "Nil config", - config: nil, - requestBody: map[string]any{}, - expectedCode: http.StatusInternalServerError, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - middleware, err := NewUUIDSetter(tt.config) - if tt.config == nil || len(tt.config.checkKeys) == 0 { - if err == nil { - t.Fatal("Expected an error, but got none") - } - return - } - if err != nil { - t.Fatalf("Unexpected error while creating middleware: %v", err) - } - bodyBytes, _ := json.Marshal(tt.requestBody) - req := httptest.NewRequest(http.MethodPost, "/test", bytes.NewReader(bodyBytes)) - req.Header.Set("Content-Type", "application/json") - rec := httptest.NewRecorder() - dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - w.WriteHeader(http.StatusOK) - if subID, ok := ctx.Value(subscriberIDKey).(string); ok { - response := map[string]any{ - "subscriber_id": subID, - } - if err := json.NewEncoder(w).Encode(response); err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - } else { - http.Error(w, "Subscriber ID not found", http.StatusInternalServerError) - return - } - }) - middleware(dummyHandler).ServeHTTP(rec, req) - if rec.Code != tt.expectedCode { - t.Errorf("Expected status code %d, but got %d", tt.expectedCode, rec.Code) - } - if rec.Code == http.StatusOK { - var responseBody map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &responseBody); err != nil { - t.Fatal("Failed to unmarshal response body:", err) - } - expectedSubIDKey := "bap_id" - if tt.role == "bpp" { - expectedSubIDKey = "bpp_id" - } - - if subID, ok := responseBody["subscriber_id"].(string); ok { - expectedSubID := tt.requestBody["context"].(map[string]any)[expectedSubIDKey] - if subID != expectedSubID { - t.Errorf("Expected subscriber_id %v, but got %v", expectedSubID, subID) - } - } else { - t.Error("subscriber_id not found in response") - } - } - }) - } -} From 81a82df6f91982dcefbebee19ac23be4f8b1b40c Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Mon, 24 Mar 2025 09:24:14 +0530 Subject: [PATCH 08/15] fix: reqstruct --- .../requestPreProcessor/reqpreprocessor.go | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go index 427393e..58a09cc 100644 --- a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go +++ b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go @@ -17,6 +17,10 @@ type Config struct { Role string } +type BecknRequest struct { + Context map[string]any `json:"context"` +} + type contextKeyType string const contextKey = "context" @@ -28,42 +32,35 @@ func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { } return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - - var data map[string]any body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Failed to read request body", http.StatusInternalServerError) return } - if err := json.Unmarshal(body, &data); err != nil { + var req BecknRequest + if err := json.Unmarshal(body, &req); err != nil { http.Error(w, "Failed to decode request body", http.StatusBadRequest) return } - contextRaw := data[contextKey] - if contextRaw == nil { + if req.Context == nil { http.Error(w, fmt.Sprintf("%s field not found.", contextKey), http.StatusBadRequest) return } - contextData, ok := contextRaw.(map[string]any) - if !ok { - http.Error(w, fmt.Sprintf("%s field is not a map.", contextKey), http.StatusBadRequest) - return - } var subID any switch cfg.Role { case "bap": - subID = contextData["bap_id"] + subID = req.Context["bap_id"] case "bpp": - subID = contextData["bpp_id"] + subID = req.Context["bpp_id"] } ctx := context.WithValue(r.Context(), subscriberIDKey, subID) for _, key := range cfg.CheckKeys { value := uuid.NewString() - updatedValue := update(contextData, key, value) + updatedValue := update(req.Context, key, value) ctx = context.WithValue(ctx, contextKeyType(key), updatedValue) } - data[contextKey] = contextData - updatedBody, err := json.Marshal(data) + reqData := map[string]any{"context": req.Context} + updatedBody, err := json.Marshal(reqData) if err != nil { http.Error(w, "Failed to marshal updated JSON", http.StatusInternalServerError) return From 77ff19438699d98c55f4162ab437fda43559d3ff Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Wed, 26 Mar 2025 12:05:58 +0530 Subject: [PATCH 09/15] fix: resolved comments --- go.mod | 11 ++++++++--- go.sum | 9 +++++++-- .../requestPreProcessor/reqpreprocessor.go | 4 ++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index d557016..d4c311e 100644 --- a/go.mod +++ b/go.mod @@ -6,10 +6,15 @@ toolchain go1.23.7 require golang.org/x/crypto v0.36.0 -require github.com/google/uuid v1.6.0 // indirect +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.10.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) require ( - github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03 cloud.google.com/go v0.119.0 // indirect cloud.google.com/go/auth v0.15.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect @@ -19,9 +24,9 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/google/s2a-go v0.1.9 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.5 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03 go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect diff --git a/go.sum b/go.sum index 2bc3958..838a9ff 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03 h1:m1h+vudopHsI67FPT9MOncyndWhTcdUoBtI1R1uajGY= -github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03/go.mod h1:8sheVFH84v3PCyFY/O02mIgSQY9I6wMYPWsq7mDnEZY= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.119.0 h1:tw7OjErMzJKbbjaEHkrt60KQrK5Wus/boCZ7tm5/RNE= cloud.google.com/go v0.119.0/go.mod h1:fwB8QLzTcNevxqi8dcpR+hoMIs3jBherGS9VUBDAW08= @@ -18,6 +16,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -57,6 +56,7 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.5 h1:VgzTY2jogw3xt39CusE github.com/googleapis/enterprise-certificate-proxy v0.3.5/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA= github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -65,6 +65,10 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03 h1:m1h+vudopHsI67FPT9MOncyndWhTcdUoBtI1R1uajGY= +github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03/go.mod h1:8sheVFH84v3PCyFY/O02mIgSQY9I6wMYPWsq7mDnEZY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= @@ -157,6 +161,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go index 58a09cc..009fe5b 100644 --- a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go +++ b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go @@ -17,7 +17,7 @@ type Config struct { Role string } -type BecknRequest struct { +type becknRequest struct { Context map[string]any `json:"context"` } @@ -37,7 +37,7 @@ func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { http.Error(w, "Failed to read request body", http.StatusInternalServerError) return } - var req BecknRequest + var req becknRequest if err := json.Unmarshal(body, &req); err != nil { http.Error(w, "Failed to decode request body", http.StatusBadRequest) return From 1c9a7ae5950d59782d2b7ef2a721a953a620336c Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Wed, 26 Mar 2025 12:29:16 +0530 Subject: [PATCH 10/15] fix: resolved comments --- .../requestPreProcessor/reqpreprocessor.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go index 009fe5b..36389dc 100644 --- a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go +++ b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go @@ -32,11 +32,7 @@ func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { } return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "Failed to read request body", http.StatusInternalServerError) - return - } + body, _ := io.ReadAll(r.Body) var req becknRequest if err := json.Unmarshal(body, &req); err != nil { http.Error(w, "Failed to decode request body", http.StatusBadRequest) @@ -60,11 +56,7 @@ func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { ctx = context.WithValue(ctx, contextKeyType(key), updatedValue) } reqData := map[string]any{"context": req.Context} - updatedBody, err := json.Marshal(reqData) - if err != nil { - http.Error(w, "Failed to marshal updated JSON", http.StatusInternalServerError) - return - } + updatedBody, _ := json.Marshal(reqData) r.Body = io.NopCloser(bytes.NewBuffer(updatedBody)) r.ContentLength = int64(len(updatedBody)) r = r.WithContext(ctx) From 4a7e9d7b4f13578169ea07c5a719b7c07653bd14 Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Wed, 26 Mar 2025 12:31:17 +0530 Subject: [PATCH 11/15] fix: resolved comments --- .../reqpreprocessor_test.go | 117 ++++++++++++------ 1 file changed, 78 insertions(+), 39 deletions(-) diff --git a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go index ad11606..2ff382f 100644 --- a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go +++ b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go @@ -8,12 +8,11 @@ import ( "testing" ) -func TestNewUUIDSetter(t *testing.T) { +func TestNewUUIDSetter_SuccessCases(t *testing.T) { tests := []struct { name string config *Config requestBody map[string]any - expectedCode int expectedKeys []string role string }{ @@ -30,7 +29,6 @@ func TestNewUUIDSetter(t *testing.T) { "bap_id": "bap-123", }, }, - expectedCode: http.StatusOK, expectedKeys: []string{"transaction_id", "message_id", "bap_id"}, role: "bap", }, @@ -47,10 +45,79 @@ func TestNewUUIDSetter(t *testing.T) { "bpp_id": "bpp-456", }, }, - expectedCode: http.StatusOK, expectedKeys: []string{"transaction_id", "message_id", "bpp_id"}, role: "bpp", }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + middleware, err := NewUUIDSetter(tt.config) + if err != nil { + t.Fatalf("Unexpected error while creating middleware: %v", err) + } + + bodyBytes, _ := json.Marshal(tt.requestBody) + req := httptest.NewRequest(http.MethodPost, "/test", bytes.NewReader(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + + rec := httptest.NewRecorder() + + dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + w.WriteHeader(http.StatusOK) + + subID, ok := ctx.Value(subscriberIDKey).(string) + if !ok { + http.Error(w, "Subscriber ID not found", http.StatusInternalServerError) + return + } + + response := map[string]any{"subscriber_id": subID} + if err := json.NewEncoder(w).Encode(response); err != nil { + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } + }) + + middleware(dummyHandler).ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Errorf("Expected status code 200, but got %d", rec.Code) + return + } + + var responseBody map[string]any + if err := json.Unmarshal(rec.Body.Bytes(), &responseBody); err != nil { + t.Fatal("Failed to unmarshal response body:", err) + } + + expectedSubIDKey := "bap_id" + if tt.role == "bpp" { + expectedSubIDKey = "bpp_id" + } + + subID, ok := responseBody["subscriber_id"].(string) + if !ok { + t.Error("subscriber_id not found in response") + return + } + + expectedSubID := tt.requestBody["context"].(map[string]any)[expectedSubIDKey] + if subID != expectedSubID { + t.Errorf("Expected subscriber_id %v, but got %v", expectedSubID, subID) + } + }) + } +} + +func TestNewUUIDSetter_ErrorCases(t *testing.T) { + tests := []struct { + name string + config *Config + requestBody map[string]any + expectedCode int + }{ { name: "Missing context key", config: &Config{ @@ -82,58 +149,30 @@ func TestNewUUIDSetter(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { middleware, err := NewUUIDSetter(tt.config) - if tt.config == nil || len(tt.config.CheckKeys) == 0 { + if tt.config == nil { if err == nil { - t.Fatal("Expected an error, but got none") + t.Error("Expected an error for nil config, but got none") } return } if err != nil { t.Fatalf("Unexpected error while creating middleware: %v", err) } + bodyBytes, _ := json.Marshal(tt.requestBody) req := httptest.NewRequest(http.MethodPost, "/test", bytes.NewReader(bodyBytes)) req.Header.Set("Content-Type", "application/json") + rec := httptest.NewRecorder() dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() w.WriteHeader(http.StatusOK) - if subID, ok := ctx.Value(subscriberIDKey).(string); ok { - response := map[string]any{ - "subscriber_id": subID, - } - if err := json.NewEncoder(w).Encode(response); err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - } else { - http.Error(w, "Subscriber ID not found", http.StatusInternalServerError) - return - } }) + middleware(dummyHandler).ServeHTTP(rec, req) + if rec.Code != tt.expectedCode { t.Errorf("Expected status code %d, but got %d", tt.expectedCode, rec.Code) } - if rec.Code == http.StatusOK { - var responseBody map[string]any - if err := json.Unmarshal(rec.Body.Bytes(), &responseBody); err != nil { - t.Fatal("Failed to unmarshal response body:", err) - } - expectedSubIDKey := "bap_id" - if tt.role == "bpp" { - expectedSubIDKey = "bpp_id" - } - - if subID, ok := responseBody["subscriber_id"].(string); ok { - expectedSubID := tt.requestBody["context"].(map[string]any)[expectedSubIDKey] - if subID != expectedSubID { - t.Errorf("Expected subscriber_id %v, but got %v", expectedSubID, subID) - } - } else { - t.Error("subscriber_id not found in response") - } - } }) } -} +} \ No newline at end of file From 523cd077c4e4b37d95ed1d1d1e15f8156819cbcb Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Thu, 27 Mar 2025 08:30:27 +0530 Subject: [PATCH 12/15] fix: plugin test case --- .../requestPreProcessor/cmd/plugin_test.go | 84 +++++++++++++++++++ .../requestPreProcessor/reqpreprocessor.go | 7 ++ 2 files changed, 91 insertions(+) create mode 100644 pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go diff --git a/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go b/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go new file mode 100644 index 0000000..956be52 --- /dev/null +++ b/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go @@ -0,0 +1,84 @@ +package main + +import ( + "context" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestProviderNew(t *testing.T) { + testCases := []struct { + name string + config map[string]string + expectedError bool + expectedStatus int + prepareRequest func(req *http.Request) + }{ + { + name: "No Config", + config: map[string]string{}, + expectedError: true, + expectedStatus: http.StatusOK, + prepareRequest: func(req *http.Request) { + // Add minimal required headers + req.Header.Set("context", "test-context") + req.Header.Set("transaction_id", "test-transaction") + }, + }, + { + name: "With Check Keys", + config: map[string]string{ + "CheckKeys": "message_id,transaction_id", + }, + expectedError: false, + expectedStatus: http.StatusOK, + prepareRequest: func(req *http.Request) { + // Add headers matching the check keys + req.Header.Set("context", "test-context") + req.Header.Set("transaction_id", "test-transaction") + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + requestBody := `{ + "context": { + "transaction_id": "abc" + } + }` + + p := provider{} + middleware, err := p.New(context.Background(), tc.config) + if tc.expectedError { + assert.Error(t, err) + return + } + require.NoError(t, err) + assert.NotNil(t, middleware) + + testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + }) + + req := httptest.NewRequest("POST", "/", strings.NewReader(requestBody)) + req.Header.Set("Content-Type", "application/json") + if tc.prepareRequest != nil { + tc.prepareRequest(req) + } + + w := httptest.NewRecorder() + middlewaredHandler := middleware(testHandler) + middlewaredHandler.ServeHTTP(w, req) + assert.Equal(t, tc.expectedStatus, w.Code, "Unexpected response status") + responseBody := w.Body.String() + t.Logf("Response Body: %s", responseBody) + + }) + } +} diff --git a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go index 36389dc..031d4ce 100644 --- a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go +++ b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go @@ -88,6 +88,13 @@ func validateConfig(cfg *Config) error { if cfg == nil { return errors.New("config cannot be nil") } + + // Check if CheckKeys is empty + if len(cfg.CheckKeys) == 0 { + return errors.New("checkKeys cannot be empty") + } + + // Validate that CheckKeys does not contain empty strings for _, key := range cfg.CheckKeys { if key == "" { return errors.New("checkKeys cannot contain empty strings") From c64224032ba23a01505a080115c4603263924547 Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Fri, 28 Mar 2025 14:16:50 +0530 Subject: [PATCH 13/15] fix: resolved comments --- pkg/response/response_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/response/response_test.go b/pkg/response/response_test.go index 242fa72..73dcb6a 100644 --- a/pkg/response/response_test.go +++ b/pkg/response/response_test.go @@ -301,3 +301,17 @@ func compareContexts(c1, c2 map[string]interface{}) bool { return reflect.DeepEqual(c1, c2) } + +func TestSchemaValidationErr_Error(t *testing.T) { + validationErrors := []Error{ + {Paths: "name", Message: "Name is required"}, + {Paths: "email", Message: "Invalid email format"}, + } + err := SchemaValidationErr{Errors: validationErrors} + expected := "name: Name is required; email: Invalid email format" + if err.Error() != expected { + t.Errorf("err.Error() = %s, want %s", + err.Error(), expected) + + } +} From ead22119604a8325bf339ede7bb57b3fd9e7b13a Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Fri, 28 Mar 2025 16:09:31 +0530 Subject: [PATCH 14/15] fix: resolved comments --- .../requestPreProcessor/cmd/plugin.go | 4 ++-- .../requestPreProcessor/cmd/plugin_test.go | 1 + .../requestPreProcessor/reqpreprocessor.go | 18 +++++++++--------- .../reqpreprocessor_test.go | 16 ++++++++-------- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/pkg/plugin/implementation/requestPreProcessor/cmd/plugin.go b/pkg/plugin/implementation/requestPreProcessor/cmd/plugin.go index e8280d9..4a05ecc 100644 --- a/pkg/plugin/implementation/requestPreProcessor/cmd/plugin.go +++ b/pkg/plugin/implementation/requestPreProcessor/cmd/plugin.go @@ -12,8 +12,8 @@ type provider struct{} func (p provider) New(ctx context.Context, c map[string]string) (func(http.Handler) http.Handler, error) { config := &requestpreprocessor.Config{} - if checkKeysStr, ok := c["CheckKeys"]; ok { - config.CheckKeys = strings.Split(checkKeysStr, ",") + if contextKeysStr, ok := c["ContextKeys"]; ok { + config.ContextKeys = strings.Split(contextKeysStr, ",") } return requestpreprocessor.NewUUIDSetter(config) } diff --git a/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go b/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go index 4a8aae7..8b4cfe9 100644 --- a/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go +++ b/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" ) +// TODO: Will Split this into success and fail (two test cases) func TestProviderNew(t *testing.T) { testCases := []struct { name string diff --git a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go index ed2abda..13d4da0 100644 --- a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go +++ b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor.go @@ -13,8 +13,8 @@ import ( ) type Config struct { - CheckKeys []string - Role string + ContextKeys []string + Role string } type becknRequest struct { @@ -50,7 +50,7 @@ func NewUUIDSetter(cfg *Config) (func(http.Handler) http.Handler, error) { subID = req.Context["bpp_id"] } ctx := context.WithValue(r.Context(), subscriberIDKey, subID) - for _, key := range cfg.CheckKeys { + for _, key := range cfg.ContextKeys { value := uuid.NewString() updatedValue := update(req.Context, key, value) ctx = context.WithValue(ctx, contextKeyType(key), updatedValue) @@ -90,15 +90,15 @@ func validateConfig(cfg *Config) error { return errors.New("config cannot be nil") } - // Check if CheckKeys is empty. - if len(cfg.CheckKeys) == 0 { - return errors.New("checkKeys cannot be empty") + // Check if ContextKeys is empty. + if len(cfg.ContextKeys) == 0 { + return errors.New("ContextKeys cannot be empty") } - // Validate that CheckKeys does not contain empty strings. - for _, key := range cfg.CheckKeys { + // Validate that ContextKeys does not contain empty strings. + for _, key := range cfg.ContextKeys { if key == "" { - return errors.New("checkKeys cannot contain empty strings") + return errors.New("ContextKeys cannot contain empty strings") } } return nil diff --git a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go index 3e64156..307a7e7 100644 --- a/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go +++ b/pkg/plugin/implementation/requestPreProcessor/reqpreprocessor_test.go @@ -19,8 +19,8 @@ func TestNewUUIDSetterSuccessCases(t *testing.T) { { name: "Valid keys, update missing keys with bap role", config: &Config{ - CheckKeys: []string{"transaction_id", "message_id"}, - Role: "bap", + ContextKeys: []string{"transaction_id", "message_id"}, + Role: "bap", }, requestBody: map[string]any{ "context": map[string]any{ @@ -35,8 +35,8 @@ func TestNewUUIDSetterSuccessCases(t *testing.T) { { name: "Valid keys, do not update existing keys with bpp role", config: &Config{ - CheckKeys: []string{"transaction_id", "message_id"}, - Role: "bpp", + ContextKeys: []string{"transaction_id", "message_id"}, + Role: "bpp", }, requestBody: map[string]any{ "context": map[string]any{ @@ -66,7 +66,7 @@ func TestNewUUIDSetterSuccessCases(t *testing.T) { dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() w.WriteHeader(http.StatusOK) - + subID, ok := ctx.Value(subscriberIDKey).(string) if !ok { http.Error(w, "Subscriber ID not found", http.StatusInternalServerError) @@ -121,7 +121,7 @@ func TestNewUUIDSetterErrorCases(t *testing.T) { { name: "Missing context key", config: &Config{ - CheckKeys: []string{"transaction_id"}, + ContextKeys: []string{"transaction_id"}, }, requestBody: map[string]any{ "otherKey": "value", @@ -131,7 +131,7 @@ func TestNewUUIDSetterErrorCases(t *testing.T) { { name: "Invalid context type", config: &Config{ - CheckKeys: []string{"transaction_id"}, + ContextKeys: []string{"transaction_id"}, }, requestBody: map[string]any{ "context": "not-a-map", @@ -175,4 +175,4 @@ func TestNewUUIDSetterErrorCases(t *testing.T) { } }) } -} \ No newline at end of file +} From 9f7926289443477cb5e391ec181e2b57e15d7ac6 Mon Sep 17 00:00:00 2001 From: "mayur.popli" Date: Fri, 28 Mar 2025 16:14:06 +0530 Subject: [PATCH 15/15] fix: resolved comments --- .../implementation/requestPreProcessor/cmd/plugin_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go b/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go index 8b4cfe9..0890dbc 100644 --- a/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go +++ b/pkg/plugin/implementation/requestPreProcessor/cmd/plugin_test.go @@ -34,7 +34,7 @@ func TestProviderNew(t *testing.T) { { name: "With Check Keys", config: map[string]string{ - "CheckKeys": "message_id,transaction_id", + "ContextKeys": "message_id,transaction_id", }, expectedError: false, expectedStatus: http.StatusOK,