From c1880a303bc4980d399c00b71214be27629982ea Mon Sep 17 00:00:00 2001 From: williamfeng323 Date: Thu, 20 May 2021 13:05:20 +0800 Subject: [PATCH] =?UTF-8?q?moving=20param=20types=20into=20parameter=20con?= =?UTF-8?q?figuration=20instead=20of=20standalone=E2=80=A6=20(#161)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * moving param types into parameter configuration instead of standalone config * remve replace path filter Signed-off-by: william feng * fix reviewdog comment --- docs/sample/dubbo-body.md | 7 +- docs/sample/dubbo-mix.md | 9 +- docs/sample/dubbo-multi.md | 10 +- docs/sample/dubbo-query.md | 7 +- docs/sample/dubbo-universality.md | 63 ++-- docs/sample/dubbo-uri.md | 7 +- docs/sample/zh-cn/dubbo-body.md | 7 +- docs/sample/zh-cn/dubbo-mix.md | 9 +- docs/sample/zh-cn/dubbo-multi.md | 10 +- docs/sample/zh-cn/dubbo-query.md | 24 +- docs/sample/zh-cn/dubbo-universality.md | 56 +--- docs/sample/zh-cn/dubbo-uri.md | 7 +- go.mod | 4 +- go.sum | 14 +- pkg/client/client.go | 30 +- pkg/client/dubbo/dubbo.go | 39 +-- pkg/client/dubbo/dubbo_test.go | 119 ++++---- pkg/client/dubbo/mapper.go | 162 +++++----- pkg/client/dubbo/mapper_test.go | 287 ++++++++++++------ pkg/client/dubbo/option.go | 192 ++++++++---- pkg/client/dubbo/option_test.go | 97 ++++++ pkg/client/http/http_test.go | 14 +- pkg/client/http/mapper.go | 16 +- pkg/client/http/mapper_test.go | 22 ++ pkg/common/constant/jtypes.go | 6 +- pkg/filter/replacepath/replace_path.go | 79 ----- pkg/filter/replacepath/replace_place_test.go | 43 --- pkg/pixiu/listener.go | 4 - samples/admin/proxy/api_config.yaml | 44 +-- .../dubbogo/multi/apiconfig/api_config.yaml | 10 +- samples/dubbogo/simple/body/api_config.yaml | 9 +- samples/dubbogo/simple/mix/api_config.yaml | 9 +- samples/dubbogo/simple/proxy/api_config.yaml | 38 +-- samples/dubbogo/simple/query/api_config.yaml | 7 +- samples/dubbogo/simple/uri/api_config.yaml | 7 +- 35 files changed, 771 insertions(+), 697 deletions(-) create mode 100644 pkg/client/dubbo/option_test.go delete mode 100644 pkg/filter/replacepath/replace_path.go delete mode 100644 pkg/filter/replacepath/replace_place_test.go diff --git a/docs/sample/dubbo-body.md b/docs/sample/dubbo-body.md index 7422decf4..8d81420dc 100644 --- a/docs/sample/dubbo-body.md +++ b/docs/sample/dubbo-body.md @@ -24,10 +24,10 @@ resources: mappingParams: - name: requestBody._all mapTo: 0 + mapType: "object" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "CreateUser" - paramTypes: [ "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -41,10 +41,10 @@ resources: mappingParams: - name: requestBody._all mapTo: 0 + mapType: "object" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUser" - paramTypes: [ "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -62,12 +62,13 @@ resources: mappingParams: - name: requestBody.name mapTo: 0 + mapType: "string" - name: requestBody.user mapTo: 1 + mapType: "object" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/dubbo-mix.md b/docs/sample/dubbo-mix.md index da7e9ae4c..b4b41195b 100644 --- a/docs/sample/dubbo-mix.md +++ b/docs/sample/dubbo-mix.md @@ -24,12 +24,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: queryStrings.age mapTo: 1 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "string", "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -43,12 +44,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -66,12 +68,13 @@ resources: mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/dubbo-multi.md b/docs/sample/dubbo-multi.md index de9c63815..e7a6ed879 100644 --- a/docs/sample/dubbo-multi.md +++ b/docs/sample/dubbo-multi.md @@ -26,10 +26,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "StudentService" interface: "com.dubbogo.pixiu.StudentService" method: "GetStudentByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -43,12 +43,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "StudentService" interface: "com.dubbogo.pixiu.StudentService" method: "UpdateStudentByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -68,10 +69,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "TeacherService" interface: "com.dubbogo.pixiu.TeacherService" method: "GetTeacherByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -85,12 +86,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "TeacherService" interface: "com.dubbogo.pixiu.TeacherService" method: "UpdateTeacherByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/dubbo-query.md b/docs/sample/dubbo-query.md index 245ececcc..52b7542a9 100644 --- a/docs/sample/dubbo-query.md +++ b/docs/sample/dubbo-query.md @@ -24,10 +24,10 @@ resources: mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -45,12 +45,13 @@ resources: mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" - name: queryStrings.age mapTo: 1 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "string","int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -68,10 +69,10 @@ resources: mappingParams: - name: queryStrings.code mapTo: 0 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByCode" - paramTypes: [ "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/dubbo-universality.md b/docs/sample/dubbo-universality.md index ce726bbbf..cce080c76 100644 --- a/docs/sample/dubbo-universality.md +++ b/docs/sample/dubbo-universality.md @@ -25,44 +25,20 @@ resources: requestType: dubbo mappingParams: - name: requestBody.values - mapTo: 0 - opt: - open: true - usable: true - name: values + mapTo: opt.values - name: requestBody.types - mapTo: 1 - opt: - open: true - name: types + mapTo: opt.types - name: uri.application - mapTo: 2 - opt: - open: true - name: application + mapTo: opt.application - name: uri.interface - mapTo: 3 - opt: - open: true - name: interface + mapTo: opt.interface - name: queryStrings.method - mapTo: 4 - opt: - open: true - name: method + mapTo: opt.method - name: queryStrings.group - mapTo: 5 - opt: - open: true - name: group + mapTo: opt.group - name: queryStrings.version - mapTo: 6 - opt: - open: true - name: version - paramTypes: ["object", "object", "string", "string", "string", "string", "string"] + mapTo: opt.version # Notice: this is the really paramTypes to dubbo service, it takes precedence over paramTypes when it is finally called. - toParamTypes: ["string"] clusterName: "test_dubbo" ``` @@ -134,7 +110,7 @@ const ( #### Options -Assemble generic params to invoke. +By configuring mapTo with option keywords(listed below), Pixiu will assemble generic params to invoke. ```go // GenericService uses for generic invoke for service call @@ -144,33 +120,33 @@ type GenericService struct { } ``` -- types +- opt.types > dubbo generic types Use for dubbogo `GenericService#Invoke` func arg 2rd param. -- method +- opt.method Use for dubbogo `GenericService#Invoke` func arg 1rd param. -- group +- opt.group Dubbo group in `ReferenceConfig#Group`. -- version +- opt.version Dubbo version in `ReferenceConfig#Version`. -- interface +- opt.interface Dubbo interface in `ReferenceConfig#InterfaceName`. -- application +- opt.application Now only use for part of cache key. -- values +- opt.values Use for dubbogo `GenericService#Invoke` func arg 3rd param. @@ -191,16 +167,11 @@ request body ```yaml - name: requestBody.types - mapTo: 1 - opt: - open: true - name: types + mapTo: opt.types ``` - `requestBody.types` means body content with types key. -- `opt.name` means use types option. -- `opt.open` must `true` will create opt,may be deleted in the future for thin provisioning。 -- `opt.usable` means if remove the request to downstream service. +- `opt.types` means use types option. ##### Multiple params diff --git a/docs/sample/dubbo-uri.md b/docs/sample/dubbo-uri.md index 932335db6..de7988f96 100644 --- a/docs/sample/dubbo-uri.md +++ b/docs/sample/dubbo-uri.md @@ -27,10 +27,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -51,10 +51,10 @@ resources: mappingParams: - name: uri.code mapTo: 0 + mapType: "int" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByCode" - paramTypes: [ "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -77,12 +77,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: uri.age mapTo: 1 + mapType: "int" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "string", "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/zh-cn/dubbo-body.md b/docs/sample/zh-cn/dubbo-body.md index f9cfff3ca..e0f374514 100644 --- a/docs/sample/zh-cn/dubbo-body.md +++ b/docs/sample/zh-cn/dubbo-body.md @@ -24,10 +24,10 @@ resources: mappingParams: - name: requestBody._all mapTo: 0 + mapType: "object" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "CreateUser" - paramTypes: [ "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -41,10 +41,10 @@ resources: mappingParams: - name: requestBody._all mapTo: 0 + mapType: "object" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUser" - paramTypes: [ "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -62,12 +62,13 @@ resources: mappingParams: - name: requestBody.name mapTo: 0 + mapType: "string" - name: requestBody.user mapTo: 1 + mapType: "object" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/zh-cn/dubbo-mix.md b/docs/sample/zh-cn/dubbo-mix.md index 6ed0f5fd7..cce31cb07 100644 --- a/docs/sample/zh-cn/dubbo-mix.md +++ b/docs/sample/zh-cn/dubbo-mix.md @@ -24,12 +24,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: queryStrings.age mapTo: 1 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "string", "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -43,12 +44,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -66,12 +68,13 @@ resources: mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/zh-cn/dubbo-multi.md b/docs/sample/zh-cn/dubbo-multi.md index ef53e1137..416e6ac54 100644 --- a/docs/sample/zh-cn/dubbo-multi.md +++ b/docs/sample/zh-cn/dubbo-multi.md @@ -26,10 +26,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "StudentService" interface: "com.dubbogo.pixiu.StudentService" method: "GetStudentByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -43,12 +43,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "StudentService" interface: "com.dubbogo.pixiu.StudentService" method: "UpdateStudentByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -68,10 +69,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "TeacherService" interface: "com.dubbogo.pixiu.TeacherService" method: "GetTeacherByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -85,12 +86,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "TeacherService" interface: "com.dubbogo.pixiu.TeacherService" method: "UpdateTeacherByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/zh-cn/dubbo-query.md b/docs/sample/zh-cn/dubbo-query.md index f9b542549..c3263bfe5 100644 --- a/docs/sample/zh-cn/dubbo-query.md +++ b/docs/sample/zh-cn/dubbo-query.md @@ -13,82 +13,66 @@ resources: - path: '/api/v1/test-dubbo/userByName' type: restful description: user - filters: - - filter0 methods: - httpVerb: GET onAir: true timeout: 1000ms inboundRequest: requestType: http - queryStrings: - - name: name - required: true integrationRequest: requestType: dubbo mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByName" - paramTypes: [ "java.lang.String" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" - path: '/api/v1/test-dubbo/userByNameAndAge' type: restful description: user - filters: - - filter0 methods: - httpVerb: GET onAir: true timeout: 1000ms inboundRequest: requestType: http - queryStrings: - - name: name - required: true - - name: age - required: true integrationRequest: requestType: dubbo mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" - name: queryStrings.age mapTo: 1 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "java.lang.String","java.lang.Integer" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" - path: '/api/v1/test-dubbo/userByCode' type: restful description: user - filters: - - filter0 methods: - httpVerb: GET onAir: true timeout: 1000ms inboundRequest: requestType: http - queryStrings: - - name: code - required: true integrationRequest: requestType: dubbo mappingParams: - name: queryStrings.code mapTo: 0 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByCode" - paramTypes: [ "java.lang.Integer" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/docs/sample/zh-cn/dubbo-universality.md b/docs/sample/zh-cn/dubbo-universality.md index f17e4044c..754c0acaa 100644 --- a/docs/sample/zh-cn/dubbo-universality.md +++ b/docs/sample/zh-cn/dubbo-universality.md @@ -25,44 +25,20 @@ resources: requestType: dubbo mappingParams: - name: requestBody.values - mapTo: 0 - opt: - open: true - usable: true - name: values + mapTo: opt.values - name: requestBody.types - mapTo: 1 - opt: - open: true - name: types + mapTo: opt.types - name: uri.application - mapTo: 2 - opt: - open: true - name: application + mapTo: opt.application - name: uri.interface - mapTo: 3 - opt: - open: true - name: interface + mapTo: opt.interface - name: queryStrings.method - mapTo: 4 - opt: - open: true - name: method + mapTo: opt.method - name: queryStrings.group - mapTo: 5 - opt: - open: true - name: group + mapTo: opt.group - name: queryStrings.version - mapTo: 6 - opt: - open: true - name: version - paramTypes: ["object", "object", "string", "string", "string", "string", "string"] - # 这个是必须注意的,实际传给 dubbo 的 paramTypes,在最终调用的时候优先级高于 paramTypes。 - toParamTypes: ["string"] + mapTo: opt.version + # Notice: this is the really paramTypes to dubbo service, it takes precedence over paramTypes when it is finally called. clusterName: "test_dubbo" ``` @@ -134,7 +110,7 @@ const ( #### 选择项 -组装泛化调用的参数 +在mapTo 里面使用特定的关键字(列表如下),貔貅可以自动组装泛化调用的参数 ```go // GenericService uses for generic invoke for service call @@ -144,33 +120,33 @@ type GenericService struct { } ``` -- types +- opt.types > dubbo 泛化类型 用于 dubbogo `GenericService#Invoke` 函数的第二个参数。 -- method +- opt.method 用于 dubbogo `GenericService#Invoke` 函数的第一个参数。 -- group +- opt.group Dubbo 组配置 `ReferenceConfig#Group`。 -- version +- opt.version Dubbo 版本配置 `ReferenceConfig#Version`。 -- interface +- opt.interface Dubbo 接口配置 `ReferenceConfig#InterfaceName`。 -- application +- opt.application 目前暂时用于缓存,索引的一部分查找对应的缓存对象。 -- values +- opt.values 值的处理,用于 `GenericService#Invoke` 函数的第三个参数。 diff --git a/docs/sample/zh-cn/dubbo-uri.md b/docs/sample/zh-cn/dubbo-uri.md index ba3444976..b0f0f6f96 100644 --- a/docs/sample/zh-cn/dubbo-uri.md +++ b/docs/sample/zh-cn/dubbo-uri.md @@ -27,10 +27,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -51,10 +51,10 @@ resources: mappingParams: - name: uri.code mapTo: 0 + mapType: "int" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByCode" - paramTypes: [ "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -77,12 +77,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: uri.age mapTo: 1 + mapType: "int" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "string", "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/go.mod b/go.mod index ca0a8ca51..00bcf21a2 100644 --- a/go.mod +++ b/go.mod @@ -6,15 +6,17 @@ require ( github.com/apache/dubbo-go v1.5.5 github.com/apache/dubbo-go-hessian2 v1.7.0 github.com/coreos/etcd v3.3.25+incompatible - github.com/dubbogo/dubbo-go-pixiu-filter v0.1.3 + github.com/dubbogo/dubbo-go-pixiu-filter v0.1.4-0.20210427062645-0bec837d429e github.com/dubbogo/go-zookeeper v1.0.2 github.com/emirpasic/gods v1.12.0 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/goinggo/mapstructure v0.0.0-20140717182941-194205d9b4a9 github.com/hashicorp/consul/api v1.5.0 github.com/pkg/errors v0.9.1 + github.com/shirou/gopsutil v3.21.3+incompatible // indirect github.com/spf13/cast v1.3.1 github.com/stretchr/testify v1.6.1 + github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/urfave/cli v1.22.4 go.uber.org/zap v1.16.0 google.golang.org/grpc v1.26.0 diff --git a/go.sum b/go.sum index b5bdb8712..c9fb8decd 100644 --- a/go.sum +++ b/go.sum @@ -230,8 +230,8 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/dubbogo/dubbo-go-pixiu-filter v0.1.3 h1:AkOubLd9pCYfX+94wux6Z2+OB9G0tGI/r5Q1uYA17ps= -github.com/dubbogo/dubbo-go-pixiu-filter v0.1.3/go.mod h1:d6SDK5BHl/QCvg84BN+g6LZS9QzVqnI2+yw0NBu0uac= +github.com/dubbogo/dubbo-go-pixiu-filter v0.1.4-0.20210427062645-0bec837d429e h1:0d1cHanEYqLu/WRwvTe4Y2zeCeeiimVqFKTL5QXAxAs= +github.com/dubbogo/dubbo-go-pixiu-filter v0.1.4-0.20210427062645-0bec837d429e/go.mod h1:d6SDK5BHl/QCvg84BN+g6LZS9QzVqnI2+yw0NBu0uac= github.com/dubbogo/go-zookeeper v1.0.2 h1:xmEnPL8SlCe3/+J5ZR9e8qE35LmFVYe8VVpDakjNM4A= github.com/dubbogo/go-zookeeper v1.0.2/go.mod h1:fn6n2CAEer3novYgk9ULLwAjuV8/g4DdC2ENwRb6E+c= github.com/dubbogo/gost v1.9.0/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8= @@ -852,8 +852,9 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shirou/gopsutil v0.0.0-20181107111621-48177ef5f880/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil v2.19.12+incompatible h1:WRstheAymn1WOPesh+24+bZKFkqrdCR8JOc77v4xV3Q= github.com/shirou/gopsutil v2.19.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.3+incompatible h1:uenXGGa8ESCQq+dbgtl916dmg6PSAz2cXov0uORQ9v8= +github.com/shirou/gopsutil v3.21.3+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= @@ -923,6 +924,10 @@ github.com/tevid/gohamcrest v1.1.1/go.mod h1:3UvtWlqm8j5JbwYZh80D/PVBt0mJ1eJiYgZ github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20200122045848-3419fae592fc h1:yUaosFVTJwnltaHbSNC3i82I92quFs+OFPRl8kNMVwo= @@ -1137,8 +1142,9 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa h1:ZYxPR6aca/uhfRJyaOAtflSHjJYiktO7QnJC5ut7iY4= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/pkg/client/client.go b/pkg/client/client.go index 53eed5df1..7f1b991c6 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -39,33 +39,5 @@ type MapOption map[string]RequestOption // RequestOption option interface. type RequestOption interface { - // Usable if option can use - Usable() bool - // SetUsable set usable - SetUsable(b bool) - // Action do with val for special - Action(req *Request, val interface{}) - // VirtualPos virtual position - VirtualPos() int -} - -// CommonOption common opt. -type CommonOption struct { - usable bool - RequestOption -} - -// Usable get usable. -func (opt *CommonOption) Usable() bool { - return opt.usable -} - -// SetUsable set usable. -func (opt *CommonOption) SetUsable(b bool) { - opt.usable = b -} - -// VirtualPos virtual position, default 0. -func (opt *CommonOption) VirtualPos() int { - return 0 + Action(target, val interface{}) error } diff --git a/pkg/client/dubbo/dubbo.go b/pkg/client/dubbo/dubbo.go index 49f93e3b6..64213a831 100644 --- a/pkg/client/dubbo/dubbo.go +++ b/pkg/client/dubbo/dubbo.go @@ -29,13 +29,13 @@ import ( dg "github.com/apache/dubbo-go/config" "github.com/apache/dubbo-go/protocol/dubbo" fc "github.com/dubbogo/dubbo-go-pixiu-filter/pkg/api/config" + "github.com/pkg/errors" ) import ( "github.com/apache/dubbo-go-pixiu/pkg/client" "github.com/apache/dubbo-go-pixiu/pkg/config" "github.com/apache/dubbo-go-pixiu/pkg/logger" - "github.com/pkg/errors" ) // TODO java class name elem @@ -140,7 +140,11 @@ func (dc *Client) Close() error { // Call invoke service func (dc *Client) Call(req *client.Request) (res interface{}, err error) { - types, values, err := dc.genericArgs(req) + values, err := dc.genericArgs(req) + val, ok := values.(*dubboTarget) + if !ok { + return nil, errors.New("map parameters failed") + } if err != nil { return nil, err } @@ -148,11 +152,11 @@ func (dc *Client) Call(req *client.Request) (res interface{}, err error) { dm := req.API.Method.IntegrationRequest method := dm.Method - logger.Debugf("[dubbo-go-pixiu] dubbo invoke, method:%s, types:%s, reqData:%v", method, types, values) + logger.Debugf("[dubbo-go-pixiu] dubbo invoke, method:%s, types:%s, reqData:%v", method, val.Types, val.Values) gs := dc.Get(dm) - rst, err := gs.Invoke(req.Context, []interface{}{method, types, values}) + rst, err := gs.Invoke(req.Context, []interface{}{method, val.Types, val.Values}) if err != nil { return nil, err } @@ -162,33 +166,26 @@ func (dc *Client) Call(req *client.Request) (res interface{}, err error) { return rst, nil } -func (dc *Client) genericArgs(req *client.Request) ([]string, interface{}, error) { +func (dc *Client) genericArgs(req *client.Request) (interface{}, error) { values, err := dc.MapParams(req) - types := req.API.IntegrationRequest.ParamTypes - if len(req.API.IntegrationRequest.ToParamTypes) > 0 { - types = req.API.IntegrationRequest.ToParamTypes - } if err != nil { - return nil, nil, err + return nil, err } - return types, values, nil + return values, nil } // MapParams params mapping to api. func (dc *Client) MapParams(req *client.Request) (interface{}, error) { r := req.API.Method.IntegrationRequest - if len(r.ParamTypes) != len(r.MappingParams) { - return nil, errors.New("Numbers of param types and paramMappings are not the same") - } - var values []interface{} + values := newDubboTarget(r.MappingParams) for _, mappingParam := range r.MappingParams { source, _, err := client.ParseMapSource(mappingParam.Name) if err != nil { return nil, err } if mapper, ok := mappers[source]; ok { - if err := mapper.Map(mappingParam, req, &values, buildOption(mappingParam)); err != nil { + if err := mapper.Map(mappingParam, req, values, buildOption(mappingParam)); err != nil { return nil, err } } @@ -198,14 +195,10 @@ func (dc *Client) MapParams(req *client.Request) (interface{}, error) { func buildOption(conf fc.MappingParam) client.RequestOption { var opt client.RequestOption - if conf.Opt.Open { - matchOpt, ok := DefaultMapOption[conf.Opt.Name] - if ok { - matchOpt.SetUsable(conf.Opt.Usable) - } - opt = matchOpt + isGeneric, mapToType := getGenericMapTo(conf.MapTo) + if isGeneric { + opt = DefaultMapOption[mapToType] } - return opt } diff --git a/pkg/client/dubbo/dubbo_test.go b/pkg/client/dubbo/dubbo_test.go index b3eae1a2d..8dcf92291 100644 --- a/pkg/client/dubbo/dubbo_test.go +++ b/pkg/client/dubbo/dubbo_test.go @@ -95,118 +95,113 @@ func TestMappingParams(t *testing.T) { api := mock.GetMockAPI(config.MethodGet, "/mock/test") api.IntegrationRequest.MappingParams = []config.MappingParam{ { - Name: "queryStrings.id", - MapTo: "0", + Name: "queryStrings.id", + MapTo: "0", + MapType: "string", }, { - Name: "queryStrings.age", - MapTo: "1", + Name: "queryStrings.age", + MapTo: "1", + MapType: "int", }, } - api.IntegrationRequest.ParamTypes = []string{ - "string", - "int", - } req := client.NewReq(context.TODO(), r, api) params, err := dClient.MapParams(req) assert.Nil(t, err) - assert.Equal(t, params.([]interface{})[0], "12345") - assert.Equal(t, params.([]interface{})[1], int32(19)) + assert.Equal(t, params.(*dubboTarget).Values[0], "12345") + assert.Equal(t, params.(*dubboTarget).Values[1], int(19)) r, _ = http.NewRequest("GET", "/mock/test?id=12345&age=19", bytes.NewReader([]byte(""))) api = mock.GetMockAPI(config.MethodGet, "/mock/test") api.IntegrationRequest.MappingParams = []config.MappingParam{ { - Name: "queryStrings.id", - MapTo: "0", + Name: "queryStrings.id", + MapTo: "0", + MapType: "string", }, { - Name: "queryStrings.age", - MapTo: "1", + Name: "queryStrings.age", + MapTo: "1", + MapType: "int", }, { - Name: "headers.Auth", - MapTo: "2", + Name: "headers.Auth", + MapTo: "2", + MapType: "string", }, } - api.IntegrationRequest.ParamTypes = []string{ - "string", - "int", - "string", - } r.Header.Set("Auth", "1234567") req = client.NewReq(context.TODO(), r, api) params, err = dClient.MapParams(req) assert.Nil(t, err) - assert.Equal(t, params.([]interface{})[0], "12345") - assert.Equal(t, params.([]interface{})[1], int32(19)) - assert.Equal(t, params.([]interface{})[2], "1234567") + assert.Equal(t, params.(*dubboTarget).Values[0], "12345") + assert.Equal(t, params.(*dubboTarget).Values[1], int(19)) + assert.Equal(t, params.(*dubboTarget).Values[2], "1234567") r, _ = http.NewRequest("POST", "/mock/test?id=12345&age=19", bytes.NewReader([]byte(`{"sex": "male", "name":{"firstName": "Joe", "lastName": "Biden"}}`))) api = mock.GetMockAPI(config.MethodGet, "/mock/test") api.IntegrationRequest.MappingParams = []config.MappingParam{ { - Name: "queryStrings.id", - MapTo: "0", + Name: "queryStrings.id", + MapTo: "0", + MapType: "string", }, { - Name: "queryStrings.age", - MapTo: "1", + Name: "queryStrings.age", + MapTo: "1", + MapType: "int", }, { - Name: "headers.Auth", - MapTo: "2", + Name: "headers.Auth", + MapTo: "2", + MapType: "string", }, { - Name: "requestBody.sex", - MapTo: "3", + Name: "requestBody.sex", + MapTo: "3", + MapType: "string", }, { - Name: "requestBody.name.firstName", - MapTo: "4", + Name: "requestBody.name.firstName", + MapTo: "4", + MapType: "java.lang.String", }, } - api.IntegrationRequest.ParamTypes = []string{ - "string", - "int", - "string", - "string", - "java.lang.String", - } r.Header.Set("Auth", "1234567") req = client.NewReq(context.TODO(), r, api) params, err = dClient.MapParams(req) assert.Nil(t, err) - assert.Equal(t, params.([]interface{})[0], "12345") - assert.Equal(t, params.([]interface{})[1], int32(19)) - assert.Equal(t, params.([]interface{})[2], "1234567") - assert.Equal(t, params.([]interface{})[3], "male") - assert.Equal(t, params.([]interface{})[4], "Joe") + assert.Equal(t, params.(*dubboTarget).Values[0], "12345") + assert.Equal(t, params.(*dubboTarget).Values[1], int(19)) + assert.Equal(t, params.(*dubboTarget).Values[2], "1234567") + assert.Equal(t, params.(*dubboTarget).Values[3], "male") + assert.Equal(t, params.(*dubboTarget).Values[4], "Joe") } func TestBuildOption(t *testing.T) { mp := config.MappingParam{ - Name: "queryStrings.id", - MapTo: "0", - Opt: config.Opt{ - Name: optionKeyGroup, - Open: true, - Usable: false, - }, + Name: "queryStrings.id", + MapTo: "0", + MapType: "string", } option := buildOption(mp) - assert.NotNil(t, option) - assert.Equal(t, false, option.Usable()) + assert.Nil(t, option) mp = config.MappingParam{ - Name: "queryStrings.id", - MapTo: "0", - Opt: config.Opt{ - Name: "other", - Open: true, - Usable: false, - }, + Name: "queryStrings.id", + MapTo: "opt.whatsoever", + MapType: "", } option = buildOption(mp) assert.Nil(t, option) + + mp = config.MappingParam{ + Name: "queryStrings.id", + MapTo: "opt.interface", + MapType: "", + } + option = buildOption(mp) + assert.NotNil(t, option) + _, ok := option.(*interfaceOpt) + assert.True(t, ok) } diff --git a/pkg/client/dubbo/mapper.go b/pkg/client/dubbo/mapper.go index f51f731c1..f697ec27b 100644 --- a/pkg/client/dubbo/mapper.go +++ b/pkg/client/dubbo/mapper.go @@ -24,6 +24,7 @@ import ( "net/url" "reflect" "strconv" + "strings" "time" ) @@ -46,11 +47,39 @@ var mappers = map[string]client.ParamMapper{ constant.RequestURI: uriMapper{}, } +type dubboTarget struct { + Values []interface{} // the slice contains the parameters. + Types []string // the slice contains the parameters' types. It should match the values one by one. +} + +// pre-allocate proper memory according to the params' usability. +func newDubboTarget(mps []config.MappingParam) *dubboTarget { + length := 0 + + for i := 0; i < len(mps); i++ { + isGeneric, v := getGenericMapTo(mps[i].MapTo) + if isGeneric && v != optionKeyValues { + continue + } + length++ + } + + if length > 0 { + val := make([]interface{}, length) + target := &dubboTarget{ + Values: val, + Types: make([]string, length), + } + return target + } + return nil +} + type queryStringsMapper struct{} // nolint func (qm queryStringsMapper) Map(mp config.MappingParam, c *client.Request, target interface{}, option client.RequestOption) error { - rv, err := validateTarget(target) + t, err := validateTarget(target) if err != nil { return err } @@ -71,7 +100,7 @@ func (qm queryStringsMapper) Map(mp config.MappingParam, c *client.Request, targ return errors.Errorf("Query parameter %s does not exist", key) } - return setTargetWithOpt(c, option, rv, pos, qValue, c.API.IntegrationRequest.ParamTypes[pos]) + return setTargetWithOpt(c, option, t, pos, qValue, mp.MapType) } type headerMapper struct{} @@ -85,14 +114,14 @@ func (hm headerMapper) Map(mp config.MappingParam, c *client.Request, target int _, key, err := client.ParseMapSource(mp.Name) pos, err := strconv.Atoi(mp.MapTo) if err != nil { - return errors.Errorf("Parameter mapping %v incorrect", mp) + return errors.Errorf("Parameter mapping %+v incorrect", mp) } header := c.IngressRequest.Header.Get(key[0]) if len(header) == 0 { return errors.Errorf("Header %s not found", key[0]) } - return setTargetWithOpt(c, option, rv, pos, header, c.API.IntegrationRequest.ParamTypes[pos]) + return setTargetWithOpt(c, option, rv, pos, header, mp.MapType) } type bodyMapper struct{} @@ -110,7 +139,7 @@ func (bm bodyMapper) Map(mp config.MappingParam, c *client.Request, target inter } pos, err := strconv.Atoi(mp.MapTo) if err != nil { - return errors.Errorf("Parameter mapping %v incorrect", mp) + return errors.Errorf("Parameter mapping %v incorrect, parameters for Dubbo backend must be mapped to an int to represent position", mp) } rawBody, err := ioutil.ReadAll(c.IngressRequest.Body) @@ -124,7 +153,7 @@ func (bm bodyMapper) Map(mp config.MappingParam, c *client.Request, target inter json.Unmarshal(rawBody, &mapBody) val, err := client.GetMapValue(mapBody, keys) - if err := setTargetWithOpt(c, option, rv, pos, val, c.API.IntegrationRequest.ParamTypes[pos]); err != nil { + if err := setTargetWithOpt(c, option, rv, pos, val, mp.MapType); err != nil { return errors.Wrap(err, "set target fail") } @@ -150,85 +179,57 @@ func (um uriMapper) Map(mp config.MappingParam, c *client.Request, target interf } uriValues := router.GetURIParams(&c.API, *c.IngressRequest.URL) - return setTargetWithOpt(c, option, rv, pos, uriValues.Get(keys[0]), c.API.IntegrationRequest.ParamTypes[pos]) + return setTargetWithOpt(c, option, rv, pos, uriValues.Get(keys[0]), mp.MapType) } // validateTarget verify if the incoming target for the Map function // can be processed as expected. -func validateTarget(target interface{}) (reflect.Value, error) { - rv := reflect.ValueOf(target) - if rv.Kind() != reflect.Ptr || rv.IsNil() { - return rv, errors.New("Target params must be a non-nil pointer") - } - if _, ok := target.(*[]interface{}); !ok { - return rv, errors.New("Target params for dubbo backend must be *[]interface{}") +func validateTarget(target interface{}) (*dubboTarget, error) { + val, ok := target.(*dubboTarget) + if !ok { + return nil, errors.New("Target params for dubbo backend must be *dubbogoTarget") } - return rv, nil + return val, nil } -func setTargetWithOpt(req *client.Request, option client.RequestOption, rv reflect.Value, pos int, value interface{}, targetType string) error { +func setTargetWithOpt(req *client.Request, option client.RequestOption, + target *dubboTarget, pos int, value interface{}, targetType string) error { + if option != nil { + return setGenericTarget(req, option, target, value, targetType) + } value, err := mapTypes(targetType, value) if err != nil { return err } - newPos := pos - - if option != nil { - option.Action(req, value) - - if option.VirtualPos() != 0 { - newPos = option.VirtualPos() - } - - if option.Usable() { - setTarget(rv, newPos, value) - } - - return nil - } - - setTarget(rv, newPos, value) - + setCommonTarget(target, pos, value, targetType) return nil } -func setTarget(rv reflect.Value, pos int, value interface{}) { - if rv.Kind() != reflect.Ptr && rv.Type().Name() != "" && rv.CanAddr() { - rv = rv.Addr() - } else { - rv = rv.Elem() - } - - tempValue := rv.Interface().([]interface{}) - - // for dubbo values split, like RequestOption - // When config mapTo -1, values is single object, set to 0 position, values is array, will auto split len(values). - // - if pos == -1 { - v, ok := value.([]interface{}) - if ok { - npos := len(v) - 1 - if len(tempValue) <= npos { - list := make([]interface{}, npos+1-len(tempValue)) - tempValue = append(tempValue, list...) - } - for i := range v { - s := v[i] - tempValue[i] = s - } - rv.Set(reflect.ValueOf(tempValue)) - return - } - - pos = 0 +func setGenericTarget(req *client.Request, option client.RequestOption, + target *dubboTarget, value interface{}, targetType string) error { + var err error + switch option.(type) { + case *groupOpt, *versionOpt, *interfaceOpt, *applicationOpt, *methodOpt: + err = option.Action(req, value) + case *valuesOpt: + err = option.Action(target, [2]interface{}{value, targetType}) + case *paramTypesOpt: + err = option.Action(target, value) } + return err +} - if len(tempValue) <= pos { - list := make([]interface{}, pos+1-len(tempValue)) - tempValue = append(tempValue, list...) +func setCommonTarget(target *dubboTarget, pos int, value interface{}, targetType string) { + // if the mapTo position is greater than the numbers of usable parameters, + // extend the values and types slices. It changes the address of the the target. + if cap(target.Values) <= pos { + list := make([]interface{}, pos+1-len(target.Values)) + typeList := make([]string, pos+1-len(target.Types)) + target.Values = append(target.Values, list...) + target.Types = append(target.Types, typeList...) } - tempValue[pos] = value - rv.Set(reflect.ValueOf(tempValue)) + target.Values[pos] = value + target.Types[pos] = targetType } func mapTypes(jType string, originVal interface{}) (interface{}, error) { @@ -239,17 +240,40 @@ func mapTypes(jType string, originVal interface{}) (interface{}, error) { switch targetType { case reflect.TypeOf(""): return cast.ToStringE(originVal) + case reflect.TypeOf(int(0)): + return cast.ToIntE(originVal) + case reflect.TypeOf(int8(0)): + return cast.ToInt8E(originVal) + case reflect.TypeOf(int16(16)): + return cast.ToInt16E(originVal) case reflect.TypeOf(int32(0)): return cast.ToInt32E(originVal) case reflect.TypeOf(int64(0)): return cast.ToInt64E(originVal) + case reflect.TypeOf(float32(0)): + return cast.ToFloat32E(originVal) case reflect.TypeOf(float64(0)): return cast.ToFloat64E(originVal) case reflect.TypeOf(true): return cast.ToBoolE(originVal) case reflect.TypeOf(time.Time{}): - return cast.ToBoolE(originVal) + return cast.ToTimeE(originVal) default: return originVal, nil } } + +// getGenericMapTo will parse the mapTo field, if the mapTo value is +// opt.xxx, the "opt." prefix will identify the param mapTo generic field, +// supporting generic fields: interface, group, application, method, version, +// values, types +func getGenericMapTo(mapTo string) (isGeneric bool, genericField string) { + fields := strings.Split(mapTo, ".") + if len(fields) != 2 || fields[0] != "opt" { + return false, "" + } + if _, ok := DefaultMapOption[fields[1]]; !ok { + return false, "" + } + return true, fields[1] +} diff --git a/pkg/client/dubbo/mapper_test.go b/pkg/client/dubbo/mapper_test.go index 8998fd34c..166b6a234 100644 --- a/pkg/client/dubbo/mapper_test.go +++ b/pkg/client/dubbo/mapper_test.go @@ -39,61 +39,68 @@ func TestQueryStringsMapper(t *testing.T) { api := mock.GetMockAPI(config.MethodGet, "/mock/test") api.IntegrationRequest.MappingParams = []config.MappingParam{ { - Name: "queryStrings.id", - MapTo: "0", + Name: "queryStrings.id", + MapTo: "0", + MapType: "string", }, { - Name: "queryStrings.name", - MapTo: "1", + Name: "queryStrings.name", + MapTo: "1", + MapType: "string", }, { - Name: "queryStrings.age", - MapTo: "jk", + Name: "queryStrings.age", + MapTo: "jk", + MapType: "int", }, } - api.IntegrationRequest.ParamTypes = []string{ - "string", - "string", - "int", - } + req := client.NewReq(context.TODO(), r, api) - var params []interface{} + params := newDubboTarget(api.IntegrationRequest.MappingParams) qs := queryStringsMapper{} - err := qs.Map(api.IntegrationRequest.MappingParams[0], req, ¶ms, nil) + // Giving valid mapping params + err := qs.Map(api.IntegrationRequest.MappingParams[0], req, params, nil) + // it should not return error assert.Nil(t, err) - assert.Equal(t, params[0], "12345") - err = qs.Map(api.IntegrationRequest.MappingParams[1], req, ¶ms, nil) + // it should update the target value in target position from corresponding query value in request. + assert.Equal(t, params.Values[0], "12345") + assert.Equal(t, params.Types[0], "string") + // Giving valid mapping params and same target + err = qs.Map(api.IntegrationRequest.MappingParams[1], req, params, nil) + // it should return error when request does not contain the source parameter assert.EqualError(t, err, "Query parameter [name] does not exist") - err = qs.Map(api.IntegrationRequest.MappingParams[2], req, ¶ms, nil) - assert.EqualError(t, err, "Parameter mapping {queryStrings.age jk { false false}} incorrect") + // Giving invalid mapping params that is not a number and same target + err = qs.Map(api.IntegrationRequest.MappingParams[2], req, params, nil) + // it should return error that points out the mapping param + assert.EqualError(t, err, "Parameter mapping {queryStrings.age jk int} incorrect") r, _ = http.NewRequest("GET", "/mock/test?id=12345&age=19", bytes.NewReader([]byte(""))) api = mock.GetMockAPI(config.MethodGet, "/mock/test") api.IntegrationRequest.MappingParams = []config.MappingParam{ { - Name: "queryStrings.id", - MapTo: "1", + Name: "queryStrings.id", + MapTo: "1", + MapType: "string", }, { - Name: "queryStrings.age", - MapTo: "0", + Name: "queryStrings.age", + MapTo: "0", + MapType: "int", }, } - api.IntegrationRequest.ParamTypes = []string{ - "string", - "string", - } + req = client.NewReq(context.TODO(), r, api) - params = []interface{}{} - err = qs.Map(api.IntegrationRequest.MappingParams[0], req, ¶ms, nil) + params = newDubboTarget(api.IntegrationRequest.MappingParams) + err = qs.Map(api.IntegrationRequest.MappingParams[0], req, params, nil) assert.Nil(t, err) - assert.Equal(t, params[1], "12345") - assert.Nil(t, params[0]) - err = qs.Map(api.IntegrationRequest.MappingParams[1], req, ¶ms, nil) + assert.Equal(t, params.Values[1], "12345") + assert.Equal(t, params.Types[1], "string") + assert.Nil(t, params.Values[0]) + err = qs.Map(api.IntegrationRequest.MappingParams[1], req, params, nil) assert.Nil(t, err) - assert.Equal(t, params[1], "12345") - assert.Equal(t, params[0], "19") + assert.Equal(t, params.Types[0], "int") + assert.Equal(t, params.Values[0], 19) } func TestHeaderMapper(t *testing.T) { @@ -102,22 +109,21 @@ func TestHeaderMapper(t *testing.T) { api := mock.GetMockAPI(config.MethodGet, "/mock/test") api.IntegrationRequest.MappingParams = []config.MappingParam{ { - Name: "headers.Auth", - MapTo: "0", + Name: "headers.Auth", + MapTo: "0", + MapType: "string", }, } - api.IntegrationRequest.ParamTypes = []string{ - "string", - } hm := headerMapper{} - target := []interface{}{} + target := newDubboTarget(api.IntegrationRequest.MappingParams) req := client.NewReq(context.TODO(), r, api) - err := hm.Map(api.IntegrationRequest.MappingParams[0], req, &target, nil) + err := hm.Map(api.IntegrationRequest.MappingParams[0], req, target, nil) assert.Nil(t, err) - assert.Equal(t, target[0], "1234567") + assert.Equal(t, target.Values[0], "1234567") + assert.Equal(t, target.Types[0], "string") - err = hm.Map(config.MappingParam{Name: "headers.Test", MapTo: "0"}, req, &target, nil) + err = hm.Map(config.MappingParam{Name: "headers.Test", MapTo: "0"}, req, target, nil) assert.EqualError(t, err, "Header Test not found") } @@ -127,89 +133,100 @@ func TestBodyMapper(t *testing.T) { api := mock.GetMockAPI(config.MethodGet, "/mock/test") api.IntegrationRequest.MappingParams = []config.MappingParam{ { - Name: "requestBody.sex", - MapTo: "0", + Name: "requestBody.sex", + MapTo: "0", + MapType: "string", }, { - Name: "requestBody.name.lastName", - MapTo: "1", + Name: "requestBody.name.lastName", + MapTo: "1", + MapType: "string", }, { - Name: "requestBody.name", - MapTo: "2", + Name: "requestBody.name", + MapTo: "2", + MapType: "object", }, } - api.IntegrationRequest.ParamTypes = []string{ - "string", - "string", - "object", - } bm := bodyMapper{} - target := []interface{}{} + target := newDubboTarget(api.IntegrationRequest.MappingParams) req := client.NewReq(context.TODO(), r, api) - err := bm.Map(api.IntegrationRequest.MappingParams[0], req, &target, nil) + err := bm.Map(api.IntegrationRequest.MappingParams[0], req, target, nil) assert.Nil(t, err) - assert.Equal(t, target[0], "male") + assert.Equal(t, target.Values[0], "male") + assert.Equal(t, target.Types[0], "string") - err = bm.Map(api.IntegrationRequest.MappingParams[1], req, &target, nil) + err = bm.Map(api.IntegrationRequest.MappingParams[1], req, target, nil) assert.Nil(t, err) - assert.Equal(t, target[1], "Biden") + assert.Equal(t, target.Values[1], "Biden") + assert.Equal(t, target.Types[1], "string") - err = bm.Map(api.IntegrationRequest.MappingParams[2], req, &target, nil) + err = bm.Map(api.IntegrationRequest.MappingParams[2], req, target, nil) assert.Nil(t, err) - assert.Equal(t, target[2], map[string]interface{}(map[string]interface{}{"firstName": "Joe", "lastName": "Biden"})) + assert.Equal(t, target.Types[2], "object") + assert.Equal(t, target.Values[2], map[string]interface{}(map[string]interface{}{ + "firstName": "Joe", "lastName": "Biden", + })) } func TestURIMapper(t *testing.T) { - r, _ := http.NewRequest("POST", "/mock/12345/joe?age=19", bytes.NewReader([]byte(`{"sex": "male", "name":{"firstName": "Joe", "lastName": "Biden"}}`))) + r, _ := http.NewRequest("POST", "/mock/12345/joe?age=19", bytes.NewReader([]byte( + `{"sex": "male", "name":{"firstName": "Joe", "lastName": "Biden"}}`))) r.Header.Set("Auth", "1234567") api := mock.GetMockAPI(config.MethodGet, "/mock/:id/:name") api.IntegrationRequest.MappingParams = []config.MappingParam{ { - Name: "requestBody.sex", - MapTo: "0", + Name: "requestBody.sex", + MapTo: "0", + MapType: "string", }, { - Name: "requestBody.name.lastName", - MapTo: "1", + Name: "requestBody.name.lastName", + MapTo: "1", + MapType: "string", }, { - Name: "uri.name", - MapTo: "2", + Name: "uri.name", + MapTo: "2", + MapType: "object", }, { - Name: "uri.id", - MapTo: "3", + Name: "uri.id", + MapTo: "3", + MapType: "string", }, } - api.IntegrationRequest.ParamTypes = []string{ - "string", - "string", - "object", - "string", - } + um := uriMapper{} - target := []interface{}{} + target := newDubboTarget(api.IntegrationRequest.MappingParams) req := client.NewReq(context.TODO(), r, api) - err := um.Map(api.IntegrationRequest.MappingParams[3], req, &target, nil) + err := um.Map(api.IntegrationRequest.MappingParams[3], req, target, nil) assert.Nil(t, err) - err = um.Map(api.IntegrationRequest.MappingParams[2], req, &target, nil) + err = um.Map(api.IntegrationRequest.MappingParams[2], req, target, nil) assert.Nil(t, err) - assert.Equal(t, target[2], "joe") - assert.Equal(t, target[3], "12345") + assert.Equal(t, target.Values[2], "joe") + assert.Equal(t, target.Types[2], "object") + assert.Equal(t, target.Values[3], "12345") + assert.Equal(t, target.Types[3], "string") } func TestValidateTarget(t *testing.T) { - target := []interface{}{} - val, err := validateTarget(&target) + target := newDubboTarget([]config.MappingParam{ + { + Name: "requestBody.sex", + MapTo: "0", + MapType: "string", + }, + }) + val, err := validateTarget(target) assert.Nil(t, err) assert.NotNil(t, val) - _, err = validateTarget(target) - assert.EqualError(t, err, "Target params must be a non-nil pointer") + _, err = validateTarget(*target) + assert.EqualError(t, err, "Target params for dubbo backend must be *dubbogoTarget") target2 := "" - _, err = validateTarget(&target2) - assert.EqualError(t, err, "Target params for dubbo backend must be *[]interface{}") + _, err = validateTarget(target2) + assert.EqualError(t, err, "Target params for dubbo backend must be *dubbogoTarget") } func TestMapType(t *testing.T) { @@ -224,12 +241,12 @@ func TestMapType(t *testing.T) { val, err = mapTypes("int", "123") assert.Nil(t, err) - assert.Equal(t, val, int32(123)) + assert.Equal(t, val, 123) val, err = mapTypes("int", 123.6) assert.Nil(t, err) - assert.Equal(t, val, int32(123)) + assert.Equal(t, val, 123) _, err = mapTypes("int", "123a") - assert.EqualError(t, err, "unable to cast \"123a\" of type string to int32") + assert.EqualError(t, err, "unable to cast \"123a\" of type string to int") val, err = mapTypes("object", map[string]string{"abc": "123"}) assert.Nil(t, err) @@ -241,3 +258,97 @@ func TestMapType(t *testing.T) { assert.Nil(t, err) assert.Equal(t, val, 123.6) } + +func TestNewDubboTarget(t *testing.T) { + mps := []config.MappingParam{ + { + Name: "string1", + MapTo: "0", + }, + { + Name: "string2", + MapTo: "opt.values", + }, + } + target := newDubboTarget(mps) + assert.NotNil(t, target) + assert.Equal(t, len(target.Values), 2) + + mps = []config.MappingParam{ + { + Name: "string1", + MapTo: "opt.interface", + }, + } + target = newDubboTarget(mps) + assert.Nil(t, target) +} + +func TestSetCommonTarget(t *testing.T) { + vals := make([]interface{}, 10) + types := make([]string, 10) + target := &dubboTarget{ + Values: vals, + Types: types, + } + setCommonTarget(target, 1, 123, "int") + assert.Equal(t, target.Values[1], 123) + assert.Equal(t, target.Types[1], "int") + assert.Nil(t, target.Values[0]) + assert.Equal(t, target.Types[0], "") + setCommonTarget(target, 10, "123", "string") + assert.Equal(t, target.Values[10], "123") + assert.Equal(t, target.Types[10], "string") +} + +func TestSetGenericTarget(t *testing.T) { + api := mock.GetMockAPI(config.MethodGet, "/mock/test") + r, _ := http.NewRequest("GET", "/mock/test?id=12345&age=19", bytes.NewReader([]byte(""))) + req := client.NewReq(context.TODO(), r, api) + + target := &dubboTarget{ + Values: make([]interface{}, 3), + Types: make([]string, 3), + } + + opt := DefaultMapOption[optionKeyValues] + err := setGenericTarget(req, opt, target, []interface{}{1, "abc", struct{ Name string }{"joe"}}, "int, string, object") + assert.Nil(t, err) + assert.Equal(t, target.Values[0], 1) + assert.Equal(t, target.Values[1], "abc") + assert.Equal(t, target.Values[2], struct{ Name string }{"joe"}) + assert.Equal(t, target.Types[0], "int") + assert.Equal(t, target.Types[1], "string") + assert.Equal(t, target.Types[2], "object") + + opt = DefaultMapOption[optionKeyTypes] + err = setGenericTarget(req, opt, target, "int, object, object", "") + assert.Nil(t, err) + assert.Equal(t, target.Types[0], "int") + assert.Equal(t, target.Types[1], "object") + assert.Equal(t, target.Types[2], "object") + + opt = DefaultMapOption[optionKeyInterface] + err = setGenericTarget(req, opt, target, "testingInterface", "") + assert.Nil(t, err) + assert.Equal(t, req.API.IntegrationRequest.Interface, "testingInterface") + + opt = DefaultMapOption[optionKeyApplication] + err = setGenericTarget(req, opt, target, "testingApplication", "") + assert.Nil(t, err) + assert.Equal(t, req.API.IntegrationRequest.ApplicationName, "testingApplication") +} + +func TestGetGenericMapTo(t *testing.T) { + isGeneric, gMapTo := getGenericMapTo("1") + assert.False(t, isGeneric) + assert.Equal(t, gMapTo, "") + + isGeneric, gMapTo = getGenericMapTo("opt.interface") + assert.True(t, isGeneric) + assert.Equal(t, gMapTo, "interface") + + isGeneric, gMapTo = getGenericMapTo("opt.whatever") + assert.False(t, isGeneric) + assert.Equal(t, gMapTo, "") +} diff --git a/pkg/client/dubbo/option.go b/pkg/client/dubbo/option.go index 72fbdc160..a70a0cc6e 100644 --- a/pkg/client/dubbo/option.go +++ b/pkg/client/dubbo/option.go @@ -17,7 +17,18 @@ package dubbo -import "github.com/apache/dubbo-go-pixiu/pkg/client" +import ( + "strings" +) + +import ( + "github.com/pkg/errors" +) + +import ( + "github.com/apache/dubbo-go-pixiu/pkg/client" + "github.com/apache/dubbo-go-pixiu/pkg/common/constant" +) // option keys const ( @@ -41,106 +52,159 @@ var DefaultMapOption = client.MapOption{ optionKeyValues: &valuesOpt{}, } -type paramTypesOpt struct { - client.CommonOption -} +type groupOpt struct{} // nolint -func (opt *paramTypesOpt) Action(req *client.Request, val interface{}) { - //v, ok := val.([]interface{}) - //if !ok { - // return - //} - // - //var pt []string - //for i := range v { - // ptv, ok := v[i].(string) - // if ok { - // pt = append(pt, ptv) - // } - //} - // - //req.API.IntegrationRequest.DubboBackendConfig.ParamTypes = pt +func (opt *groupOpt) Action(target, val interface{}) error { + v, ok := val.(string) + if !ok { + return errors.New("Group value is not string") + } + r, ok := target.(*client.Request) + if !ok { + return errors.New("Target is not *client.Request in value options") + } + r.API.IntegrationRequest.DubboBackendConfig.Group = v + return nil } -type groupOpt struct { - client.CommonOption -} +type versionOpt struct{} // nolint -func (opt *groupOpt) Action(req *client.Request, val interface{}) { +func (opt *versionOpt) Action(target, val interface{}) error { v, ok := val.(string) if !ok { - return + return errors.New("Version value is not string") } - - req.API.IntegrationRequest.DubboBackendConfig.Group = v + r, ok := target.(*client.Request) + if !ok { + return errors.New("Target is not *client.Request in value options") + } + r.API.IntegrationRequest.DubboBackendConfig.Version = v + return nil } -type versionOpt struct { - client.CommonOption -} +type methodOpt struct{} // nolint -func (opt *versionOpt) Action(req *client.Request, val interface{}) { +func (opt *methodOpt) Action(target, val interface{}) error { v, ok := val.(string) if !ok { - return + return errors.New("Method value is not string") } - - req.API.IntegrationRequest.DubboBackendConfig.Version = v + r, ok := target.(*client.Request) + if !ok { + return errors.New("Target is not *client.Request in value options") + } + r.API.IntegrationRequest.DubboBackendConfig.Method = v + return nil } -type methodOpt struct { - client.CommonOption -} +type applicationOpt struct{} // nolint -func (opt *methodOpt) Action(req *client.Request, val interface{}) { +func (opt *applicationOpt) Action(target, val interface{}) error { v, ok := val.(string) if !ok { - return + return errors.New("Application value is not string") } - - req.API.IntegrationRequest.DubboBackendConfig.Method = v + r, ok := target.(*client.Request) + if !ok { + return errors.New("Target is not *client.Request in value options") + } + r.API.IntegrationRequest.DubboBackendConfig.ApplicationName = v + return nil } -type applicationOpt struct { - client.CommonOption -} +type interfaceOpt struct{} // nolint -func (opt *applicationOpt) Action(req *client.Request, val interface{}) { +func (opt *interfaceOpt) Action(target, val interface{}) error { v, ok := val.(string) if !ok { - return + return errors.New("Interface value is not string") } - - req.API.IntegrationRequest.DubboBackendConfig.ApplicationName = v + r, ok := target.(*client.Request) + if !ok { + return errors.New("Target is not *client.Request in value options") + } + r.API.IntegrationRequest.DubboBackendConfig.Interface = v + return nil } -type interfaceOpt struct { - client.CommonOption -} +type valuesOpt struct{} -// nolint -func (opt *interfaceOpt) Action(req *client.Request, val interface{}) { - v, ok := val.(string) +// Action of valuesOpt retrieve value from [2]interface{} then assign to target, which the first element is the +// parameter values to dubbo generic call. the second element is string, which is the types +// for the generic call, it could be empty or types sep from ','. If empty, it should retrieve types from +// another generic option - types. +func (opt *valuesOpt) Action(target, val interface{}) error { + dubboTarget, ok := target.(*dubboTarget) if !ok { - return + return errors.New("Target is not dubboTarget in value options") } + v, ok := val.([2]interface{}) + if !ok { + return errors.New("The value must be [2]interface{}") + } + var toVals []interface{} + toTypes := []string{} - req.API.IntegrationRequest.DubboBackendConfig.Interface = v -} - -type valuesOpt struct { - client.CommonOption + if t, tok := v[1].(string); tok && len(t) != 0 { + toTypes = strings.Split(t, ",") + } + if val, vok := v[0].([]interface{}); vok { + toVals = val + } else { + toVals = []interface{}{v[0]} + } + if !(len(toTypes) != 0 && len(toTypes) == len(toVals)) { + dubboTarget.Types = toTypes + dubboTarget.Values = toVals + return nil + } + for i := range toVals { + trimType := strings.TrimSpace(toTypes[i]) + if _, ok = constant.JTypeMapper[trimType]; ok { + toTypes[i] = trimType + } else { + return errors.Errorf("Types invalid %s", trimType) + } + var err error + toVals[i], err = mapTypes(toTypes[i], toVals[i]) + if err != nil { + return errors.WithStack(err) + } + } + dubboTarget.Types = toTypes + dubboTarget.Values = toVals + return nil } -// nolint -func (opt *valuesOpt) Action(req *client.Request, val interface{}) { -} +type paramTypesOpt struct{} -func (opt *valuesOpt) VirtualPos() int { - return -1 +// Action for paramTypesOpt override the other param types mapping/config. +// The val must be []string, and will then assign to the target.(dubboTarget).Types +func (opt *paramTypesOpt) Action(target, val interface{}) error { + v, ok := val.(string) + if !ok { + return errors.New("The val type must be string") + } + types := strings.Split(v, ",") + dubboTarget, ok := target.(*dubboTarget) + if !ok { + return errors.New("Target is not dubboTarget in target parameter") + } + for i := range types { + trimType := strings.TrimSpace(types[i]) + if len(trimType) == 0 { + continue + } + if _, ok = constant.JTypeMapper[trimType]; !ok { + return errors.Errorf("Types invalid %s", trimType) + } + types[i] = trimType + } + dubboTarget.Types = types + return nil } diff --git a/pkg/client/dubbo/option_test.go b/pkg/client/dubbo/option_test.go new file mode 100644 index 000000000..e8762e599 --- /dev/null +++ b/pkg/client/dubbo/option_test.go @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dubbo + +import ( + "testing" +) + +import ( + "github.com/stretchr/testify/assert" +) + +func TestValuesOpt(t *testing.T) { + opt := &valuesOpt{} + target := &dubboTarget{ + Values: make([]interface{}, 3), + Types: make([]string, 3), + } + vals := []interface{}{ + struct{ Name string }{"joe"}, + "abc", + 123, + } + err := opt.Action(target, [2]interface{}{ + vals, + "object, string, int", + }) + assert.Nil(t, err) + assert.Equal(t, len(target.Values), 3) + assert.Equal(t, target.Values, vals) + assert.Equal(t, target.Types[0], "object") + assert.Equal(t, target.Types[1], "string") + assert.Equal(t, target.Types[2], "int") + + err = opt.Action(target, []interface{}{ + vals, + "object, string, int", + }) + assert.NotNil(t, err) + + target = &dubboTarget{ + Values: make([]interface{}, 3), + Types: make([]string, 3), + } + vals = []interface{}{ + struct{ Name string }{"joe"}, + "abc", + 123, + } + err = opt.Action(target, [2]interface{}{ + vals, + "", + }) + assert.Nil(t, err) + assert.Equal(t, len(target.Values), 3) + assert.Equal(t, target.Values, vals) + assert.Equal(t, len(target.Types), 0) +} + +func TestParamTypesOptAction(t *testing.T) { + opt := ¶mTypesOpt{} + target := &dubboTarget{ + Values: make([]interface{}, 3), + Types: make([]string, 3), + } + err := opt.Action(target, "object,string") + assert.Nil(t, err) + assert.Equal(t, "object", target.Types[0]) + assert.Equal(t, "string", target.Types[1]) + + err = opt.Action(target, "object,whatsoever") + assert.EqualError(t, err, "Types invalid whatsoever") + + err = opt.Action("target", []string{}) + assert.EqualError(t, err, "The val type must be string") + err = opt.Action(target, "object,") + assert.Nil(t, err) + assert.Equal(t, "object", target.Types[0]) + err = opt.Action(target, "object") + assert.Nil(t, err) + assert.Equal(t, "object", target.Types[0]) +} diff --git a/pkg/client/http/http_test.go b/pkg/client/http/http_test.go index 9cfe71981..c63f5c151 100644 --- a/pkg/client/http/http_test.go +++ b/pkg/client/http/http_test.go @@ -37,7 +37,8 @@ import ( func TestMapParams(t *testing.T) { hClient := NewHTTPClient() - r, _ := http.NewRequest("POST", "/mock/test?team=theBoys", bytes.NewReader([]byte("{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}"))) + r, _ := http.NewRequest("POST", "/mock/test?team=theBoys", bytes.NewReader([]byte( + "{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}"))) r.Header.Set("Auth", "12345") api := mock.GetMockAPI(config.MethodGet, "/mock/test") req := client.NewReq(context.TODO(), r, api) @@ -49,7 +50,8 @@ func TestMapParams(t *testing.T) { assert.Equal(t, p.Header.Get("Auth"), "12345") rawBody, err := ioutil.ReadAll(p.Body) assert.Nil(t, err) - assert.Equal(t, string(rawBody), "{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}") + assert.Equal(t, string(rawBody), + "{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}") api.IntegrationRequest.MappingParams = []config.MappingParam{ { @@ -79,7 +81,8 @@ func TestMapParams(t *testing.T) { } api.IntegrationRequest.HTTPBackendConfig.Schema = "https" api.IntegrationRequest.HTTPBackendConfig.Host = "localhost" - r, _ = http.NewRequest("POST", "/mock/test?team=theBoys", bytes.NewReader([]byte("{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}"))) + r, _ = http.NewRequest("POST", "/mock/test?team=theBoys", bytes.NewReader([]byte( + "{\"id\":\"12345\",\"age\":\"19\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\",\"nickName\":\"trump\"}}"))) r.Header.Set("Auth", "12345") req = client.NewReq(context.TODO(), r, api) val, err = hClient.MapParams(req) @@ -90,9 +93,8 @@ func TestMapParams(t *testing.T) { assert.Equal(t, p.Query.Get("team"), "theBoys") rawBody, err = ioutil.ReadAll(p.Body) assert.Nil(t, err) - assert.Equal(t, string(rawBody), "{\"age\":\"19\",\"nickName\":\"trump\",\"testStruct\":{\"name\":\"mock\",\"nickName\":\"trump\",\"test\":\"happy\"}}") - - hClient.Call(req) + assert.Equal(t, string(rawBody), + "{\"age\":\"19\",\"nickName\":\"trump\",\"testStruct\":{\"name\":\"mock\",\"nickName\":\"trump\",\"test\":\"happy\"}}") } func TestParseURL(t *testing.T) { diff --git a/pkg/client/http/mapper.go b/pkg/client/http/mapper.go index 59cae7645..ab28eb125 100644 --- a/pkg/client/http/mapper.go +++ b/pkg/client/http/mapper.go @@ -145,12 +145,8 @@ func (um uriMapper) Map(mp config.MappingParam, c *client.Request, rawTarget int } func validateTarget(target interface{}) (*requestParams, error) { - rv := reflect.ValueOf(target) - if rv.Kind() != reflect.Ptr || rv.IsNil() { - return nil, errors.New("Target params must be a non-nil pointer") - } val, ok := target.(*requestParams) - if !ok { + if !ok || val == nil { return nil, errors.New("Target params must be a requestParams pointer") } return val, nil @@ -174,11 +170,15 @@ func setTarget(target *requestParams, to string, key string, val interface{}) er target.Body = ioutil.NopCloser(bytes.NewReader(rawBody)) }() if err != nil { - return errors.New("Raw body parse failed") + return errors.New("Raw body read failed") } mapBody := map[string]interface{}{} - json.Unmarshal(rawBody, &mapBody) - + if len(rawBody) != 0 { + err = json.Unmarshal(rawBody, &mapBody) + if err != nil { + return errors.New("Raw body parse failed") + } + } setMapWithPath(mapBody, key, val) rawBody, err = json.Marshal(mapBody) if err != nil { diff --git a/pkg/client/http/mapper_test.go b/pkg/client/http/mapper_test.go index ad50dd7b5..f08bb6194 100644 --- a/pkg/client/http/mapper_test.go +++ b/pkg/client/http/mapper_test.go @@ -251,3 +251,25 @@ func TestSetTarget(t *testing.T) { assert.Nil(t, err) assert.Equal(t, string(rawBody), "{\"otherStructure\":\"abcde\",\"testStruct\":{\"name\":\"mock\",\"test\":\"happy\"}}") } + +func TestValidateTarget(t *testing.T) { + requestP := newRequestParams() + p, e := validateTarget(requestP) + assert.NotNil(t, p) + assert.Nil(t, e) + + requestP = nil + p, e = validateTarget(requestP) + assert.Nil(t, p) + assert.NotNil(t, e) + + requestP2 := []int{} + p, e = validateTarget(requestP2) + assert.Nil(t, p) + assert.NotNil(t, e) + + requestP3 := struct{}{} + p, e = validateTarget(requestP3) + assert.Nil(t, p) + assert.NotNil(t, e) +} diff --git a/pkg/common/constant/jtypes.go b/pkg/common/constant/jtypes.go index 463a96b78..2184642d5 100644 --- a/pkg/common/constant/jtypes.go +++ b/pkg/common/constant/jtypes.go @@ -30,10 +30,10 @@ var JTypeMapper = map[string]reflect.Type{ "string": reflect.TypeOf(""), "java.lang.String": reflect.TypeOf(""), "char": reflect.TypeOf(""), - "short": reflect.TypeOf(int32(0)), - "int": reflect.TypeOf(int32(0)), + "short": reflect.TypeOf(int16(0)), + "int": reflect.TypeOf(int(0)), "long": reflect.TypeOf(int64(0)), - "float": reflect.TypeOf(float64(0)), + "float": reflect.TypeOf(float32(0)), "double": reflect.TypeOf(float64(0)), "boolean": reflect.TypeOf(true), "java.util.Date": reflect.TypeOf(time.Time{}), diff --git a/pkg/filter/replacepath/replace_path.go b/pkg/filter/replacepath/replace_path.go deleted file mode 100644 index 0ef88f732..000000000 --- a/pkg/filter/replacepath/replace_path.go +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package replacepath - -import ( - nh "net/http" - "net/url" -) - -import ( - "github.com/dubbogo/dubbo-go-pixiu-filter/pkg/context" - "github.com/dubbogo/dubbo-go-pixiu-filter/pkg/filter" -) - -import ( - "github.com/apache/dubbo-go-pixiu/pkg/common/constant" - "github.com/apache/dubbo-go-pixiu/pkg/context/http" -) - -const ( - // ReplacedPathHeader is the default header to set the old path to. - ReplacedPathHeader = "X-Replaced-Path" - replacePathError = "replace path fail" -) - -// replacePathFilter is a filter for host. -type replacePathFilter struct { - path string -} - -// New create replace path filter. -func New(path string) filter.Filter { - return &replacePathFilter{path: path} -} - -// // Do execute replacePathFilter filter logic. -func (f replacePathFilter) Do() context.FilterFunc { - return func(c context.Context) { - f.doReplacePathFilter(c.(*http.HttpContext)) - } -} - -func (f replacePathFilter) doReplacePathFilter(ctx *http.HttpContext) { - req := ctx.Request - if req.URL.RawPath == "" { - req.Header.Add(ReplacedPathHeader, req.URL.Path) - } else { - req.Header.Add(ReplacedPathHeader, req.URL.RawPath) - } - - req.URL.RawPath = f.path - var err error - req.URL.Path, err = url.PathUnescape(req.URL.RawPath) - if err != nil { - ctx.AddHeader(constant.HeaderKeyContextType, constant.HeaderValueTextPlain) - ctx.WriteWithStatus(nh.StatusInternalServerError, []byte(replacePathError)) - ctx.Abort() - return - } - - req.RequestURI = req.URL.RequestURI() - - ctx.Next() -} diff --git a/pkg/filter/replacepath/replace_place_test.go b/pkg/filter/replacepath/replace_place_test.go deleted file mode 100644 index 56df3b000..000000000 --- a/pkg/filter/replacepath/replace_place_test.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package replacepath - -import ( - "bytes" - "net/http" - "testing" -) - -import ( - "github.com/stretchr/testify/assert" -) - -import ( - "github.com/apache/dubbo-go-pixiu/pkg/context/mock" - "github.com/apache/dubbo-go-pixiu/pkg/filter/recovery" -) - -func TestReplacePath(t *testing.T) { - path := "/user" - request, err := http.NewRequest("POST", "http://www.dubbogopixiu.com/mock/test?name=tc", bytes.NewReader([]byte("{\"id\":\"12345\"}"))) - assert.NoError(t, err) - c := mock.GetMockHTTPContext(request, New(path).Do(), recovery.New().Do()) - c.Next() - assert.Equal(t, path, c.Request.URL.Path) - assert.Equal(t, path+"?name=tc", c.Request.RequestURI) -} diff --git a/pkg/pixiu/listener.go b/pkg/pixiu/listener.go index 366f77af2..552fdddc8 100644 --- a/pkg/pixiu/listener.go +++ b/pkg/pixiu/listener.go @@ -44,7 +44,6 @@ import ( ctx "github.com/apache/dubbo-go-pixiu/pkg/context" h "github.com/apache/dubbo-go-pixiu/pkg/context/http" "github.com/apache/dubbo-go-pixiu/pkg/filter/host" - "github.com/apache/dubbo-go-pixiu/pkg/filter/replacepath" "github.com/apache/dubbo-go-pixiu/pkg/logger" "github.com/apache/dubbo-go-pixiu/pkg/model" ) @@ -179,9 +178,6 @@ func httpFilter(ctx *h.HttpContext, request fc.IntegrationRequest) { if len(request.Host) != 0 { ctx.AppendFilterFunc(host.New(request.Host).Do()) } - if len(request.Path) != 0 { - ctx.AppendFilterFunc(replacepath.New(request.Path).Do()) - } } func (s *DefaultHttpListener) routeRequest(ctx *h.HttpContext, req *http.Request) (router.API, error) { diff --git a/samples/admin/proxy/api_config.yaml b/samples/admin/proxy/api_config.yaml index cd81c1e63..d6386c94f 100644 --- a/samples/admin/proxy/api_config.yaml +++ b/samples/admin/proxy/api_config.yaml @@ -40,37 +40,19 @@ resources: paramTypes: [ "string", "string", "string", "string", "string", "string", "string" ] mappingParams: - name: requestBody.values - mapTo: 0 + mapTo: opt.values - name: requestBody.types - mapTo: 1 - opt: - open: true - name: types + mapTo: opt.types - name: uri.application - mapTo: 2 - opt: - open: true - name: application + mapTo: opt.application - name: uri.interface - mapTo: 3 - opt: - open: true - name: interface + mapTo: opt.interface - name: queryStrings.method - mapTo: 4 - opt: - open: true - name: method + mapTo: opt.method - name: queryStrings.group - mapTo: 5 - opt: - open: true - name: group + mapTo: opt.group - name: queryStrings.version - mapTo: 6 - opt: - open: true - name: version + mapTo: opt.version clusterName: "test_dubbo" - path: '/api/v1/test-dubbo/user' type: restful @@ -88,10 +70,10 @@ resources: required: true integrationRequest: requestType: dubbo - paramTypes: [ "java.lang.String" ] mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "java.lang.String" applicationName: "UserProvider" interface: "com.ic.user.UserProvider" method: "GetUserByName" @@ -103,14 +85,12 @@ resources: timeout: 10s inboundRequest: requestType: http - # requestBody: - # - definitionName: "userCreate" integrationRequest: requestType: dubbo - paramTypes: [ "object" ] mappingParams: - name: requestBody._all mapTo: 0 + mapType: "object" applicationName: "UserProvider" interface: "com.ic.user.UserProvider" method: "CreateUser" @@ -134,10 +114,10 @@ resources: required: true integrationRequest: requestType: dubbo - paramTypes: [ "string" ] mappingParams: - name: queryStrings.name mapTo: 1 + mapType: "string" applicationName: "UserProvider" interface: "com.ic.user.UserProvider" method: "GetUserTimeout" @@ -155,14 +135,16 @@ resources: requestType: http integrationRequest: requestType: dubbo - paramTypes: [ "string", "string", "int" ] mappingParams: - name: requestBody.name mapTo: 0 + mapType: "string" - name: requestBody.id mapTo: 1 + mapType: "string" - name: requestBody.age mapTo: 2 + mapType: "int" applicationName: "UserProvider" interface: "com.ic.user.UserProvider" method: "CreateUser" diff --git a/samples/dubbogo/multi/apiconfig/api_config.yaml b/samples/dubbogo/multi/apiconfig/api_config.yaml index 4ce16ef4b..34c937cbc 100644 --- a/samples/dubbogo/multi/apiconfig/api_config.yaml +++ b/samples/dubbogo/multi/apiconfig/api_config.yaml @@ -35,10 +35,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "StudentService" interface: "com.dubbogo.pixiu.StudentService" method: "GetStudentByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -52,12 +52,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "StudentService" interface: "com.dubbogo.pixiu.StudentService" method: "UpdateStudentByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -77,10 +78,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "TeacherService" interface: "com.dubbogo.pixiu.TeacherService" method: "GetTeacherByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -94,12 +95,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "TeacherService" interface: "com.dubbogo.pixiu.TeacherService" method: "UpdateTeacherByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" \ No newline at end of file diff --git a/samples/dubbogo/simple/body/api_config.yaml b/samples/dubbogo/simple/body/api_config.yaml index 7ea3b5966..a662e2614 100644 --- a/samples/dubbogo/simple/body/api_config.yaml +++ b/samples/dubbogo/simple/body/api_config.yaml @@ -33,10 +33,10 @@ resources: mappingParams: - name: requestBody._all mapTo: 0 + mapType: "object" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "CreateUser" - paramTypes: [ "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -50,10 +50,10 @@ resources: mappingParams: - name: requestBody._all mapTo: 0 + mapType: "object" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUser" - paramTypes: [ "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -71,13 +71,14 @@ resources: mappingParams: - name: requestBody.name mapTo: 0 + mapType: "string" - name: requestBody.user mapTo: 1 + mapType: "object" # applicationName: "UserService" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -96,10 +97,10 @@ resources: mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" diff --git a/samples/dubbogo/simple/mix/api_config.yaml b/samples/dubbogo/simple/mix/api_config.yaml index 7434baae6..9900188fd 100644 --- a/samples/dubbogo/simple/mix/api_config.yaml +++ b/samples/dubbogo/simple/mix/api_config.yaml @@ -33,12 +33,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: queryStrings.age mapTo: 1 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "string", "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -52,12 +53,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -77,12 +79,13 @@ resources: mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" - name: requestBody._all mapTo: 1 + mapType: "object" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "UpdateUserByName" - paramTypes: [ "string", "object" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" \ No newline at end of file diff --git a/samples/dubbogo/simple/proxy/api_config.yaml b/samples/dubbogo/simple/proxy/api_config.yaml index de29ca601..a7332b19f 100644 --- a/samples/dubbogo/simple/proxy/api_config.yaml +++ b/samples/dubbogo/simple/proxy/api_config.yaml @@ -32,41 +32,17 @@ resources: requestType: dubbo mappingParams: - name: requestBody.values - mapTo: 0 - opt: - open: true - usable: true - name: values + mapTo: opt.values - name: requestBody.types - mapTo: 1 - opt: - open: true - name: types + mapTo: opt.types - name: uri.application - mapTo: 2 - opt: - open: true - name: application + mapTo: opt.application - name: uri.interface - mapTo: 3 - opt: - open: true - name: interface + mapTo: opt.interface - name: queryStrings.method - mapTo: 4 - opt: - open: true - name: method + mapTo: opt.method - name: queryStrings.group - mapTo: 5 - opt: - open: true - name: group + mapTo: opt.group - name: queryStrings.version - mapTo: 6 - opt: - open: true - name: version - paramTypes: ["object", "object", "string", "string", "string", "string", "string"] - toParamTypes: ["string"] + mapTo: opt.version clusterName: "test_dubbo" \ No newline at end of file diff --git a/samples/dubbogo/simple/query/api_config.yaml b/samples/dubbogo/simple/query/api_config.yaml index 9a7ade84b..a1f16c9c6 100644 --- a/samples/dubbogo/simple/query/api_config.yaml +++ b/samples/dubbogo/simple/query/api_config.yaml @@ -33,10 +33,10 @@ resources: mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -54,12 +54,13 @@ resources: mappingParams: - name: queryStrings.name mapTo: 0 + mapType: "string" - name: queryStrings.age mapTo: 1 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "string","int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -77,10 +78,10 @@ resources: mappingParams: - name: queryStrings.code mapTo: 0 + mapType: "int" applicationName: "UserService" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByCode" - paramTypes: [ "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" \ No newline at end of file diff --git a/samples/dubbogo/simple/uri/api_config.yaml b/samples/dubbogo/simple/uri/api_config.yaml index ebcf28bbb..f1effb978 100644 --- a/samples/dubbogo/simple/uri/api_config.yaml +++ b/samples/dubbogo/simple/uri/api_config.yaml @@ -36,10 +36,10 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByName" - paramTypes: [ "string" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -60,10 +60,10 @@ resources: mappingParams: - name: uri.code mapTo: 0 + mapType: "int" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByCode" - paramTypes: [ "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" @@ -86,12 +86,13 @@ resources: mappingParams: - name: uri.name mapTo: 0 + mapType: "string" - name: uri.age mapTo: 1 + mapType: "int" applicationName: "UserProvider" interface: "com.dubbogo.pixiu.UserService" method: "GetUserByNameAndAge" - paramTypes: [ "string", "int" ] group: "test" version: 1.0.0 clusterName: "test_dubbo" \ No newline at end of file