updated code.
1. Resolved merge conflicts. 2. Resolved go linting issues.
This commit is contained in:
@@ -25,12 +25,12 @@ type Config struct {
|
|||||||
Log log.Config `yaml:"log"`
|
Log log.Config `yaml:"log"`
|
||||||
PluginManager *plugin.ManagerConfig `yaml:"pluginManager"`
|
PluginManager *plugin.ManagerConfig `yaml:"pluginManager"`
|
||||||
Modules []module.Config `yaml:"modules"`
|
Modules []module.Config `yaml:"modules"`
|
||||||
HTTP timeouts `yaml:"http"` // Nest http config
|
HTTP timeouts `yaml:"http"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type timeouts struct {
|
type timeouts struct {
|
||||||
Port string `yaml:"port"`
|
Port string `yaml:"port"`
|
||||||
Timeout timeoutConfig `yaml:"timeout"`
|
Timeouts timeoutConfig `yaml:"timeout"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type timeoutConfig struct {
|
type timeoutConfig struct {
|
||||||
@@ -138,9 +138,9 @@ func run(ctx context.Context, configPath string) error {
|
|||||||
httpServer := &http.Server{
|
httpServer := &http.Server{
|
||||||
Addr: net.JoinHostPort("", cfg.HTTP.Port),
|
Addr: net.JoinHostPort("", cfg.HTTP.Port),
|
||||||
Handler: srv,
|
Handler: srv,
|
||||||
ReadTimeout: cfg.HTTP.Timeout.Read * time.Second, // Use timeouts from config
|
ReadTimeout: cfg.HTTP.Timeouts.Read * time.Second,
|
||||||
WriteTimeout: cfg.HTTP.Timeout.Write * time.Second,
|
WriteTimeout: cfg.HTTP.Timeouts.Write * time.Second,
|
||||||
IdleTimeout: cfg.HTTP.Timeout.Idle * time.Second,
|
IdleTimeout: cfg.HTTP.Timeouts.Idle * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start HTTP server.
|
// Start HTTP server.
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ func TestNewServerSuccess(t *testing.T) {
|
|||||||
Modules: tt.modules,
|
Modules: tt.modules,
|
||||||
HTTP: timeouts{
|
HTTP: timeouts{
|
||||||
Port: "8080",
|
Port: "8080",
|
||||||
Timeout: timeoutConfig{
|
Timeouts: timeoutConfig{
|
||||||
Read: 5,
|
Read: 5,
|
||||||
Write: 5,
|
Write: 5,
|
||||||
Idle: 10,
|
Idle: 10,
|
||||||
@@ -411,7 +411,7 @@ func TestNewServerFailure(t *testing.T) {
|
|||||||
Modules: tt.modules,
|
Modules: tt.modules,
|
||||||
HTTP: timeouts{
|
HTTP: timeouts{
|
||||||
Port: "8080",
|
Port: "8080",
|
||||||
Timeout: timeoutConfig{
|
Timeouts: timeoutConfig{
|
||||||
Read: 5,
|
Read: 5,
|
||||||
Write: 5,
|
Write: 5,
|
||||||
Idle: 10,
|
Idle: 10,
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
routes:
|
|
||||||
- action: search
|
|
||||||
target: https://bpp-adapter-903496459467.asia-southeast1.run.app/reciever
|
|
||||||
@@ -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"
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
routes:
|
|
||||||
- action: on_search
|
|
||||||
target: targeturl
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
routes:
|
|
||||||
- action: search
|
|
||||||
target: https://sellerapp-903496459467.asia-southeast1.run.app
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -24,7 +24,7 @@ type Config struct {
|
|||||||
// RegisteryClient encapsulates the logic for calling the subscribe and lookup endpoints.
|
// RegisteryClient encapsulates the logic for calling the subscribe and lookup endpoints.
|
||||||
type RegisteryClient struct {
|
type RegisteryClient struct {
|
||||||
Config *Config
|
Config *Config
|
||||||
Client *retryablehttp.Client // Retryable HTTP Client
|
Client *retryablehttp.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRegisteryClient creates a new instance of Client.
|
// NewRegisteryClient creates a new instance of Client.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/beckn/beckn-onix/pkg/model"
|
"github.com/beckn/beckn-onix/pkg/model"
|
||||||
@@ -10,7 +9,7 @@ import (
|
|||||||
"github.com/beckn/beckn-onix/pkg/plugin/definition"
|
"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 {
|
type PluginManager interface {
|
||||||
Middleware(ctx context.Context, cfg *plugin.Config) (func(http.Handler) http.Handler, error)
|
Middleware(ctx context.Context, cfg *plugin.Config) (func(http.Handler) http.Handler, error)
|
||||||
SignValidator(ctx context.Context, cfg *plugin.Config) (definition.Verifier, error)
|
SignValidator(ctx context.Context, cfg *plugin.Config) (definition.Verifier, error)
|
||||||
@@ -53,45 +52,4 @@ type Config struct {
|
|||||||
RegistryURL string `yaml:"registryUrl"`
|
RegistryURL string `yaml:"registryUrl"`
|
||||||
Role model.Role
|
Role model.Role
|
||||||
SubscriberID string `yaml:"subscriberId"`
|
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
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ func NewStdHandler(ctx context.Context, mgr PluginManager, cfg *Config) (http.Ha
|
|||||||
SubscriberID: cfg.SubscriberID,
|
SubscriberID: cfg.SubscriberID,
|
||||||
role: cfg.Role,
|
role: cfg.Role,
|
||||||
}
|
}
|
||||||
// Initialize plugins
|
// Initialize plugins.
|
||||||
if err := h.initPlugins(ctx, mgr, &cfg.Plugins, cfg.RegistryURL); err != nil {
|
if err := h.initPlugins(ctx, mgr, &cfg.Plugins, cfg.RegistryURL); err != nil {
|
||||||
return nil, fmt.Errorf("failed to initialize plugins: %w", err)
|
return nil, fmt.Errorf("failed to initialize plugins: %w", err)
|
||||||
}
|
}
|
||||||
// Initialize steps
|
// Initialize steps.
|
||||||
if err := h.initSteps(ctx, mgr, cfg); err != nil {
|
if err := h.initSteps(ctx, mgr, cfg); err != nil {
|
||||||
return nil, fmt.Errorf("failed to initialize steps: %w", err)
|
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)
|
log.Request(r.Context(), r, ctx.Body)
|
||||||
|
|
||||||
// Execute processing steps
|
// Execute processing steps.
|
||||||
for _, step := range h.steps {
|
for _, step := range h.steps {
|
||||||
if err := step.Run(ctx); err != nil {
|
if err := step.Run(ctx); err != nil {
|
||||||
log.Errorf(ctx, err, "%T.run(%v):%v", step, ctx, err)
|
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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Restore request body before forwarding or publishing
|
// Restore request body before forwarding or publishing.
|
||||||
r.Body = io.NopCloser(bytes.NewReader(ctx.Body))
|
r.Body = io.NopCloser(bytes.NewReader(ctx.Body))
|
||||||
if ctx.Route == nil {
|
if ctx.Route == nil {
|
||||||
response.SendAck(w)
|
response.SendAck(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle routing based on the defined route type
|
// Handle routing based on the defined route type.
|
||||||
route(ctx, r, w, h.publisher)
|
route(ctx, r, w, h.publisher)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -74,17 +73,17 @@ func (s *validateSignStep) Run(ctx *model.StepContext) error {
|
|||||||
if len(headerValue) != 0 {
|
if len(headerValue) != 0 {
|
||||||
if err := s.validate(ctx, headerValue); err != nil {
|
if err := s.validate(ctx, headerValue); err != nil {
|
||||||
ctx.RespHeader.Set(model.UnaAuthorizedHeaderGateway, unauthHeader)
|
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)
|
headerValue = ctx.Request.Header.Get(model.AuthHeaderSubscriber)
|
||||||
if len(headerValue) == 0 {
|
if len(headerValue) == 0 {
|
||||||
ctx.RespHeader.Set(model.UnaAuthorizedHeaderSubscriber, unauthHeader)
|
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 {
|
if err := s.validate(ctx, headerValue); err != nil {
|
||||||
ctx.RespHeader.Set(model.UnaAuthorizedHeaderSubscriber, unauthHeader)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
@@ -113,15 +112,6 @@ type validateSchemaStep struct {
|
|||||||
validator definition.SchemaValidator
|
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.
|
// Run executes the schema validation step.
|
||||||
func (s *validateSchemaStep) Run(ctx *model.StepContext) error {
|
func (s *validateSchemaStep) Run(ctx *model.StepContext) error {
|
||||||
if err := s.validator.Validate(ctx, ctx.Request.URL, ctx.Body); err != nil {
|
if err := s.validator.Validate(ctx, ctx.Request.URL, ctx.Body); err != nil {
|
||||||
@@ -135,14 +125,6 @@ type addRouteStep struct {
|
|||||||
router definition.Router
|
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.
|
// Run executes the routing step.
|
||||||
func (s *addRouteStep) Run(ctx *model.StepContext) error {
|
func (s *addRouteStep) Run(ctx *model.StepContext) error {
|
||||||
route, err := s.router.Route(ctx, ctx.Request.URL, ctx.Body)
|
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)
|
return fmt.Errorf("failed to determine route: %w", err)
|
||||||
}
|
}
|
||||||
log.Debugf(ctx, "Routing to %#v", route)
|
log.Debugf(ctx, "Routing to %#v", route)
|
||||||
ctx.Route = route
|
|
||||||
|
|
||||||
log.Debugf(ctx, "ctx.Route to %#v", ctx.Route)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
8
go.mod
8
go.mod
@@ -27,9 +27,15 @@ require (
|
|||||||
golang.org/x/text v0.23.0 // indirect
|
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 (
|
require (
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7
|
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
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|||||||
13
go.sum
13
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/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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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/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 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
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 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
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/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 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
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 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
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/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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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.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 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
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 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
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=
|
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=
|
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 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
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 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
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 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 h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -25,11 +25,13 @@ type destination struct {
|
|||||||
Config map[string]string `yaml:"config"`
|
Config map[string]string `yaml:"config"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destination types for logging output.
|
||||||
const (
|
const (
|
||||||
Stdout destinationType = "stdout"
|
Stdout destinationType = "stdout"
|
||||||
File destinationType = "file"
|
File destinationType = "file"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Log levels define the severity of log messages.
|
||||||
const (
|
const (
|
||||||
DebugLevel level = "debug"
|
DebugLevel level = "debug"
|
||||||
InfoLevel level = "info"
|
InfoLevel level = "info"
|
||||||
@@ -48,6 +50,7 @@ var logLevels = map[level]zerolog.Level{
|
|||||||
PanicLevel: zerolog.PanicLevel,
|
PanicLevel: zerolog.PanicLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config represents the configuration for logging.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Level level `yaml:"level"`
|
Level level `yaml:"level"`
|
||||||
Destinations []destination `yaml:"destinations"`
|
Destinations []destination `yaml:"destinations"`
|
||||||
@@ -60,6 +63,7 @@ var (
|
|||||||
once sync.Once
|
once sync.Once
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Logger instance and configuration.
|
||||||
var (
|
var (
|
||||||
ErrInvalidLogLevel = errors.New("invalid log level")
|
ErrInvalidLogLevel = errors.New("invalid log level")
|
||||||
ErrLogDestinationNil = errors.New("log Destinations cant be empty")
|
ErrLogDestinationNil = errors.New("log Destinations cant be empty")
|
||||||
@@ -163,6 +167,8 @@ func getLogger(config Config) (zerolog.Logger, error) {
|
|||||||
return newLogger, nil
|
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 {
|
func InitLogger(c Config) error {
|
||||||
var initErr error
|
var initErr error
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
@@ -175,60 +181,74 @@ func InitLogger(c Config) error {
|
|||||||
return initErr
|
return initErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Debug logs a debug-level message with the provided context.
|
||||||
func Debug(ctx context.Context, msg string) {
|
func Debug(ctx context.Context, msg string) {
|
||||||
logEvent(ctx, zerolog.DebugLevel, msg, nil)
|
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) {
|
func Debugf(ctx context.Context, format string, v ...any) {
|
||||||
msg := fmt.Sprintf(format, v...)
|
msg := fmt.Sprintf(format, v...)
|
||||||
logEvent(ctx, zerolog.DebugLevel, msg, nil)
|
logEvent(ctx, zerolog.DebugLevel, msg, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Info logs an info-level message with the provided context.
|
||||||
func Info(ctx context.Context, msg string) {
|
func Info(ctx context.Context, msg string) {
|
||||||
logEvent(ctx, zerolog.InfoLevel, msg, nil)
|
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) {
|
func Infof(ctx context.Context, format string, v ...any) {
|
||||||
msg := fmt.Sprintf(format, v...)
|
msg := fmt.Sprintf(format, v...)
|
||||||
logEvent(ctx, zerolog.InfoLevel, msg, nil)
|
logEvent(ctx, zerolog.InfoLevel, msg, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Warn logs a warning-level message with the provided context.
|
||||||
func Warn(ctx context.Context, msg string) {
|
func Warn(ctx context.Context, msg string) {
|
||||||
logEvent(ctx, zerolog.WarnLevel, msg, nil)
|
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) {
|
func Warnf(ctx context.Context, format string, v ...any) {
|
||||||
msg := fmt.Sprintf(format, v...)
|
msg := fmt.Sprintf(format, v...)
|
||||||
logEvent(ctx, zerolog.WarnLevel, msg, nil)
|
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) {
|
func Error(ctx context.Context, err error, msg string) {
|
||||||
logEvent(ctx, zerolog.ErrorLevel, msg, err)
|
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) {
|
func Errorf(ctx context.Context, err error, format string, v ...any) {
|
||||||
msg := fmt.Sprintf(format, v...)
|
msg := fmt.Sprintf(format, v...)
|
||||||
logEvent(ctx, zerolog.ErrorLevel, msg, err)
|
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) {
|
func Fatal(ctx context.Context, err error, msg string) {
|
||||||
logEvent(ctx, zerolog.FatalLevel, msg, err)
|
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) {
|
func Fatalf(ctx context.Context, err error, format string, v ...any) {
|
||||||
msg := fmt.Sprintf(format, v...)
|
msg := fmt.Sprintf(format, v...)
|
||||||
logEvent(ctx, zerolog.FatalLevel, msg, err)
|
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) {
|
func Panic(ctx context.Context, err error, msg string) {
|
||||||
logEvent(ctx, zerolog.PanicLevel, msg, err)
|
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) {
|
func Panicf(ctx context.Context, err error, format string, v ...any) {
|
||||||
msg := fmt.Sprintf(format, v...)
|
msg := fmt.Sprintf(format, v...)
|
||||||
logEvent(ctx, zerolog.PanicLevel, msg, err)
|
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) {
|
func logEvent(ctx context.Context, level zerolog.Level, msg string, err error) {
|
||||||
event := logger.WithLevel(level)
|
event := logger.WithLevel(level)
|
||||||
|
|
||||||
@@ -239,6 +259,7 @@ func logEvent(ctx context.Context, level zerolog.Level, msg string, err error) {
|
|||||||
event.Msg(msg)
|
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) {
|
func Request(ctx context.Context, r *http.Request, body []byte) {
|
||||||
event := logger.Info()
|
event := logger.Info()
|
||||||
addCtx(ctx, event)
|
addCtx(ctx, event)
|
||||||
@@ -249,6 +270,7 @@ func Request(ctx context.Context, r *http.Request, body []byte) {
|
|||||||
Msg("HTTP Request")
|
Msg("HTTP Request")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addCtx adds context values to the log event based on configured context keys.
|
||||||
func addCtx(ctx context.Context, event *zerolog.Event) {
|
func addCtx(ctx context.Context, event *zerolog.Event) {
|
||||||
for _, key := range cfg.ContextKeys {
|
for _, key := range cfg.ContextKeys {
|
||||||
val, ok := ctx.Value(key).(string)
|
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) {
|
func Response(ctx context.Context, r *http.Request, statusCode int, responseTime time.Duration) {
|
||||||
event := logger.Info()
|
event := logger.Info()
|
||||||
addCtx(ctx, event)
|
addCtx(ctx, event)
|
||||||
|
|||||||
@@ -40,14 +40,20 @@ const (
|
|||||||
|
|
||||||
type contextKey string
|
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")
|
const MsgIDKey = contextKey("message_id")
|
||||||
|
|
||||||
|
// Role defines the type of participant in the network.
|
||||||
type Role string
|
type Role string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RoleBAP Role = "bap"
|
// RoleBAP represents a Buyer App Participant (BAP) in the network.
|
||||||
RoleBPP Role = "bpp"
|
RoleBAP Role = "bap"
|
||||||
RoleGateway Role = "gateway"
|
// 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"
|
RoleRegistery Role = "registery"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -91,22 +97,32 @@ type StepContext struct {
|
|||||||
RespHeader http.Header
|
RespHeader http.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithContext updates the existing StepContext with a new context.
|
||||||
func (ctx *StepContext) WithContext(newCtx context.Context) {
|
func (ctx *StepContext) WithContext(newCtx context.Context) {
|
||||||
ctx.Context = newCtx
|
ctx.Context = newCtx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Status represents the acknowledgment status in a response.
|
||||||
type Status string
|
type Status string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
StatusACK Status = "ACK"
|
// StatusACK indicates a successful acknowledgment.
|
||||||
|
StatusACK Status = "ACK"
|
||||||
|
// StatusNACK indicates a negative acknowledgment or failure.
|
||||||
StatusNACK Status = "NACK"
|
StatusNACK Status = "NACK"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Ack represents an acknowledgment response.
|
||||||
type Ack struct {
|
type Ack struct {
|
||||||
|
// Status holds the acknowledgment status (ACK/NACK).
|
||||||
Status Status `json:"status"`
|
Status Status `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Message represents the structure of a response message.
|
||||||
type Message struct {
|
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"`
|
Error *Error `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
definition "github.com/beckn/beckn-onix/pkg/plugin/definition"
|
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.
|
// schemaValidatorProvider provides instances of schemaValidator.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package schemaValidator
|
package schemavalidator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package schemaValidator
|
package schemavalidator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|||||||
@@ -149,8 +149,15 @@ func (m *Manager) Router(ctx context.Context, cfg *Config) (definition.Router, e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to load provider for %s: %w", cfg.ID, err)
|
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) {
|
func (m *Manager) Middleware(ctx context.Context, cfg *Config) (func(http.Handler) http.Handler, error) {
|
||||||
|
|||||||
@@ -12,10 +12,16 @@ import (
|
|||||||
"github.com/beckn/beckn-onix/pkg/model"
|
"github.com/beckn/beckn-onix/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Error represents a standardized error response used across the system.
|
||||||
type Error struct {
|
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"`
|
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.
|
// SchemaValidationErr represents a collection of schema validation failures.
|
||||||
@@ -32,13 +38,18 @@ func (e *SchemaValidationErr) Error() string {
|
|||||||
return strings.Join(errorMessages, "; ")
|
return strings.Join(errorMessages, "; ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Message represents a standard message structure with acknowledgment and error information.
|
||||||
type Message struct {
|
type Message struct {
|
||||||
|
// Ack contains the acknowledgment status of the response.
|
||||||
Ack struct {
|
Ack struct {
|
||||||
Status string `json:"status,omitempty"`
|
Status string `json:"status,omitempty"`
|
||||||
} `json:"ack,omitempty"`
|
} `json:"ack,omitempty"`
|
||||||
|
|
||||||
|
// Error holds error details if any occurred during processing.
|
||||||
Error *Error `json:"error,omitempty"`
|
Error *Error `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendAck sends an acknowledgment response (ACK) to the client.
|
||||||
func SendAck(w http.ResponseWriter) {
|
func SendAck(w http.ResponseWriter) {
|
||||||
resp := &model.Response{
|
resp := &model.Response{
|
||||||
Message: model.Message{
|
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{
|
resp := &model.Response{
|
||||||
Message: model.Message{
|
Message: model.Message{
|
||||||
Ack: model.Ack{
|
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 {
|
func internalServerError(ctx context.Context) *model.Error {
|
||||||
return &model.Error{
|
return &model.Error{
|
||||||
Code: http.StatusText(http.StatusInternalServerError),
|
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) {
|
func SendNack(ctx context.Context, w http.ResponseWriter, err error) {
|
||||||
var schemaErr *model.SchemaValidationErr
|
var schemaErr *model.SchemaValidationErr
|
||||||
var signErr *model.SignValidationErr
|
var signErr *model.SignValidationErr
|
||||||
@@ -95,19 +109,19 @@ func SendNack(ctx context.Context, w http.ResponseWriter, err error) {
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case errors.As(err, &schemaErr):
|
case errors.As(err, &schemaErr):
|
||||||
nack(w, schemaErr.BecknError(), http.StatusBadRequest, ctx)
|
nack(ctx, w, schemaErr.BecknError(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
case errors.As(err, &signErr):
|
case errors.As(err, &signErr):
|
||||||
nack(w, signErr.BecknError(), http.StatusUnauthorized, ctx)
|
nack(ctx, w, signErr.BecknError(), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
case errors.As(err, &badReqErr):
|
case errors.As(err, &badReqErr):
|
||||||
nack(w, badReqErr.BecknError(), http.StatusBadRequest, ctx)
|
nack(ctx, w, badReqErr.BecknError(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
case errors.As(err, ¬FoundErr):
|
case errors.As(err, ¬FoundErr):
|
||||||
nack(w, notFoundErr.BecknError(), http.StatusNotFound, ctx)
|
nack(ctx, w, notFoundErr.BecknError(), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
nack(w, internalServerError(ctx), http.StatusInternalServerError, ctx)
|
nack(ctx, w, internalServerError(ctx), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ func TestNack_1(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nack(w, tt.err, tt.status, ctx)
|
nack(ctx, w, tt.err, tt.status)
|
||||||
if !tt.useBadWrite {
|
if !tt.useBadWrite {
|
||||||
recorder, ok := w.(*httptest.ResponseRecorder)
|
recorder, ok := w.(*httptest.ResponseRecorder)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|||||||
Reference in New Issue
Block a user