dubbo.apache.org/dubbo-go/v3@v3.1.1/proxy/proxy_factory/pass_through.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package proxy_factory 19 20 import ( 21 "context" 22 "reflect" 23 ) 24 25 import ( 26 "github.com/dubbogo/gost/log/logger" 27 28 perrors "github.com/pkg/errors" 29 ) 30 31 import ( 32 "dubbo.apache.org/dubbo-go/v3/common" 33 "dubbo.apache.org/dubbo-go/v3/common/constant" 34 "dubbo.apache.org/dubbo-go/v3/common/extension" 35 "dubbo.apache.org/dubbo-go/v3/protocol" 36 "dubbo.apache.org/dubbo-go/v3/proxy" 37 ) 38 39 func init() { 40 extension.SetProxyFactory(constant.PassThroughProxyFactoryKey, NewPassThroughProxyFactory) 41 } 42 43 // PassThroughProxyFactory is the factory of PassThroughProxyInvoker 44 type PassThroughProxyFactory struct { 45 } 46 47 // NewPassThroughProxyFactory returns a proxy factory instance 48 func NewPassThroughProxyFactory(_ ...proxy.Option) proxy.ProxyFactory { 49 return &PassThroughProxyFactory{} 50 } 51 52 // GetProxy gets a proxy 53 func (factory *PassThroughProxyFactory) GetProxy(invoker protocol.Invoker, url *common.URL) *proxy.Proxy { 54 return factory.GetAsyncProxy(invoker, nil, url) 55 } 56 57 // GetAsyncProxy gets a async proxy 58 func (factory *PassThroughProxyFactory) GetAsyncProxy(invoker protocol.Invoker, callBack interface{}, url *common.URL) *proxy.Proxy { 59 //create proxy 60 attachments := map[string]string{} 61 attachments[constant.AsyncKey] = url.GetParam(constant.AsyncKey, "false") 62 return proxy.NewProxy(invoker, callBack, attachments) 63 } 64 65 // GetInvoker gets a invoker 66 func (factory *PassThroughProxyFactory) GetInvoker(url *common.URL) protocol.Invoker { 67 return &PassThroughProxyInvoker{ 68 ProxyInvoker: &ProxyInvoker{ 69 BaseInvoker: *protocol.NewBaseInvoker(url), 70 }, 71 } 72 } 73 74 // PassThroughProxyInvoker is a invoker struct, it calls service with specific method 'Serivce' and params: 75 // Service(method string, argsTypes []string, args [][]byte, attachment map[string]interface{}) 76 // PassThroughProxyInvoker pass through raw invocation data and method name to service, which will deal with them. 77 type PassThroughProxyInvoker struct { 78 *ProxyInvoker 79 } 80 81 // Invoke is used to call service method by invocation 82 func (pi *PassThroughProxyInvoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result { 83 result := &protocol.RPCResult{} 84 result.SetAttachments(invocation.Attachments()) 85 url := getProviderURL(pi.GetURL()) 86 87 arguments := invocation.Arguments() 88 srv := common.ServiceMap.GetServiceByServiceKey(url.Protocol, url.ServiceKey()) 89 90 var args [][]byte 91 if len(arguments) > 0 { 92 args = make([][]byte, 0, len(arguments)) 93 for _, arg := range arguments { 94 if v, ok := arg.([]byte); ok { 95 args = append(args, v) 96 } else { 97 result.Err = perrors.New("the param type is not []byte") 98 return result 99 } 100 } 101 } 102 method := srv.Method()["Service"] 103 104 in := make([]reflect.Value, 5) 105 in = append(in, srv.Rcvr()) 106 in = append(in, reflect.ValueOf(invocation.MethodName())) 107 in = append(in, reflect.ValueOf(invocation.GetAttachmentInterface(constant.ParamsTypeKey))) 108 in = append(in, reflect.ValueOf(args)) 109 in = append(in, reflect.ValueOf(invocation.Attachments())) 110 111 var replyv reflect.Value 112 var retErr interface{} 113 114 returnValues, callErr := callLocalMethod(method.Method(), in) 115 116 if callErr != nil { 117 logger.Errorf("Invoke function error: %+v, service: %#v", callErr, url) 118 result.SetError(callErr) 119 return result 120 } 121 122 replyv = returnValues[0] 123 retErr = returnValues[1].Interface() 124 125 if retErr != nil { 126 result.SetError(retErr.(error)) 127 return result 128 } 129 if replyv.IsValid() && (replyv.Kind() != reflect.Ptr || replyv.Kind() == reflect.Ptr && replyv.Elem().IsValid()) { 130 result.SetResult(replyv.Interface()) 131 } 132 133 return result 134 }