fix: add compatibility logic for empty array when unmarshal json string to route (#374)
diff --git a/pkg/apisix/resource_test.go b/pkg/apisix/resource_test.go
index 51ea1eb..fe98958 100644
--- a/pkg/apisix/resource_test.go
+++ b/pkg/apisix/resource_test.go
@@ -18,6 +18,7 @@
"encoding/json"
"testing"
+ v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
"github.com/stretchr/testify/assert"
)
@@ -74,3 +75,24 @@
assert.Equal(t, r.Methods[1], "POST")
assert.Equal(t, r.Name, "unknown")
}
+
+func TestRouteVarsUnmarshalJSONCompatibility(t *testing.T) {
+ var route v1.Route
+ data := `{"vars":{}}`
+ err := json.Unmarshal([]byte(data), &route)
+ assert.Nil(t, err)
+
+ data = `{"vars":{"a":"b"}}`
+ err = json.Unmarshal([]byte(data), &route)
+ assert.Equal(t, err.Error(), "unexpected non-empty object")
+
+ data = `{"vars":[]}`
+ err = json.Unmarshal([]byte(data), &route)
+ assert.Nil(t, err)
+
+ data = `{"vars":[["http_a","==","b"]]}`
+ err = json.Unmarshal([]byte(data), &route)
+ assert.Equal(t, "http_a", route.Vars[0][0].StrVal)
+ assert.Equal(t, "==", route.Vars[0][1].StrVal)
+ assert.Equal(t, "b", route.Vars[0][2].StrVal)
+}
diff --git a/pkg/apisix/route.go b/pkg/apisix/route.go
index 21561c1..c724e79 100644
--- a/pkg/apisix/route.go
+++ b/pkg/apisix/route.go
@@ -92,6 +92,7 @@
log.Errorw("failed to convert route item",
zap.String("url", r.url),
zap.String("route_key", resp.Item.Key),
+ zap.String("route_value", string(resp.Item.Value)),
zap.Error(err),
)
return nil, err
@@ -124,6 +125,7 @@
log.Errorw("failed to convert route item",
zap.String("url", r.url),
zap.String("route_key", item.Key),
+ zap.String("route_value", string(item.Value)),
zap.Error(err),
)
return nil, err
diff --git a/pkg/types/apisix/v1/types.go b/pkg/types/apisix/v1/types.go
index ec4cf2e..b660d3b 100644
--- a/pkg/types/apisix/v1/types.go
+++ b/pkg/types/apisix/v1/types.go
@@ -82,16 +82,38 @@
type Route struct {
Metadata `json:",inline" yaml:",inline"`
- Host string `json:"host,omitempty" yaml:"host,omitempty"`
- Hosts []string `json:"hosts,omitempty" yaml:"hosts,omitempty"`
- Uri string `json:"uri,omitempty" yaml:"uri,omitempty"`
- Priority int `json:"priority,omitempty" yaml:"priority,omitempty"`
- Vars [][]StringOrSlice `json:"vars,omitempty" yaml:"vars,omitempty"`
- Uris []string `json:"uris,omitempty" yaml:"uris,omitempty"`
- Methods []string `json:"methods,omitempty" yaml:"methods,omitempty"`
- RemoteAddrs []string `json:"remote_addrs,omitempty" yaml:"remote_addrs,omitempty"`
- UpstreamId string `json:"upstream_id,omitempty" yaml:"upstream_id,omitempty"`
- Plugins Plugins `json:"plugins,omitempty" yaml:"plugins,omitempty"`
+ Host string `json:"host,omitempty" yaml:"host,omitempty"`
+ Hosts []string `json:"hosts,omitempty" yaml:"hosts,omitempty"`
+ Uri string `json:"uri,omitempty" yaml:"uri,omitempty"`
+ Priority int `json:"priority,omitempty" yaml:"priority,omitempty"`
+ Vars Vars `json:"vars,omitempty" yaml:"vars,omitempty"`
+ Uris []string `json:"uris,omitempty" yaml:"uris,omitempty"`
+ Methods []string `json:"methods,omitempty" yaml:"methods,omitempty"`
+ RemoteAddrs []string `json:"remote_addrs,omitempty" yaml:"remote_addrs,omitempty"`
+ UpstreamId string `json:"upstream_id,omitempty" yaml:"upstream_id,omitempty"`
+ Plugins Plugins `json:"plugins,omitempty" yaml:"plugins,omitempty"`
+}
+
+// Vars represents the route match expressions of APISIX.
+type Vars [][]StringOrSlice
+
+// UnmarshalJSON implements json.Unmarshaler interface.
+// lua-cjson doesn't distinguish empty array and table,
+// and by default empty array will be encoded as '{}'.
+// We have to maintain the compatibility.
+func (vars *Vars) UnmarshalJSON(p []byte) error {
+ if p[0] == '{' {
+ if len(p) != 2 {
+ return errors.New("unexpected non-empty object")
+ }
+ return nil
+ }
+ var data [][]StringOrSlice
+ if err := json.Unmarshal(p, &data); err != nil {
+ return err
+ }
+ *vars = data
+ return nil
}
// StringOrSlice represents a string or a string slice.