Repository: cloudflare/cloudflare-go
Pull request #994 (2022-07-18 08:12:57)

Add dynamic redirect phase support for rulesets
Added extension of redirect action and the dynamic redirect phase in rulesets API

## Description

Added support of the new phase and redirect action extended to be used in that phase

## Has your change been tested?

Added unit-test

codecov-commenter: # [Codecov](https://codecov.io/gh/cloudflare/cloudflare-go/pull/994?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) Report
> Merging [#994](https://codecov.io/gh/cloudflare/cloudflare-go/pull/994?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) (6023ab8) into [master](https://codecov.io/gh/cloudflare/cloudflare-go/commit/bcdf39d32b8cbe715b3a99246fc9470a8a251ef9?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) (bcdf39d) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##           master     #994   +/-   ##
=======================================
  Coverage   48.94%   48.94%           
=======================================
  Files         108      108           
  Lines       10384    10384           
=======================================
  Hits         5082     5082           
  Misses       4194     4194           
  Partials     1108     1108           
```


| [Impacted Files](https://codecov.io/gh/cloudflare/cloudflare-go/pull/994?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare) | Coverage Δ | |
|---|---|---|
| [rulesets.go](https://codecov.io/gh/cloudflare/cloudflare-go/pull/994/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare#diff-cnVsZXNldHMuZ28=) | `28.10% <ø> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/cloudflare/cloudflare-go/pull/994?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/cloudflare/cloudflare-go/pull/994?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare). Last update [bcdf39d...6023ab8](https://codecov.io/gh/cloudflare/cloudflare-go/pull/994?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=cloudflare).


Patch:
diff --git a/rulesets.go b/rulesets.go
index aff7e5617..00d46cc77 100644
--- a/rulesets.go
+++ b/rulesets.go
@@ -27,6 +27,7 @@ const (
 	RulesetPhaseHTTPRequestLateTransformManaged     RulesetPhase = "http_request_late_transform_managed"
 	RulesetPhaseHTTPRequestMain                     RulesetPhase = "http_request_main"
 	RulesetPhaseHTTPRequestOrigin                   RulesetPhase = "http_request_origin"
+	RulesetPhaseHTTPRequestDynamicRedirect          RulesetPhase = "http_request_dynamic_redirect"
 	RulesetPhaseHTTPRequestRedirect                 RulesetPhase = "http_request_redirect"
 	RulesetPhaseHTTPRequestSanitize                 RulesetPhase = "http_request_sanitize"
 	RulesetPhaseHTTPRequestTransform                RulesetPhase = "http_request_transform"
@@ -91,6 +92,7 @@ func RulesetPhaseValues() []string {
 		string(RulesetPhaseHTTPRequestLateTransformManaged),
 		string(RulesetPhaseHTTPRequestMain),
 		string(RulesetPhaseHTTPRequestOrigin),
+		string(RulesetPhaseHTTPRequestDynamicRedirect),
 		string(RulesetPhaseHTTPRequestRedirect),
 		string(RulesetPhaseHTTPRequestSanitize),
 		string(RulesetPhaseHTTPRequestTransform),
@@ -218,6 +220,7 @@ type RulesetRuleActionParameters struct {
 	CacheKey                *RulesetRuleActionParametersCacheKey             `json:"cache_key,omitempty"`
 	OriginErrorPagePassthru *bool                                            `json:"origin_error_page_passthru,omitempty"`
 	FromList                *RulesetRuleActionParametersFromList             `json:"from_list,omitempty"`
+	FromValue               *RulesetRuleActionParametersFromValue            `json:"from_value,omitempty"`
 }
 
 // RulesetRuleActionParametersFromList holds the FromList struct for
@@ -227,6 +230,17 @@ type RulesetRuleActionParametersFromList struct {
 	Key  string `json:"key"`
 }
 
+type RulesetRuleActionParametersFromValue struct {
+	StatusCode          uint16                               `json:"status_code,omitempty"`
+	TargetURL           RulesetRuleActionParametersTargetURL `json:"target_url"`
+	PreserveQueryString bool                                 `json:"preserve_query_string,omitempty"`
+}
+
+type RulesetRuleActionParametersTargetURL struct {
+	Value      string `json:"value,omitempty"`
+	Expression string `json:"expression,omitempty"`
+}
+
 type RulesetRuleActionParametersEdgeTTL struct {
 	Mode          string                                     `json:"mode,omitempty"`
 	Default       *uint                                      `json:"default,omitempty"`


Test patch:
diff --git a/rulesets_test.go b/rulesets_test.go
index 498625e57..a2c841a55 100644
--- a/rulesets_test.go
+++ b/rulesets_test.go
@@ -354,6 +354,95 @@ func TestGetRuleset_SetCacheSettings(t *testing.T) {
 	}
 }
 
+func TestGetRuleset_RedirectFromValue(t *testing.T) {
+	setup()
+	defer teardown()
+
+	handler := func(w http.ResponseWriter, r *http.Request) {
+		assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method)
+		w.Header().Set("content-type", "application/json")
+		fmt.Fprint(w, `{
+      "result": {
+        "id": "70339d97bdb34195bbf054b1ebe81f76",
+        "name": "Cloudflare Redirect Rules Ruleset",
+        "description": "This ruleset provides redirect from value",
+        "kind": "zone",
+        "version": "1",
+        "rules": [
+          {
+            "id": "78723a9e0c7c4c6dbec5684cb766231d",
+            "version": "1",
+            "action": "redirect",
+            "action_parameters": {
+				"from_value": {
+					"status_code": 301,
+					"target_url": {
+						"value": "some_host.com"
+					},
+					"preserve_query_string": true
+				}
+			},
+			"description": "Set dynamic redirect from value",
+			"last_updated": "2020-12-18T09:28:09.655749Z",
+			"ref": "272936dc447b41fe976255ff6b768ec0",
+			"enabled": true
+          }
+        ],
+        "last_updated": "2020-12-18T09:28:09.655749Z",
+        "phase": "http_request_dynamic_redirect"
+      },
+      "success": true,
+      "errors": [],
+      "messages": []
+    }`)
+	}
+
+	mux.HandleFunc("/accounts/"+testAccountID+"/rulesets/b232b534beea4e00a21dcbb7a8a545e9", handler)
+	mux.HandleFunc("/zones/"+testZoneID+"/rulesets/b232b534beea4e00a21dcbb7a8a545e9", handler)
+
+	lastUpdated, _ := time.Parse(time.RFC3339, "2020-12-18T09:28:09.655749Z")
+
+	rules := []RulesetRule{{
+		ID:      "78723a9e0c7c4c6dbec5684cb766231d",
+		Version: "1",
+		Action:  string(RulesetRuleActionRedirect),
+		ActionParameters: &RulesetRuleActionParameters{
+			FromValue: &RulesetRuleActionParametersFromValue{
+				StatusCode: 301,
+				TargetURL: RulesetRuleActionParametersTargetURL{
+					Value: "some_host.com",
+				},
+				PreserveQueryString: true,
+			},
+		},
+		Description: "Set dynamic redirect from value",
+		LastUpdated: &lastUpdated,
+		Ref:         "272936dc447b41fe976255ff6b768ec0",
+		Enabled:     true,
+	}}
+
+	want := Ruleset{
+		ID:          "70339d97bdb34195bbf054b1ebe81f76",
+		Name:        "Cloudflare Redirect Rules Ruleset",
+		Description: "This ruleset provides redirect from value",
+		Kind:        string(RulesetKindZone),
+		Version:     "1",
+		LastUpdated: &lastUpdated,
+		Phase:       string(RulesetPhaseHTTPRequestDynamicRedirect),
+		Rules:       rules,
+	}
+
+	zoneActual, err := client.GetZoneRuleset(context.Background(), testZoneID, "b232b534beea4e00a21dcbb7a8a545e9")
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, zoneActual)
+	}
+
+	accountActual, err := client.GetAccountRuleset(context.Background(), testAccountID, "b232b534beea4e00a21dcbb7a8a545e9")
+	if assert.NoError(t, err) {
+		assert.Equal(t, want, accountActual)
+	}
+}
+
 func TestCreateRuleset(t *testing.T) {
 	setup()
 	defer teardown()