From 5aa58102fa4a2a89cbb04bd9a487c80cbbec9a5d Mon Sep 17 00:00:00 2001 From: Tom Petr Date: Wed, 27 Sep 2023 16:21:51 -0400 Subject: [PATCH 1/3] add the ability to specify additonal fallback relay configs --- pkg/config.go | 11 ++++++----- pkg/relay.go | 8 ++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pkg/config.go b/pkg/config.go index bf2b62e..74f3762 100644 --- a/pkg/config.go +++ b/pkg/config.go @@ -216,11 +216,12 @@ type InboundProxyConfig struct { } type FilteredRelayConfig struct { - DestinationURL string `mapstructure:"destinationUrl"` - JSONPath string `mapstructure:"jsonPath"` - Contains []string `mapstructure:"contains"` - Equals []string `mapstructure:"equals"` - HasPrefix []string `mapstructure:"hasPrefix"` + DestinationURL string `mapstructure:"destinationUrl"` + JSONPath string `mapstructure:"jsonPath"` + Contains []string `mapstructure:"contains"` + Equals []string `mapstructure:"equals"` + HasPrefix []string `mapstructure:"hasPrefix"` + AdditionalConfigs []FilteredRelayConfig `mapstructure:"additionalConfigs"` // this is awful, but we can refactor this in the near future } type OutboundProxyConfig struct { diff --git a/pkg/relay.go b/pkg/relay.go index 7f536d1..26c0960 100644 --- a/pkg/relay.go +++ b/pkg/relay.go @@ -67,6 +67,14 @@ func (config *FilteredRelayConfig) Matches(value map[string]interface{}) (bool, return true, nil } } + + for i := range config.AdditionalConfigs { + inner_match, inner_err := config.AdditionalConfigs[i].Matches(value) + if inner_match || inner_err != nil { + return inner_match, inner_err + } + } + return false, nil } From 76abee89c038c55ddaf6024c4ff629eb6dfb881e Mon Sep 17 00:00:00 2001 From: Tom Petr Date: Fri, 29 Sep 2023 15:20:53 -0400 Subject: [PATCH 2/3] docs --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index b7c7793..ff03a65 100644 --- a/README.md +++ b/README.md @@ -226,3 +226,20 @@ outbound: would result in requests addressed to http://localhost:8080/relay/test being relayed to https://httpbin.org/anything as long as the result of the jsonpath query `$.foo` executed on the request body results in the string `bar`. Check out an example [here](./examples/github-pr-comment-relay.yaml) for how to use the relay for GitHub PR comments. + +You can also define additional relay mappings via the `additionalConfigs` field: + +```yaml +outbound: + listenPort: 8080 + relay: + test: + destinationUrl: https://httpbin.org/anything + jsonPath: "$.foo" + equals: + - bar + additionalConfigs: + - destinationUrl: htttps://example.com/fallback +``` + +The example above would relay traffic to https://httpbin.org/anything if the request body contains `{"foo": "bar"}`, otherwise, it'd relay traffic to `htttps://example.com/fallback`. \ No newline at end of file From 25704a5da5555ebe8a3bc7a298b8a58f268b0770 Mon Sep 17 00:00:00 2001 From: Tom Petr Date: Fri, 29 Sep 2023 15:36:26 -0400 Subject: [PATCH 3/3] fix --- pkg/relay.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/relay.go b/pkg/relay.go index 26c0960..365b1bf 100644 --- a/pkg/relay.go +++ b/pkg/relay.go @@ -32,50 +32,50 @@ func GetRequestBodyJSON(body io.Reader) (map[string]interface{}, error) { return value, nil } -func (config *FilteredRelayConfig) Matches(value map[string]interface{}) (bool, error) { +func (config *FilteredRelayConfig) FindMatch(value map[string]interface{}) (*FilteredRelayConfig, bool, error) { if config.JSONPath == "" { - return true, nil + return config, true, nil } result, err := jsonpath.Get(config.JSONPath, value) if err != nil { if strings.HasPrefix(err.Error(), "unknown key ") { - return false, nil + return config, false, nil } - return false, fmt.Errorf("error evaluating jsonpath: %v", err) + return config, false, fmt.Errorf("error evaluating jsonpath: %v", err) } if reflect.TypeOf(result).Kind() != reflect.String { - return false, fmt.Errorf("jsonpath result is not a string") + return config, false, fmt.Errorf("jsonpath result is not a string") } resultStr := result.(string) for _, val := range config.Equals { if resultStr == val { - return true, nil + return config, true, nil } } for _, val := range config.HasPrefix { if strings.HasPrefix(resultStr, val) { - return true, nil + return config, true, nil } } for _, val := range config.Contains { if strings.Contains(resultStr, val) { - return true, nil + return config, true, nil } } for i := range config.AdditionalConfigs { - inner_match, inner_err := config.AdditionalConfigs[i].Matches(value) + inner_config, inner_match, inner_err := config.AdditionalConfigs[i].FindMatch(value) if inner_match || inner_err != nil { - return inner_match, inner_err + return inner_config, inner_match, inner_err } } - return false, nil + return config, false, nil } func (config *OutboundProxyConfig) Start() error { @@ -128,7 +128,7 @@ func (config *OutboundProxyConfig) Start() error { logger.WithError(err).Warn("relay.parse_json") } - match, err := relayConfig.Matches(obj) + config, match, err := relayConfig.FindMatch(obj) if err != nil { logger.WithError(err).Info("relay.match_err") c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("matching error: %v", err)}) @@ -141,9 +141,9 @@ func (config *OutboundProxyConfig) Start() error { return } - logger = logger.WithField("destinationUrl", relayConfig.DestinationURL) + logger = logger.WithField("destinationUrl", config.DestinationURL) - destinationUrl, err := url.Parse(relayConfig.DestinationURL) // TODO: precompute this + destinationUrl, err := url.Parse(config.DestinationURL) // TODO: precompute this if err != nil { logger.WithError(err).Warn("relay.destination_url_parse") c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("url parser error: %v", err)})