From 0ac0a4a6fd217457fca00e6fbe63b392ce704b0d Mon Sep 17 00:00:00 2001 From: fangyincheng <fangyincheng@sina.com> Date: Thu, 23 May 2019 14:14:52 +0800 Subject: [PATCH] Imp:modify calling mode of server --- common/proxy/proxy.go | 2 +- common/rpc_service.go | 86 +++++++++++-------- common/rpc_service_test.go | 29 +++---- examples/dubbo/go-client/app/client.go | 2 +- examples/dubbo/go-client/app/user.go | 2 +- examples/dubbo/go-server/app/user.go | 20 +++-- .../main/java/com/ikurento/user/Consumer.java | 4 + .../java/com/ikurento/user/UserProvider.java | 7 +- .../java/com/ikurento/user/UserProvider.java | 2 + .../user/UserProviderAnotherImpl.java | 4 + .../com/ikurento/user/UserProviderImpl.java | 3 + examples/jsonrpc/go-client/app/client.go | 2 +- examples/jsonrpc/go-client/app/user.go | 2 +- examples/jsonrpc/go-server/app/user.go | 18 ++++ .../main/java/com/ikurento/user/Consumer.java | 4 + .../java/com/ikurento/user/UserProvider.java | 7 +- .../java/com/ikurento/user/UserProvider.java | 2 + .../user/UserProviderAnotherImpl.java | 4 + .../com/ikurento/user/UserProviderImpl.java | 4 + protocol/dubbo/client_test.go | 6 +- protocol/dubbo/listener.go | 40 ++++++--- protocol/jsonrpc/http_test.go | 6 +- protocol/jsonrpc/server.go | 51 ++++++----- 23 files changed, 197 insertions(+), 110 deletions(-) diff --git a/common/proxy/proxy.go b/common/proxy/proxy.go index 044f6018a..a7c0ab8be 100644 --- a/common/proxy/proxy.go +++ b/common/proxy/proxy.go @@ -150,7 +150,7 @@ func (p *Proxy) Implement(v common.RPCService) { // reply must be Ptr when outNum == 1 if outNum == 1 && t.Type.In(inNum-1).Kind() != reflect.Ptr { - log.Warn("reply type of method %q is not a pointer or interface", t.Name) + log.Warn("reply type of method %q is not a pointer", t.Name) continue } diff --git a/common/rpc_service.go b/common/rpc_service.go index 827455276..60679e00d 100644 --- a/common/rpc_service.go +++ b/common/rpc_service.go @@ -51,9 +51,9 @@ var ( type MethodType struct { method reflect.Method - ctxType reflect.Type // type of the request context - argType reflect.Type - replyType reflect.Type + ctxType reflect.Type // request context + argsType []reflect.Type // args except ctx, include replyType if existing + replyType reflect.Type // return value, otherwise it is nil } func (m *MethodType) Method() reflect.Method { @@ -62,8 +62,8 @@ func (m *MethodType) Method() reflect.Method { func (m *MethodType) CtxType() reflect.Type { return m.ctxType } -func (m *MethodType) ArgType() reflect.Type { - return m.argType +func (m *MethodType) ArgsType() []reflect.Type { + return m.argsType } func (m *MethodType) ReplyType() reflect.Type { return m.replyType @@ -224,51 +224,61 @@ func suitableMethods(typ reflect.Type) (string, map[string]*MethodType) { func suiteMethod(method reflect.Method) *MethodType { mtype := method.Type mname := method.Name + inNum := mtype.NumIn() + outNum := mtype.NumOut() // Method must be exported. if method.PkgPath != "" { return nil } - var replyType, argType, ctxType reflect.Type - switch mtype.NumIn() { - case 3: - argType = mtype.In(1) - replyType = mtype.In(2) - case 4: - ctxType = mtype.In(1) - argType = mtype.In(2) - replyType = mtype.In(3) - default: - log.Error("method %s of mtype %v has wrong number of in parameters %d; needs exactly 3/4", - mname, mtype, mtype.NumIn()) - return nil - } - // First arg need not be a pointer. - if !isExportedOrBuiltinType(argType) { - log.Error("argument type of method %q is not exported %v", mname, argType) + var ( + replyType, ctxType reflect.Type + argsType []reflect.Type + ) + + if outNum != 1 && outNum != 2 { + log.Warn("method %s of mtype %v has wrong number of in out parameters %d; needs exactly 1/2", + mname, mtype.String(), outNum) return nil } - // Second arg must be a pointer. - if replyType.Kind() != reflect.Ptr { - log.Error("reply type of method %q is not a pointer %v", mname, replyType) + + // The latest return type of the method must be error. + if returnType := mtype.Out(outNum - 1); returnType != typeOfError { + log.Warn("the latest return type %s of method %q is not error", returnType, mname) return nil } - // Reply type must be exported. - if !isExportedOrBuiltinType(replyType) { - log.Error("reply type of method %s not exported{%v}", mname, replyType) - return nil + + // replyType + if outNum == 1 { + if mtype.In(inNum-1).Kind() != reflect.Ptr { + log.Error("reply type of method %q is not a pointer %v", mname, replyType) + return nil + } + } else { + replyType = mtype.Out(0) + if !isExportedOrBuiltinType(replyType) { + log.Error("reply type of method %s not exported{%v}", mname, replyType) + return nil + } } - // Method needs one out. - if mtype.NumOut() != 1 { - log.Error("method %q has %d out parameters; needs exactly 1", mname, mtype.NumOut()) - return nil + + index := 1 + + // ctxType + if mtype.In(1).String() == "context.Context" { + ctxType = mtype.In(1) + index = 2 } - // The return type of the method must be error. - if returnType := mtype.Out(0); returnType != typeOfError { - log.Error("return type %s of method %q is not error", returnType, mname) - return nil + + for ; index < inNum; index++ { + argsType = append(argsType, mtype.In(index)) + // need not be a pointer. + if !isExportedOrBuiltinType(mtype.In(index)) { + log.Error("argument type of method %q is not exported %v", mname, mtype.In(index)) + return nil + } } - return &MethodType{method: method, argType: argType, replyType: replyType, ctxType: ctxType} + return &MethodType{method: method, argsType: argsType, replyType: replyType, ctxType: ctxType} } diff --git a/common/rpc_service_test.go b/common/rpc_service_test.go index 5d5c7283b..41476149c 100644 --- a/common/rpc_service_test.go +++ b/common/rpc_service_test.go @@ -30,9 +30,8 @@ type TestService struct { func (s *TestService) MethodOne(ctx context.Context, args []interface{}, rsp *struct{}) error { return nil } -func (s *TestService) MethodTwo(args []interface{}, rsp *struct{}) error { - return nil - +func (s *TestService) MethodTwo(args []interface{}) (struct{}, error) { + return struct{}{}, nil } func (s *TestService) Service() string { return "com.test.Path" @@ -50,8 +49,8 @@ func (s *testService) Method1(ctx context.Context, args testService, rsp *struct func (s *testService) Method2(ctx context.Context, args []interface{}, rsp struct{}) error { return nil } -func (s *testService) Method3(ctx context.Context, args []interface{}, rsp *testService) error { - return nil +func (s *testService) Method3(ctx context.Context, args []interface{}) (testService, error) { + return testService{}, nil } func (s *testService) Method4(ctx context.Context, args []interface{}, rsp *struct{}) { } @@ -131,33 +130,33 @@ func TestMethodType_SuiteContext(t *testing.T) { } func TestSuiteMethod(t *testing.T) { - // 4 + s := &TestService{} method, ok := reflect.TypeOf(s).MethodByName("MethodOne") assert.True(t, ok) methodType := suiteMethod(method) method = methodType.Method() assert.Equal(t, "func(*common.TestService, context.Context, []interface {}, *struct {}) error", method.Type.String()) - at := methodType.ArgType() - assert.Equal(t, "[]interface {}", at.String()) + at := methodType.ArgsType() + assert.Equal(t, "[]interface {}", at[0].String()) + assert.Equal(t, "*struct {}", at[1].String()) ct := methodType.CtxType() assert.Equal(t, "context.Context", ct.String()) rt := methodType.ReplyType() - assert.Equal(t, "*struct {}", rt.String()) + assert.Nil(t, rt) - // 3 method, ok = reflect.TypeOf(s).MethodByName("MethodTwo") assert.True(t, ok) methodType = suiteMethod(method) method = methodType.Method() - assert.Equal(t, "func(*common.TestService, []interface {}, *struct {}) error", method.Type.String()) - at = methodType.ArgType() - assert.Equal(t, "[]interface {}", at.String()) + assert.Equal(t, "func(*common.TestService, []interface {}) (struct {}, error)", method.Type.String()) + at = methodType.ArgsType() + assert.Equal(t, "[]interface {}", at[0].String()) assert.Nil(t, methodType.CtxType()) rt = methodType.ReplyType() - assert.Equal(t, "*struct {}", rt.String()) + assert.Equal(t, "struct {}", rt.String()) - // wrong number of in parameters + // wrong number of in return s1 := &testService{} method, ok = reflect.TypeOf(s1).MethodByName("Version") assert.True(t, ok) diff --git a/examples/dubbo/go-client/app/client.go b/examples/dubbo/go-client/app/client.go index 89c35a6c6..62ae4a105 100644 --- a/examples/dubbo/go-client/app/client.go +++ b/examples/dubbo/go-client/app/client.go @@ -83,7 +83,7 @@ func main() { println("response result: %v", user) println("\n\n\nstart to test dubbo - GetUser0") - ret, err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).GetUser0(context.TODO(), "A003") + ret, err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).GetUser0("A003", "Moorse") if err != nil { panic(err) } diff --git a/examples/dubbo/go-client/app/user.go b/examples/dubbo/go-client/app/user.go index c6dfc9ebd..4ec6c5af3 100644 --- a/examples/dubbo/go-client/app/user.go +++ b/examples/dubbo/go-client/app/user.go @@ -94,7 +94,7 @@ func (User) JavaClassName() string { type UserProvider struct { GetUser func(ctx context.Context, req []interface{}, rsp *User) error - GetUser0 func(ctx context.Context, req interface{}) (User, error) `dubbo:"GetUser"` + GetUser0 func(id string, name string) (User, error) GetUser1 func(ctx context.Context, req []interface{}, rsp *User) error GetUser2 func(ctx context.Context, req []interface{}, rsp *User) error `dubbo:"getUser"` Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used diff --git a/examples/dubbo/go-server/app/user.go b/examples/dubbo/go-server/app/user.go index 1e31338e3..02aa25413 100644 --- a/examples/dubbo/go-server/app/user.go +++ b/examples/dubbo/go-server/app/user.go @@ -23,6 +23,7 @@ import ( import ( "github.com/dubbogo/hessian2" + perrors "github.com/pkg/errors" ) import ( @@ -137,15 +138,24 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User if err == nil { *rsp = *user println("rsp:%#v", rsp) - // s, _ := json.Marshal(rsp) - // fmt.Println("hello0:", string(s)) - - // s, _ = json.Marshal(*rsp) - // fmt.Println("hello1:", string(s)) } return err } +func (u *UserProvider) GetUser0(id string, name string) (User, error) { + var err error + + println("id:%s, name:%s", id, name) + user, err := u.getUser(id) + if err != nil { + return User{}, err + } + if user.Name != name { + return User{}, perrors.New("name is not " + user.Name) + } + return *user, err +} + func (u *UserProvider) Service() string { return "com.ikurento.user.UserProvider" } diff --git a/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java b/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java index c04acefbe..69229943f 100644 --- a/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java +++ b/examples/dubbo/java-client/src/main/java/com/ikurento/user/Consumer.java @@ -47,6 +47,10 @@ public class Consumer { System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); + User user2 = userProvider.GetUser0("A003","Moorse"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() + + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); } catch (Exception e) { e.printStackTrace(); } diff --git a/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java b/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java index add09807e..d5bce8105 100644 --- a/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java +++ b/examples/dubbo/java-client/src/main/java/com/ikurento/user/UserProvider.java @@ -1,12 +1,12 @@ /* * Copyright 1999-2011 Alibaba Group. - * + * * Licensed 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. @@ -22,4 +22,5 @@ public interface UserProvider { User GetUser(String userId); List<User> GetUsers(List<String> userIdList); + User GetUser0(String userId, String name); } diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java index 55ec64c24..b75740bbc 100644 --- a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java +++ b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProvider.java @@ -12,6 +12,8 @@ public interface UserProvider { List<User> GetUsers(List<String> userIdList); + User GetUser0(String userId, String name); + Map<String, User> GetUserMap(List<String> userIdList); User getUser(int usercode); diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java index ff051a97e..f0d7faf3d 100644 --- a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java +++ b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java @@ -32,6 +32,10 @@ public class UserProviderAnotherImpl implements UserProvider { return new User(userId, "Joe", 48); } + public User GetUser0(String userId, String name) { + return new User(userId, name, 48); + } + public List<User> GetUsers(ArrayList<String> userIdList) { Iterator it = userIdList.iterator(); List<User> userList = new ArrayList<User>(); diff --git a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java index 2464ca1c2..1311bd807 100644 --- a/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java +++ b/examples/dubbo/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java @@ -32,6 +32,9 @@ public class UserProviderImpl implements UserProvider { public User GetUser(String userId) { return new User(userId, "zhangsan", 18); } + public User GetUser0(String userId, String name) { + return new User(userId, name, 18); + } public List<User> GetUsers(List<String> userIdList) { Iterator it = userIdList.iterator(); diff --git a/examples/jsonrpc/go-client/app/client.go b/examples/jsonrpc/go-client/app/client.go index 304165ca9..4dd53dff3 100644 --- a/examples/jsonrpc/go-client/app/client.go +++ b/examples/jsonrpc/go-client/app/client.go @@ -79,7 +79,7 @@ func main() { println("response result: %v", user) println("\n\n\nstart to test dubbo - GetUser0") - ret, err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).GetUser0(context.TODO(), "A003") + ret, err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).GetUser0("A003", "Moorse") if err != nil { panic(err) } diff --git a/examples/jsonrpc/go-client/app/user.go b/examples/jsonrpc/go-client/app/user.go index 8d9f7fa5b..8cfc84bca 100644 --- a/examples/jsonrpc/go-client/app/user.go +++ b/examples/jsonrpc/go-client/app/user.go @@ -45,7 +45,7 @@ func (u JsonRPCUser) String() string { type UserProvider struct { GetUser func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error - GetUser0 func(ctx context.Context, req interface{}) (*JsonRPCUser, error) `dubbo:"GetUser"` + GetUser0 func(id string, name string) (JsonRPCUser, error) GetUser1 func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error GetUser2 func(ctx context.Context, req []interface{}, rsp *JsonRPCUser) error `dubbo:"getUser"` Echo func(ctx context.Context, req interface{}) (interface{}, error) // Echo represent EchoFilter will be used diff --git a/examples/jsonrpc/go-server/app/user.go b/examples/jsonrpc/go-server/app/user.go index 4f65f4282..cdf95ba07 100644 --- a/examples/jsonrpc/go-server/app/user.go +++ b/examples/jsonrpc/go-server/app/user.go @@ -20,6 +20,10 @@ import ( "time" ) +import ( + perrors "github.com/pkg/errors" +) + import ( "github.com/dubbo/go-for-apache-dubbo/config" ) @@ -106,6 +110,20 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User return err } +func (u *UserProvider) GetUser0(id string, name string) (User, error) { + var err error + + println("id:%s, name:%s", id, name) + user, err := u.getUser(id) + if err != nil { + return User{}, err + } + if user.Name != name { + return User{}, perrors.New("name is not " + user.Name) + } + return *user, err +} + func (u *UserProvider) Service() string { return "com.ikurento.user.UserProvider" } diff --git a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java index fec159724..832f78e85 100644 --- a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java +++ b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/Consumer.java @@ -51,6 +51,10 @@ public class Consumer { System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + " UserInfo, Id:" + user1.getId() + ", name:" + user1.getName() + ", sex:" + user1.getSex().toString() + ", age:" + user1.getAge() + ", time:" + user1.getTime().toString()); + User user2 = userProvider.GetUser0("A003","Moorse"); + System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] " + + " UserInfo, Id:" + user2.getId() + ", name:" + user2.getName() + ", sex:" + user2.getSex().toString() + + ", age:" + user2.getAge() + ", time:" + user2.getTime().toString()); } catch (Exception e) { e.printStackTrace(); } diff --git a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java index add09807e..d5bce8105 100644 --- a/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java +++ b/examples/jsonrpc/java-client/src/main/java/com/ikurento/user/UserProvider.java @@ -1,12 +1,12 @@ /* * Copyright 1999-2011 Alibaba Group. - * + * * Licensed 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. @@ -22,4 +22,5 @@ public interface UserProvider { User GetUser(String userId); List<User> GetUsers(List<String> userIdList); + User GetUser0(String userId, String name); } diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java index 55ec64c24..b75740bbc 100644 --- a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java +++ b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProvider.java @@ -12,6 +12,8 @@ public interface UserProvider { List<User> GetUsers(List<String> userIdList); + User GetUser0(String userId, String name); + Map<String, User> GetUserMap(List<String> userIdList); User getUser(int usercode); diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java index ff051a97e..157253575 100644 --- a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java +++ b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderAnotherImpl.java @@ -32,6 +32,10 @@ public class UserProviderAnotherImpl implements UserProvider { return new User(userId, "Joe", 48); } + public User GetUser0(String userId, String name) { + return new User(userId, name, 48); + } + public List<User> GetUsers(ArrayList<String> userIdList) { Iterator it = userIdList.iterator(); List<User> userList = new ArrayList<User>(); diff --git a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java index 2464ca1c2..25e97dd1c 100644 --- a/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java +++ b/examples/jsonrpc/java-server/src/main/java/com/ikurento/user/UserProviderImpl.java @@ -33,6 +33,10 @@ public class UserProviderImpl implements UserProvider { return new User(userId, "zhangsan", 18); } + public User GetUser0(String userId, String name) { + return new User(userId, name, 18); + } + public List<User> GetUsers(List<String> userIdList) { Iterator it = userIdList.iterator(); List<User> userList = new ArrayList<User>(); diff --git a/protocol/dubbo/client_test.go b/protocol/dubbo/client_test.go index 5631d9747..2938f569d 100644 --- a/protocol/dubbo/client_test.go +++ b/protocol/dubbo/client_test.go @@ -183,10 +183,8 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User return nil } -func (u *UserProvider) GetUser0(req []interface{}, rsp *User) error { - rsp.Id = req[0].(string) - rsp.Name = req[1].(string) - return nil +func (u *UserProvider) GetUser0(id string, name string) (User, error) { + return User{Id: id, Name: name}, nil } func (u *UserProvider) GetUser1(ctx context.Context, req []interface{}, rsp *User) error { diff --git a/protocol/dubbo/listener.go b/protocol/dubbo/listener.go index a1268497e..5817e3e22 100644 --- a/protocol/dubbo/listener.go +++ b/protocol/dubbo/listener.go @@ -291,24 +291,38 @@ func (h *RpcServerHandler) callService(req *DubboPackage, ctx context.Context) { return } - // prepare argv - argv := req.Body.(map[string]interface{})["args"] // type is []interface + in := []reflect.Value{svc.Rcvr()} + if method.CtxType() != nil { + in = append(in, method.SuiteContext(ctx)) + } - // prepare replyv - replyv := reflect.New(method.ReplyType().Elem()) - var returnValues []reflect.Value - if method.CtxType() == nil { - returnValues = method.Method().Func.Call([]reflect.Value{svc.Rcvr(), reflect.ValueOf(argv), reflect.ValueOf(replyv.Interface())}) + // prepare argv + argv := req.Body.(map[string]interface{})["args"] + if (len(method.ArgsType()) == 1 || len(method.ArgsType()) == 2 && method.ReplyType() == nil) && method.ArgsType()[0].String() == "[]interface {}" { + in = append(in, reflect.ValueOf(argv)) } else { - if contextv := reflect.ValueOf(ctx); contextv.IsValid() { - returnValues = method.Method().Func.Call([]reflect.Value{svc.Rcvr(), contextv, reflect.ValueOf(argv), reflect.ValueOf(replyv.Interface())}) - } else { - returnValues = method.Method().Func.Call([]reflect.Value{svc.Rcvr(), reflect.Zero(method.CtxType()), reflect.ValueOf(argv), reflect.ValueOf(replyv.Interface())}) + for i := 0; i < len(argv.([]interface{})); i++ { + in = append(in, reflect.ValueOf(argv.([]interface{})[i])) } } - // The return value for the method is an error. - if retErr := returnValues[0].Interface(); retErr != nil { + // prepare replyv + var replyv reflect.Value + if method.ReplyType() == nil { + replyv = reflect.New(method.ArgsType()[len(method.ArgsType())-1].Elem()) + in = append(in, replyv) + } + + returnValues := method.Method().Func.Call(in) + + var retErr interface{} + if len(returnValues) == 1 { + retErr = returnValues[0].Interface() + } else { + replyv = returnValues[0] + retErr = returnValues[1].Interface() + } + if retErr != nil { req.Header.ResponseStatus = hessian.Response_SERVER_ERROR req.Body = retErr.(error) } else { diff --git a/protocol/jsonrpc/http_test.go b/protocol/jsonrpc/http_test.go index 11db1f9cd..e70d5b83f 100644 --- a/protocol/jsonrpc/http_test.go +++ b/protocol/jsonrpc/http_test.go @@ -111,10 +111,8 @@ func (u *UserProvider) GetUser(ctx context.Context, req []interface{}, rsp *User return nil } -func (u *UserProvider) GetUser0(req []interface{}, rsp *User) error { - rsp.Id = req[0].(string) - rsp.Name = req[1].(string) - return nil +func (u *UserProvider) GetUser0(id string, name string) (User, error) { + return User{Id: id, Name: name}, nil } func (u *UserProvider) GetUser1(ctx context.Context, req []interface{}, rsp *User) error { diff --git a/protocol/jsonrpc/server.go b/protocol/jsonrpc/server.go index c514bfcdc..a54dcb9d0 100644 --- a/protocol/jsonrpc/server.go +++ b/protocol/jsonrpc/server.go @@ -354,34 +354,45 @@ func serveRequest(ctx context.Context, if svc == nil { return perrors.New("cannot find svc " + serviceName) } - mtype := svc.Method()[methodName] - if mtype == nil { + method := svc.Method()[methodName] + if method == nil { return perrors.New("cannot find method " + methodName + " of svc " + serviceName) } - replyv := reflect.New(mtype.ReplyType().Elem()) + in := []reflect.Value{svc.Rcvr()} + if method.CtxType() != nil { + in = append(in, method.SuiteContext(ctx)) + } + + // prepare argv + if (len(method.ArgsType()) == 1 || len(method.ArgsType()) == 2 && method.ReplyType() == nil) && method.ArgsType()[0].String() == "[]interface {}" { + in = append(in, reflect.ValueOf(args)) + } else { + for i := 0; i < len(args.([]interface{})); i++ { + in = append(in, reflect.ValueOf(args.([]interface{})[i])) + } + } + + // prepare replyv + var replyv reflect.Value + if method.ReplyType() == nil { + replyv = reflect.New(method.ArgsType()[len(method.ArgsType())-1].Elem()) + in = append(in, replyv) + } + + returnValues := method.Method().Func.Call(in) - // call service.method(args) var ( - errMsg string - returnValues []reflect.Value + retErr interface{} + errMsg string ) - if mtype.CtxType() == nil { - returnValues = mtype.Method().Func.Call([]reflect.Value{ - svc.Rcvr(), - reflect.ValueOf(args), - reflect.ValueOf(replyv.Interface()), - }) + if len(returnValues) == 1 { + retErr = returnValues[0].Interface() } else { - returnValues = mtype.Method().Func.Call([]reflect.Value{ - svc.Rcvr(), - mtype.SuiteContext(ctx), - reflect.ValueOf(args), - reflect.ValueOf(replyv.Interface()), - }) + replyv = returnValues[0] + retErr = returnValues[1].Interface() } - // The return value for the method is an error. - if retErr := returnValues[0].Interface(); retErr != nil { + if retErr != nil { errMsg = retErr.(error).Error() } -- GitLab