From 7055c1c0d83545f8c75c0251c8a01d37bcaaf5c3 Mon Sep 17 00:00:00 2001 From: MohitKatare-protean Date: Fri, 28 Mar 2025 22:45:58 +0530 Subject: [PATCH] updated code. 1. Resolved merge conflicts. 2. Resolved go linting issues. --- cmd/adapter/main.go | 12 ++-- cmd/adapter/main_test.go | 4 +- config/bap.yaml | 69 ------------------- config/bapCallerRouting-config.yaml | 3 - config/bpp-local.yaml | 63 ----------------- config/bpp.yaml | 63 ----------------- config/bppCallerRouting-config.yaml | 3 - config/bppRecieverRouting-config.yaml | 3 - config/byuerApp-config.yaml | 2 - config/sellerData.yaml | 69 ------------------- core/module/client/registery.go | 2 +- core/module/handler/config.go | 44 +----------- core/module/handler/stdHandler.go | 10 +-- core/module/handler/step.go | 27 +------- go.mod | 8 ++- go.sum | 13 ++++ pkg/log/log.go | 23 +++++++ pkg/model/model.go | 26 +++++-- .../schemaValidator/cmd/plugin.go | 2 +- .../schemaValidator/schemaValidator.go | 2 +- .../schemaValidator/schemaValidator_test.go | 2 +- pkg/plugin/manager.go | 11 ++- pkg/response/response.go | 30 +++++--- pkg/response/response_test.go | 2 +- 24 files changed, 117 insertions(+), 376 deletions(-) delete mode 100644 config/bap.yaml delete mode 100644 config/bapCallerRouting-config.yaml delete mode 100644 config/bpp-local.yaml delete mode 100644 config/bpp.yaml delete mode 100644 config/bppCallerRouting-config.yaml delete mode 100644 config/bppRecieverRouting-config.yaml delete mode 100644 config/byuerApp-config.yaml delete mode 100644 config/sellerData.yaml diff --git a/cmd/adapter/main.go b/cmd/adapter/main.go index a233ea5..a581a59 100644 --- a/cmd/adapter/main.go +++ b/cmd/adapter/main.go @@ -25,12 +25,12 @@ type Config struct { Log log.Config `yaml:"log"` PluginManager *plugin.ManagerConfig `yaml:"pluginManager"` Modules []module.Config `yaml:"modules"` - HTTP timeouts `yaml:"http"` // Nest http config + HTTP timeouts `yaml:"http"` } type timeouts struct { - Port string `yaml:"port"` - Timeout timeoutConfig `yaml:"timeout"` + Port string `yaml:"port"` + Timeouts timeoutConfig `yaml:"timeout"` } type timeoutConfig struct { @@ -138,9 +138,9 @@ func run(ctx context.Context, configPath string) error { httpServer := &http.Server{ Addr: net.JoinHostPort("", cfg.HTTP.Port), Handler: srv, - ReadTimeout: cfg.HTTP.Timeout.Read * time.Second, // Use timeouts from config - WriteTimeout: cfg.HTTP.Timeout.Write * time.Second, - IdleTimeout: cfg.HTTP.Timeout.Idle * time.Second, + ReadTimeout: cfg.HTTP.Timeouts.Read * time.Second, + WriteTimeout: cfg.HTTP.Timeouts.Write * time.Second, + IdleTimeout: cfg.HTTP.Timeouts.Idle * time.Second, } // Start HTTP server. diff --git a/cmd/adapter/main_test.go b/cmd/adapter/main_test.go index 14f87e5..db27567 100644 --- a/cmd/adapter/main_test.go +++ b/cmd/adapter/main_test.go @@ -366,7 +366,7 @@ func TestNewServerSuccess(t *testing.T) { Modules: tt.modules, HTTP: timeouts{ Port: "8080", - Timeout: timeoutConfig{ + Timeouts: timeoutConfig{ Read: 5, Write: 5, Idle: 10, @@ -411,7 +411,7 @@ func TestNewServerFailure(t *testing.T) { Modules: tt.modules, HTTP: timeouts{ Port: "8080", - Timeout: timeoutConfig{ + Timeouts: timeoutConfig{ Read: 5, Write: 5, Idle: 10, diff --git a/config/bap.yaml b/config/bap.yaml deleted file mode 100644 index 25c67b2..0000000 --- a/config/bap.yaml +++ /dev/null @@ -1,69 +0,0 @@ -appName: "bapAdapter" -log: - level: debug - destinations: - - type: stdout - context_keys: - - transaction_id - - message_id -http: - port: 8080 - timeout: - read: 30 - write: 30 - idle: 30 -plugin: - root: /app/plugins - pluginZipPath: /mnt/gcs/plugins/plugins_bundle.zip - plugins: - - publisher Src version raw comp zip - - nopschemavalidator - - router - - nopsigner - - nopsignvalidator - - reqpreprocessor - - gcpAuthMdw -modules: - - name: reciever - type: transaction - path: /reciever - targetType: msgQ - plugin: - schemaValidator: - id: nopschemavalidator - signValidator: - id: nopsignvalidator - publisher: - id: publisher - config: - project: ondc-seller-dev - topic: bapNetworkReciever - router: - id: router - config: - routingConfigPath: /mnt/gcs/configs/bapRecieverRouting-config.yaml - preProcessors: - - id: reqpreprocessor - steps: - steps: - - addRoute - signValidate - -addRout - customValidate - - name: transactionCaller - path: /caller - targetType: "http" - plugin: - signer: - id: nopsigner - router: - id: router - config: - routingConfigPath: /mnt/gcs/configs/bapCallerRouting-config.yaml - preProcessors: - - id: reqpreprocessor - # postProcessors: - # - id: gcpAuthMdw - # config: - # audience: https://bpp-adapter-903496459467.asia-southeast1.run.app - # serviceAccount: 903496459467-compute@developer.gserviceaccount.com diff --git a/config/bapCallerRouting-config.yaml b/config/bapCallerRouting-config.yaml deleted file mode 100644 index a6702ea..0000000 --- a/config/bapCallerRouting-config.yaml +++ /dev/null @@ -1,3 +0,0 @@ -routes: - - action: search - target: https://bpp-adapter-903496459467.asia-southeast1.run.app/reciever \ No newline at end of file diff --git a/config/bpp-local.yaml b/config/bpp-local.yaml deleted file mode 100644 index 5af87f4..0000000 --- a/config/bpp-local.yaml +++ /dev/null @@ -1,63 +0,0 @@ -appName: "bppClientService" -log: - level: debug - destinations: - - type: stdout - context_keys: - - transaction_id - - message_id -http: - port: 8080 - timeout: - read: 30 - write: 30 - idle: 30 -plugin: - root: extracted/plugins - pluginZipPath: plugins_bundle.zip - plugins: - - publisher - - nopschemavalidator - - router - - nopsigner - - nopsignvalidator - - reqpreprocessor - - gcpAuthMdw -module: - modules: - - name: transactionReciever - path: /reciever - targetType: msgQ - plugin: - schemaValidator: - id: nopschemavalidator - signValidator: - id: nopsignValidator - publisher: - id: publisher - config: - project: ondc-seller-dev - topic: clientSideTopic - Router: - id: router - config: - routingConfigPath: configs/bppRecieverRouting-config.yaml - preProcessors: - - id: reqpreprocessor - - name: transactionCaller - path: /caller - targetType: "http" - plugin: - signer: - id: nopsigner - Router: - id: router - config: - routingConfigPath: configs/bppCallerRouting-config.yaml - preProcessors: - - id: reqpreprocessor - postProcessors: - - id: gcpAuthMdw - config: - audience: "target" - diff --git a/config/bpp.yaml b/config/bpp.yaml deleted file mode 100644 index a4d9a65..0000000 --- a/config/bpp.yaml +++ /dev/null @@ -1,63 +0,0 @@ -appName: "bppClientService" -log: - level: debug - destinations: - - type: stdout - context_keys: - - transaction_id - - message_id -http: - port: 8080 - timeout: - read: 30 - write: 30 - idle: 30 -plugin: - root: /app/plugins - pluginZipPath: /mnt/gcs/plugins/plugins_bundle.zip - plugins: - - publisher - - nopschemavalidator - - router - - nopsigner - - nopsignvalidator - - reqpreprocessor - - gcpAuthMdw -module: - modules: - - name: transactionReciever - path: /reciever - targetType: msgQ - plugin: - schemaValidator: - id: nopschemavalidator - signValidator: - id: nopsignvalidator - publisher: - id: publisher - config: - project: ondc-seller-dev - topic: bppNetworkReciever - router: - id: router - config: - routingConfigPath: /mnt/gcs/configs/bppRecieverRouting-config.yaml - preProcessors: - - id: reqpreprocessor - - name: transactionCaller - path: /caller - targetType: "http" - plugin: - signer: - id: nopsigner - router: - id: router - config: - routingConfigPath: /mnt/gcs/configs/bppCallerRouting-config.yaml - preProcessors: - - id: reqpreprocessor - # postProcessors: - # - id: gcpAuthMdw - # config: - # audience: https://bap-adapter-903496459467.asia-southeast1.run.app - # serviceAccount: 903496459467-compute@developer.gserviceaccount.com diff --git a/config/bppCallerRouting-config.yaml b/config/bppCallerRouting-config.yaml deleted file mode 100644 index 9aa5e39..0000000 --- a/config/bppCallerRouting-config.yaml +++ /dev/null @@ -1,3 +0,0 @@ -routes: - - action: on_search - target: targeturl \ No newline at end of file diff --git a/config/bppRecieverRouting-config.yaml b/config/bppRecieverRouting-config.yaml deleted file mode 100644 index 15fdb33..0000000 --- a/config/bppRecieverRouting-config.yaml +++ /dev/null @@ -1,3 +0,0 @@ -routes: - - action: search - target: https://sellerapp-903496459467.asia-southeast1.run.app \ No newline at end of file diff --git a/config/byuerApp-config.yaml b/config/byuerApp-config.yaml deleted file mode 100644 index a441371..0000000 --- a/config/byuerApp-config.yaml +++ /dev/null @@ -1,2 +0,0 @@ -bap_url: "https://bap-csr-903496459467.asia-southeast1.run.app" # Replace with actual Beckn API endpoint -port: "8080" # The port on which the server will run \ No newline at end of file diff --git a/config/sellerData.yaml b/config/sellerData.yaml deleted file mode 100644 index 9a96fdf..0000000 --- a/config/sellerData.yaml +++ /dev/null @@ -1,69 +0,0 @@ -- id: pooja-stores - descriptor: - name: Pooja Stores - locations: - - id: koramangala-4th-block-location - gps: "12.9349377,77.6055586" - categories: - - id: fresh_fruits - descriptor: - name: Fresh Fruits - - id: beverages - descriptor: - name: Beverages - items: - - id: item_2 - descriptor: - name: Green Apples Organic - images: - - url: "https://mock_bpp.com/images/item_2.jpg" - category_id: fresh_fruits - location_id: koramangala-4th-block-location - price: - currency: INR - value: "170" - matched: true - - id: item_1 - descriptor: - name: Red Apples - images: - - url: "https://mock_bpp.com/images/item_1.jpg" - category_id: fresh_fruits - location_id: koramangala-4th-block-location - price: - currency: INR - value: "90" - related: true - - id: item_7 - descriptor: - name: Green Apple Juice - images: - - url: "https://mock_bpp.com/images/item_7.jpg" - category_id: beverages - location_id: koramangala-4th-block-location - price: - currency: INR - value: "70" - matched: true -- id: food-mall - descriptor: - name: Food Mall - locations: - - id: food-mall-location - gps: "12.9349377,77.6055586" - categories: - - id: fresh-food - descriptor: - name: Fresh food - items: - - id: item_1_1 - descriptor: - name: Green Apple Salad - images: - - url: "https://mock_bpp.com/images/item_1_1.jpg" - category_id: fresh-food - location_id: food-mall-location - price: - currency: INR - value: "200" - matched: true diff --git a/core/module/client/registery.go b/core/module/client/registery.go index 2a688c6..57b8e71 100644 --- a/core/module/client/registery.go +++ b/core/module/client/registery.go @@ -24,7 +24,7 @@ type Config struct { // RegisteryClient encapsulates the logic for calling the subscribe and lookup endpoints. type RegisteryClient struct { Config *Config - Client *retryablehttp.Client // Retryable HTTP Client + Client *retryablehttp.Client } // NewRegisteryClient creates a new instance of Client. diff --git a/core/module/handler/config.go b/core/module/handler/config.go index 209de7f..fa2a966 100644 --- a/core/module/handler/config.go +++ b/core/module/handler/config.go @@ -2,7 +2,6 @@ package handler import ( "context" - "fmt" "net/http" "github.com/beckn/beckn-onix/pkg/model" @@ -10,7 +9,7 @@ import ( "github.com/beckn/beckn-onix/pkg/plugin/definition" ) -// PluginManager defines the methods required for managing plugins in stdHandler. +// PluginManager defines an interface for managing plugins dynamically. type PluginManager interface { Middleware(ctx context.Context, cfg *plugin.Config) (func(http.Handler) http.Handler, error) SignValidator(ctx context.Context, cfg *plugin.Config) (definition.Verifier, error) @@ -53,45 +52,4 @@ type Config struct { RegistryURL string `yaml:"registryUrl"` Role model.Role SubscriberID string `yaml:"subscriberId"` - Trace map[string]bool -} - -// Step represents a named processing step. -type Step string - -const ( - // StepInitialize represents the initialization phase of the request processing pipeline. - StepInitialize Step = "initialize" - - // StepValidate represents the validation phase, where input data is checked for correctness. - StepValidate Step = "validate" - - // StepProcess represents the core processing phase of the request. - StepProcess Step = "process" - - // StepFinalize represents the finalization phase, where the response is prepared and sent. - StepFinalize Step = "finalize" -) - -// validSteps ensures only allowed step values are used. -var validSteps = map[Step]bool{ - StepInitialize: true, - StepValidate: true, - StepProcess: true, - StepFinalize: true, -} - -// UnmarshalYAML customizes YAML unmarshalling for Step to enforce valid values. -func (s *Step) UnmarshalYAML(unmarshal func(interface{}) error) error { - var stepName string - if err := unmarshal(&stepName); err != nil { - return err - } - - step := Step(stepName) - if !validSteps[step] { - return fmt.Errorf("invalid step: %s", stepName) - } - *s = step - return nil } diff --git a/core/module/handler/stdHandler.go b/core/module/handler/stdHandler.go index 08e9628..9ca3dbe 100644 --- a/core/module/handler/stdHandler.go +++ b/core/module/handler/stdHandler.go @@ -38,11 +38,11 @@ func NewStdHandler(ctx context.Context, mgr PluginManager, cfg *Config) (http.Ha SubscriberID: cfg.SubscriberID, role: cfg.Role, } - // Initialize plugins + // Initialize plugins. if err := h.initPlugins(ctx, mgr, &cfg.Plugins, cfg.RegistryURL); err != nil { return nil, fmt.Errorf("failed to initialize plugins: %w", err) } - // Initialize steps + // Initialize steps. if err := h.initSteps(ctx, mgr, cfg); err != nil { return nil, fmt.Errorf("failed to initialize steps: %w", err) } @@ -59,7 +59,7 @@ func (h *stdHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } log.Request(r.Context(), r, ctx.Body) - // Execute processing steps + // Execute processing steps. for _, step := range h.steps { if err := step.Run(ctx); err != nil { log.Errorf(ctx, err, "%T.run(%v):%v", step, ctx, err) @@ -67,14 +67,14 @@ func (h *stdHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } } - // Restore request body before forwarding or publishing + // Restore request body before forwarding or publishing. r.Body = io.NopCloser(bytes.NewReader(ctx.Body)) if ctx.Route == nil { response.SendAck(w) return } - // Handle routing based on the defined route type + // Handle routing based on the defined route type. route(ctx, r, w, h.publisher) } diff --git a/core/module/handler/step.go b/core/module/handler/step.go index bbe01fd..d4aa63e 100644 --- a/core/module/handler/step.go +++ b/core/module/handler/step.go @@ -1,7 +1,6 @@ package handler import ( - "context" "fmt" "strings" "time" @@ -74,17 +73,17 @@ func (s *validateSignStep) Run(ctx *model.StepContext) error { if len(headerValue) != 0 { if err := s.validate(ctx, headerValue); err != nil { ctx.RespHeader.Set(model.UnaAuthorizedHeaderGateway, unauthHeader) - return model.NewSignValidationErrf("failed to validate %s: %w", model.AuthHeaderGateway, err) + return model.NewSignValidationErr(fmt.Errorf("failed to validate %s: %w", model.AuthHeaderGateway, err)) } } headerValue = ctx.Request.Header.Get(model.AuthHeaderSubscriber) if len(headerValue) == 0 { ctx.RespHeader.Set(model.UnaAuthorizedHeaderSubscriber, unauthHeader) - return model.NewSignValidationErrf("%s missing", model.UnaAuthorizedHeaderSubscriber) + return model.NewSignValidationErr(fmt.Errorf("%s missing", model.UnaAuthorizedHeaderSubscriber)) } if err := s.validate(ctx, headerValue); err != nil { ctx.RespHeader.Set(model.UnaAuthorizedHeaderSubscriber, unauthHeader) - return model.NewSignValidationErrf("failed to validate %s: %w", model.AuthHeaderSubscriber, err) + return model.NewSignValidationErr(fmt.Errorf("failed to validate %s: %w", model.AuthHeaderSubscriber, err)) } return nil } @@ -113,15 +112,6 @@ type validateSchemaStep struct { validator definition.SchemaValidator } -// newValidateSchemaStep creates and returns the validateSchema step after validation -func newValidateSchemaStep(schemaValidator definition.SchemaValidator) (definition.Step, error) { - if schemaValidator == nil { - return nil, fmt.Errorf("invalid config: SchemaValidator plugin not configured") - } - log.Debug(context.Background(), "adding schema validator") - return &validateSchemaStep{validator: schemaValidator}, nil -} - // Run executes the schema validation step. func (s *validateSchemaStep) Run(ctx *model.StepContext) error { if err := s.validator.Validate(ctx, ctx.Request.URL, ctx.Body); err != nil { @@ -135,14 +125,6 @@ type addRouteStep struct { router definition.Router } -// newRouteStep initializes and returns a new routing step. -func newRouteStep(router definition.Router) (definition.Step, error) { - if router == nil { - return nil, fmt.Errorf("invalid config: Router plugin not configured") - } - return &addRouteStep{router: router}, nil -} - // Run executes the routing step. func (s *addRouteStep) Run(ctx *model.StepContext) error { route, err := s.router.Route(ctx, ctx.Request.URL, ctx.Body) @@ -150,8 +132,5 @@ func (s *addRouteStep) Run(ctx *model.StepContext) error { return fmt.Errorf("failed to determine route: %w", err) } log.Debugf(ctx, "Routing to %#v", route) - ctx.Route = route - - log.Debugf(ctx, "ctx.Route to %#v", ctx.Route) return nil } diff --git a/go.mod b/go.mod index 7ec431b..044bb06 100644 --- a/go.mod +++ b/go.mod @@ -27,9 +27,15 @@ require ( golang.org/x/text v0.23.0 // indirect ) -require golang.org/x/sys v0.31.0 // indirect +require ( + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + golang.org/x/sys v0.31.0 // indirect +) require ( github.com/hashicorp/go-retryablehttp v0.7.7 + github.com/rs/zerolog v1.34.0 + gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 183730d..b00b8d5 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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= @@ -5,6 +6,7 @@ github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxK github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 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= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -22,14 +24,20 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= +github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= +github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= @@ -40,6 +48,9 @@ github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03 h1:m1h+vudopHsI67F github.com/zenazn/pkcs7pad v0.0.0-20170308005700-253a5b1f0e03/go.mod h1:8sheVFH84v3PCyFY/O02mIgSQY9I6wMYPWsq7mDnEZY= 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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= @@ -47,6 +58,8 @@ golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/pkg/log/log.go b/pkg/log/log.go index 8531eee..eabd9f0 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -25,11 +25,13 @@ type destination struct { Config map[string]string `yaml:"config"` } +// Destination types for logging output. const ( Stdout destinationType = "stdout" File destinationType = "file" ) +// Log levels define the severity of log messages. const ( DebugLevel level = "debug" InfoLevel level = "info" @@ -48,6 +50,7 @@ var logLevels = map[level]zerolog.Level{ PanicLevel: zerolog.PanicLevel, } +// Config represents the configuration for logging. type Config struct { Level level `yaml:"level"` Destinations []destination `yaml:"destinations"` @@ -60,6 +63,7 @@ var ( once sync.Once ) +// Logger instance and configuration. var ( ErrInvalidLogLevel = errors.New("invalid log level") ErrLogDestinationNil = errors.New("log Destinations cant be empty") @@ -163,6 +167,8 @@ func getLogger(config Config) (zerolog.Logger, error) { return newLogger, nil } +// InitLogger initializes the logger with the given configuration. +// It ensures that the logger is initialized only once using sync.Once. func InitLogger(c Config) error { var initErr error once.Do(func() { @@ -175,60 +181,74 @@ func InitLogger(c Config) error { return initErr } +// Debug logs a debug-level message with the provided context. func Debug(ctx context.Context, msg string) { logEvent(ctx, zerolog.DebugLevel, msg, nil) } +// Debugf logs a formatted debug-level message with the provided context. func Debugf(ctx context.Context, format string, v ...any) { msg := fmt.Sprintf(format, v...) logEvent(ctx, zerolog.DebugLevel, msg, nil) } +// Info logs an info-level message with the provided context. func Info(ctx context.Context, msg string) { logEvent(ctx, zerolog.InfoLevel, msg, nil) } +// Infof logs a formatted info-level message with the provided context. func Infof(ctx context.Context, format string, v ...any) { msg := fmt.Sprintf(format, v...) logEvent(ctx, zerolog.InfoLevel, msg, nil) } +// Warn logs a warning-level message with the provided context. func Warn(ctx context.Context, msg string) { logEvent(ctx, zerolog.WarnLevel, msg, nil) } +// Warnf logs a formatted warning-level message with the provided context. func Warnf(ctx context.Context, format string, v ...any) { msg := fmt.Sprintf(format, v...) logEvent(ctx, zerolog.WarnLevel, msg, nil) } +// Error logs an error-level message along with an error object. func Error(ctx context.Context, err error, msg string) { logEvent(ctx, zerolog.ErrorLevel, msg, err) } +// Errorf logs a formatted error-level message along with an error object. func Errorf(ctx context.Context, err error, format string, v ...any) { msg := fmt.Sprintf(format, v...) logEvent(ctx, zerolog.ErrorLevel, msg, err) } +// Fatal logs a fatal-level message along with an error object and exits the application. func Fatal(ctx context.Context, err error, msg string) { logEvent(ctx, zerolog.FatalLevel, msg, err) } +// Fatalf logs a formatted fatal-level message along with an error object and exits the application. func Fatalf(ctx context.Context, err error, format string, v ...any) { msg := fmt.Sprintf(format, v...) logEvent(ctx, zerolog.FatalLevel, msg, err) } +// Panic logs a panic-level message along with an error object and panics. func Panic(ctx context.Context, err error, msg string) { logEvent(ctx, zerolog.PanicLevel, msg, err) } +// Panicf logs a formatted panic-level message along with an error object and panics. func Panicf(ctx context.Context, err error, format string, v ...any) { msg := fmt.Sprintf(format, v...) logEvent(ctx, zerolog.PanicLevel, msg, err) } +// logEvent logs an event at the specified log level with an optional error message. +// It adds contextual information before logging the message. func logEvent(ctx context.Context, level zerolog.Level, msg string, err error) { event := logger.WithLevel(level) @@ -239,6 +259,7 @@ func logEvent(ctx context.Context, level zerolog.Level, msg string, err error) { event.Msg(msg) } +// Request logs details of an incoming HTTP request, including method, URL, body, and remote address. func Request(ctx context.Context, r *http.Request, body []byte) { event := logger.Info() addCtx(ctx, event) @@ -249,6 +270,7 @@ func Request(ctx context.Context, r *http.Request, body []byte) { Msg("HTTP Request") } +// addCtx adds context values to the log event based on configured context keys. func addCtx(ctx context.Context, event *zerolog.Event) { for _, key := range cfg.ContextKeys { val, ok := ctx.Value(key).(string) @@ -260,6 +282,7 @@ func addCtx(ctx context.Context, event *zerolog.Event) { } } +// Response logs details of an outgoing HTTP response, including method, URL, status code, and response time. func Response(ctx context.Context, r *http.Request, statusCode int, responseTime time.Duration) { event := logger.Info() addCtx(ctx, event) diff --git a/pkg/model/model.go b/pkg/model/model.go index c9876bf..b1cd0ae 100644 --- a/pkg/model/model.go +++ b/pkg/model/model.go @@ -40,14 +40,20 @@ const ( type contextKey string +// MsgIDKey is the context key used to store and retrieve the message ID in a request context. const MsgIDKey = contextKey("message_id") +// Role defines the type of participant in the network. type Role string const ( - RoleBAP Role = "bap" - RoleBPP Role = "bpp" - RoleGateway Role = "gateway" + // RoleBAP represents a Buyer App Participant (BAP) in the network. + RoleBAP Role = "bap" + // RoleBPP represents a Buyer Platform Participant (BPP) in the network. + RoleBPP Role = "bpp" + // RoleGateway represents a Gateway that facilitates communication in the network. + RoleGateway Role = "gateway" + // RoleRegistery represents the Registry that maintains network participant details. RoleRegistery Role = "registery" ) @@ -91,22 +97,32 @@ type StepContext struct { RespHeader http.Header } +// WithContext updates the existing StepContext with a new context. func (ctx *StepContext) WithContext(newCtx context.Context) { ctx.Context = newCtx } +// Status represents the acknowledgment status in a response. type Status string const ( - StatusACK Status = "ACK" + // StatusACK indicates a successful acknowledgment. + StatusACK Status = "ACK" + // StatusNACK indicates a negative acknowledgment or failure. StatusNACK Status = "NACK" ) +// Ack represents an acknowledgment response. type Ack struct { + // Status holds the acknowledgment status (ACK/NACK). Status Status `json:"status"` } + +// Message represents the structure of a response message. type Message struct { - Ack Ack `json:"ack"` + // Ack contains the acknowledgment status. + Ack Ack `json:"ack"` + // Error holds error details, if any, in the response. Error *Error `json:"error,omitempty"` } diff --git a/pkg/plugin/implementation/schemaValidator/cmd/plugin.go b/pkg/plugin/implementation/schemaValidator/cmd/plugin.go index 2a8f44a..b45f17e 100644 --- a/pkg/plugin/implementation/schemaValidator/cmd/plugin.go +++ b/pkg/plugin/implementation/schemaValidator/cmd/plugin.go @@ -5,7 +5,7 @@ import ( "errors" definition "github.com/beckn/beckn-onix/pkg/plugin/definition" - schemaValidator "github.com/beckn/beckn-onix/pkg/plugin/implementation/schemaValidator" + schemaValidator "github.com/beckn/beckn-onix/pkg/plugin/implementation/schemavalidator" ) // schemaValidatorProvider provides instances of schemaValidator. diff --git a/pkg/plugin/implementation/schemaValidator/schemaValidator.go b/pkg/plugin/implementation/schemaValidator/schemaValidator.go index 2d6b189..a981778 100644 --- a/pkg/plugin/implementation/schemaValidator/schemaValidator.go +++ b/pkg/plugin/implementation/schemaValidator/schemaValidator.go @@ -1,4 +1,4 @@ -package schemaValidator +package schemavalidator import ( "context" diff --git a/pkg/plugin/implementation/schemaValidator/schemaValidator_test.go b/pkg/plugin/implementation/schemaValidator/schemaValidator_test.go index 277b539..7264e2e 100644 --- a/pkg/plugin/implementation/schemaValidator/schemaValidator_test.go +++ b/pkg/plugin/implementation/schemaValidator/schemaValidator_test.go @@ -1,4 +1,4 @@ -package schemaValidator +package schemavalidator import ( "context" diff --git a/pkg/plugin/manager.go b/pkg/plugin/manager.go index 44f6bcf..2bf8c20 100644 --- a/pkg/plugin/manager.go +++ b/pkg/plugin/manager.go @@ -149,8 +149,15 @@ func (m *Manager) Router(ctx context.Context, cfg *Config) (definition.Router, e if err != nil { return nil, fmt.Errorf("failed to load provider for %s: %w", cfg.ID, err) } - return rp.New(ctx, cfg.Config) - + router, closer, err := rp.New(ctx, cfg.Config) + if closer != nil { + m.addCloser(func() { + if err := closer(); err != nil { + panic(err) + } + }) + } + return router, nil } func (m *Manager) Middleware(ctx context.Context, cfg *Config) (func(http.Handler) http.Handler, error) { diff --git a/pkg/response/response.go b/pkg/response/response.go index 976c1e0..c72b475 100644 --- a/pkg/response/response.go +++ b/pkg/response/response.go @@ -12,10 +12,16 @@ import ( "github.com/beckn/beckn-onix/pkg/model" ) +// Error represents a standardized error response used across the system. type Error struct { - Code string `json:"code,omitempty"` + // Code is a short, machine-readable error code. + Code string `json:"code,omitempty"` + + // Message provides a human-readable description of the error. Message string `json:"message,omitempty"` - Paths string `json:"paths,omitempty"` + + // Paths indicates the specific field(s) or endpoint(s) related to the error. + Paths string `json:"paths,omitempty"` } // SchemaValidationErr represents a collection of schema validation failures. @@ -32,13 +38,18 @@ func (e *SchemaValidationErr) Error() string { return strings.Join(errorMessages, "; ") } +// Message represents a standard message structure with acknowledgment and error information. type Message struct { + // Ack contains the acknowledgment status of the response. Ack struct { Status string `json:"status,omitempty"` } `json:"ack,omitempty"` + + // Error holds error details if any occurred during processing. Error *Error `json:"error,omitempty"` } +// SendAck sends an acknowledgment response (ACK) to the client. func SendAck(w http.ResponseWriter) { resp := &model.Response{ Message: model.Message{ @@ -59,7 +70,8 @@ func SendAck(w http.ResponseWriter) { } } -func nack(w http.ResponseWriter, err *model.Error, status int, ctx context.Context) { +// nack sends a negative acknowledgment (NACK) response with an error message. +func nack(ctx context.Context, w http.ResponseWriter, err *model.Error, status int) { resp := &model.Response{ Message: model.Message{ Ack: model.Ack{ @@ -80,6 +92,7 @@ func nack(w http.ResponseWriter, err *model.Error, status int, ctx context.Conte } } +// internalServerError generates an internal server error response. func internalServerError(ctx context.Context) *model.Error { return &model.Error{ Code: http.StatusText(http.StatusInternalServerError), @@ -87,6 +100,7 @@ func internalServerError(ctx context.Context) *model.Error { } } +// SendNack processes different types of errors and sends an appropriate NACK response. func SendNack(ctx context.Context, w http.ResponseWriter, err error) { var schemaErr *model.SchemaValidationErr var signErr *model.SignValidationErr @@ -95,19 +109,19 @@ func SendNack(ctx context.Context, w http.ResponseWriter, err error) { switch { case errors.As(err, &schemaErr): - nack(w, schemaErr.BecknError(), http.StatusBadRequest, ctx) + nack(ctx, w, schemaErr.BecknError(), http.StatusBadRequest) return case errors.As(err, &signErr): - nack(w, signErr.BecknError(), http.StatusUnauthorized, ctx) + nack(ctx, w, signErr.BecknError(), http.StatusUnauthorized) return case errors.As(err, &badReqErr): - nack(w, badReqErr.BecknError(), http.StatusBadRequest, ctx) + nack(ctx, w, badReqErr.BecknError(), http.StatusBadRequest) return case errors.As(err, ¬FoundErr): - nack(w, notFoundErr.BecknError(), http.StatusNotFound, ctx) + nack(ctx, w, notFoundErr.BecknError(), http.StatusNotFound) return default: - nack(w, internalServerError(ctx), http.StatusInternalServerError, ctx) + nack(ctx, w, internalServerError(ctx), http.StatusInternalServerError) return } } diff --git a/pkg/response/response_test.go b/pkg/response/response_test.go index 7e62aca..8b7f748 100644 --- a/pkg/response/response_test.go +++ b/pkg/response/response_test.go @@ -234,7 +234,7 @@ func TestNack_1(t *testing.T) { return } - nack(w, tt.err, tt.status, ctx) + nack(ctx, w, tt.err, tt.status) if !tt.useBadWrite { recorder, ok := w.(*httptest.ResponseRecorder) if !ok {