Skip to content
Snippets Groups Projects
Commit 5cbba12b authored by Patrick's avatar Patrick
Browse files

rest configs and invoker

parent 64b94391
No related branches found
No related tags found
No related merge requests found
Showing
with 600 additions and 21 deletions
package extension
import (
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
)
var (
restClients = make(map[string]func(restOptions *rest_interface.RestOptions) rest_interface.RestClient)
)
func SetRestClient(name string, fun func(restOptions *rest_interface.RestOptions) rest_interface.RestClient) {
restClients[name] = fun
}
func GetRestClient(name string, restOptions *rest_interface.RestOptions) rest_interface.RestClient {
if restClients[name] == nil {
panic("restClient for " + name + " is not existing, make sure you have import the package.")
}
return restClients[name](restOptions)
}
package extension
import (
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
)
var (
restConfigReaders = make(map[string]func() rest_interface.RestConfigReader)
)
func SetRestConfigReader(name string, fun func() rest_interface.RestConfigReader) {
restConfigReaders[name] = fun
}
func GetRestConfigReader(name string) rest_interface.RestConfigReader {
if name == "" {
name = "default"
}
if restConfigReaders[name] == nil {
panic("restConfigReaders for " + name + " is not existing, make sure you have import the package.")
}
return restConfigReaders[name]()
}
......@@ -58,6 +58,7 @@ type ConsumerConfig struct {
ProtocolConf interface{} `yaml:"protocol_conf" json:"protocol_conf,omitempty" property:"protocol_conf"`
FilterConf interface{} `yaml:"filter_conf" json:"filter_conf,omitempty" property:"filter_conf" `
ShutdownConfig *ShutdownConfig `yaml:"shutdown_conf" json:"shutdown_conf,omitempty" property:"shutdown_conf" `
RestConfigType string `default:"default" yaml:"rest_config_type" json:"rest_config_type,omitempty" property:"rest_config_type"`
}
func (c *ConsumerConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
......
......@@ -50,6 +50,7 @@ type ProviderConfig struct {
ProtocolConf interface{} `yaml:"protocol_conf" json:"protocol_conf,omitempty" property:"protocol_conf" `
FilterConf interface{} `yaml:"filter_conf" json:"filter_conf,omitempty" property:"filter_conf" `
ShutdownConfig *ShutdownConfig `yaml:"shutdown_conf" json:"shutdown_conf,omitempty" property:"shutdown_conf" `
RestConfigType string `default:"default" yaml:"rest_config_type" json:"rest_config_type,omitempty" property:"rest_config_type"`
}
func (c *ProviderConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
......
......@@ -17,6 +17,7 @@ require (
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
github.com/gin-gonic/gin v1.5.0
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-resty/resty/v2 v2.1.0
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect
github.com/golang/mock v1.3.1
github.com/google/btree v1.0.0 // indirect
......
......@@ -143,6 +143,8 @@ github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotf
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-resty/resty/v2 v2.1.0 h1:Z6IefCpUMfnvItVJaJXWv/pMiiD11So35QgwEELsldE=
github.com/go-resty/resty/v2 v2.1.0/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
github.com/go-sql-driver/mysql v0.0.0-20180618115901-749ddf1598b4 h1:1LlmVz15APoKz9dnm5j2ePptburJlwEH+/v/pUuoxck=
github.com/go-sql-driver/mysql v0.0.0-20180618115901-749ddf1598b4/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
......@@ -507,6 +509,8 @@ golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20170807180024-9a379c6b3e95/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
......
package rest_client
import (
"context"
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
"github.com/go-resty/resty/v2"
"net"
"net/http"
"path"
"time"
)
const (
RESTY = "resty"
)
func init() {
extension.SetRestClient(RESTY, GetRestyClient)
}
var restyClient *RestyClient
type RestyClient struct {
client *resty.Client
}
func NewRestyClient(restOption *rest_interface.RestOptions) *RestyClient {
if restOption.ConnectTimeout == 0 {
restOption.ConnectTimeout = 3
}
if restOption.RequestTimeout == 0 {
restOption.RequestTimeout = 3
}
client := resty.New()
client.SetTransport(
&http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
c, err := net.DialTimeout(network, addr, restOption.ConnectTimeout*time.Second)
if err != nil {
return nil, err
}
err = c.SetDeadline(time.Now().Add(restOption.RequestTimeout * time.Second))
if err != nil {
return nil, err
}
return c, nil
},
})
return &RestyClient{
client: client,
}
}
func (rc *RestyClient) Do(restRequest *rest_interface.RestRequest, res interface{}) error {
_, err := rc.client.R().
SetHeader("Content-Type", restRequest.Consumes).
SetHeader("Accept", restRequest.Produces).
SetPathParams(restRequest.PathParams).
SetQueryParams(restRequest.QueryParams).
SetBody(restRequest.Body).
SetResult(res).
Execute(restRequest.Method, "http://"+path.Join(restRequest.Location, restRequest.Path))
return err
}
func GetRestyClient(restOptions *rest_interface.RestOptions) rest_interface.RestClient {
return NewRestyClient(restOptions)
}
package rest
import (
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/common/logger"
"github.com/apache/dubbo-go/config"
_ "github.com/apache/dubbo-go/protocol/rest/rest_config_reader"
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
"strconv"
"strings"
)
var (
restConsumerConfig *rest_interface.RestConsumerConfig
restProviderConfig *rest_interface.RestProviderConfig
restConsumerServiceConfigMap map[string]*rest_interface.RestConfig
restProviderServiceConfigMap map[string]*rest_interface.RestConfig
)
func init() {
initConsumerRestConfig()
initProviderRestConfig()
}
func initConsumerRestConfig() {
consumerConfigType := config.GetConsumerConfig().RestConfigType
consumerConfigReader := extension.GetRestConfigReader(consumerConfigType)
restConsumerConfig = consumerConfigReader.ReadConsumerConfig()
if restConsumerConfig == nil {
return
}
for _, rc := range restConsumerConfig.RestConfigMap {
rc.Client = getNotEmptyStr(rc.Client, restConsumerConfig.Client, "resty")
rc.RestMethodConfigsMap = initMethodConfigMap(rc, restConsumerConfig.Consumes, restConsumerConfig.Produces)
restConsumerServiceConfigMap[rc.InterfaceName] = rc
}
}
func initProviderRestConfig() {
providerConfigType := config.GetProviderConfig().RestConfigType
providerConfigReader := extension.GetRestConfigReader(providerConfigType)
restProviderConfig = providerConfigReader.ReadProviderConfig()
if restProviderConfig == nil {
return
}
for _, rc := range restProviderConfig.RestConfigMap {
rc.Server = getNotEmptyStr(rc.Server, restProviderConfig.Server)
rc.RestMethodConfigsMap = initMethodConfigMap(rc, restProviderConfig.Consumes, restProviderConfig.Produces)
restProviderServiceConfigMap[rc.InterfaceName] = rc
}
}
func initMethodConfigMap(rc *rest_interface.RestConfig, consumes string, produces string) map[string]*rest_interface.RestMethodConfig {
mcm := make(map[string]*rest_interface.RestMethodConfig, len(rc.RestMethodConfigs))
for _, mc := range rc.RestMethodConfigs {
mc.InterfaceName = rc.InterfaceName
mc.Path = rc.Path + mc.Path
mc.Consumes = getNotEmptyStr(mc.Consumes, rc.Consumes, consumes)
mc.Produces = getNotEmptyStr(mc.Produces, rc.Produces, produces)
mc.MethodType = getNotEmptyStr(mc.MethodType, rc.MethodType)
mc = transformMethodConfig(mc)
mcm[mc.MethodName] = mc
}
return mcm
}
func getNotEmptyStr(args ...string) string {
var r string
for _, t := range args {
if len(r) == 0 {
r = t
} else {
break
}
}
return r
}
func transformMethodConfig(methodConfig *rest_interface.RestMethodConfig) *rest_interface.RestMethodConfig {
if len(methodConfig.PathParamsMap) == 0 && len(methodConfig.PathParams) > 0 {
paramsMap, err := parseParamsString2Map(methodConfig.PathParams)
if err != nil {
logger.Warnf("[Rest Config] Path Param parse error:%v", err)
} else {
methodConfig.PathParamsMap = paramsMap
}
}
if len(methodConfig.QueryParamsMap) == 0 && len(methodConfig.QueryParams) > 0 {
paramsMap, err := parseParamsString2Map(methodConfig.PathParams)
if err != nil {
logger.Warnf("[Rest Config] Argument Param parse error:%v", err)
} else {
methodConfig.QueryParamsMap = paramsMap
}
}
if len(methodConfig.BodyMap) == 0 && len(methodConfig.Body) > 0 {
paramsMap, err := parseParamsString2Map(methodConfig.Body)
if err != nil {
logger.Warnf("[Rest Config] Body Param parse error:%v", err)
} else {
methodConfig.BodyMap = paramsMap
}
}
return methodConfig
}
func parseParamsString2Map(params string) (map[int]string, error) {
m := make(map[int]string)
for _, p := range strings.Split(params, ",") {
pa := strings.Split(p, ":")
key, err := strconv.Atoi(pa[0])
if err != nil {
return nil, err
}
m[key] = pa[1]
}
return m, nil
}
func GetRestConsumerServiceConfig(service string) *rest_interface.RestConfig {
return restConsumerServiceConfigMap[service]
}
func GetRestProviderServiceConfig(service string) *rest_interface.RestConfig {
return restProviderServiceConfigMap[service]
}
func SetRestConsumerServiceConfigMap(configMap map[string]*rest_interface.RestConfig) {
restConsumerServiceConfigMap = configMap
}
package rest_config_reader
import (
"github.com/apache/dubbo-go/common/constant"
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/common/logger"
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
perrors "github.com/pkg/errors"
"gopkg.in/yaml.v2"
"io/ioutil"
"os"
"path"
)
const (
DEFAULT_READER = "default"
)
var (
defaultConfigReader *DefaultConfigReader
)
func init() {
extension.SetRestConfigReader(DEFAULT_READER, GetDefaultConfigReader)
}
type DefaultConfigReader struct {
}
func NewDefaultConfigReader() *DefaultConfigReader {
return &DefaultConfigReader{}
}
func (dcr *DefaultConfigReader) ReadConsumerConfig() *rest_interface.RestConsumerConfig {
confConFile := os.Getenv(constant.CONF_CONSUMER_FILE_PATH)
if confConFile == "" {
logger.Warnf("rest consumer configure(consumer) file name is nil")
return nil
}
if path.Ext(confConFile) != ".yml" {
logger.Warnf("rest consumer configure file name{%v} suffix must be .yml", confConFile)
return nil
}
confFileStream, err := ioutil.ReadFile(confConFile)
if err != nil {
logger.Warnf("ioutil.ReadFile(file:%s) = error:%v", confConFile, perrors.WithStack(err))
return nil
}
restConsumerConfig := &rest_interface.RestConsumerConfig{}
err = yaml.Unmarshal(confFileStream, restConsumerConfig)
if err != nil {
logger.Warnf("yaml.Unmarshal() = error:%v", perrors.WithStack(err))
return nil
}
return restConsumerConfig
}
func (dcr *DefaultConfigReader) ReadProviderConfig() *rest_interface.RestProviderConfig {
confProFile := os.Getenv(constant.CONF_PROVIDER_FILE_PATH)
if len(confProFile) == 0 {
logger.Warnf("rest provider configure(provider) file name is nil")
return nil
}
if path.Ext(confProFile) != ".yml" {
logger.Warnf("rest provider configure file name{%v} suffix must be .yml", confProFile)
return nil
}
confFileStream, err := ioutil.ReadFile(confProFile)
if err != nil {
logger.Warnf("ioutil.ReadFile(file:%s) = error:%v", confProFile, perrors.WithStack(err))
return nil
}
restProviderConfig := &rest_interface.RestProviderConfig{}
err = yaml.Unmarshal(confFileStream, restProviderConfig)
if err != nil {
logger.Warnf("yaml.Unmarshal() = error:%v", perrors.WithStack(err))
return nil
}
return restProviderConfig
}
func GetDefaultConfigReader() rest_interface.RestConfigReader {
if defaultConfigReader == nil {
defaultConfigReader = NewDefaultConfigReader()
}
return defaultConfigReader
}
package rest_interface
import (
"time"
)
type RestOptions struct {
RequestTimeout time.Duration
ConnectTimeout time.Duration
}
type RestRequest struct {
Location string
Path string
Produces string
Consumes string
Method string
PathParams map[string]string
QueryParams map[string]string
Body map[string]interface{}
}
type RestClient interface {
Do(request *RestRequest, res interface{}) error
}
package rest_interface
type RestConfig struct {
InterfaceName string `required:"true" yaml:"interface" json:"interface,omitempty" property:"interface"`
Url string `yaml:"url" json:"url,omitempty" property:"url"`
Path string `yaml:"rest_path" json:"rest_path,omitempty" property:"rest_path"`
Produces string `yaml:"rest_produces" json:"rest_produces,omitempty" property:"rest_produces"`
Consumes string `yaml:"rest_consumes" json:"rest_consumes,omitempty" property:"rest_consumes"`
MethodType string `yaml:"rest_method" json:"rest_method,omitempty" property:"rest_method"`
Client string `yaml:"rest_client" json:"rest_client,omitempty" property:"rest_client"`
Server string `yaml:"rest_server" json:"rest_server,omitempty" property:"rest_server"`
RestMethodConfigs []*RestMethodConfig `yaml:"methods" json:"methods,omitempty" property:"methods"`
RestMethodConfigsMap map[string]*RestMethodConfig
}
type RestConsumerConfig struct {
Client string `default:"resty" yaml:"rest_client" json:"rest_client,omitempty" property:"rest_client"`
Produces string `yaml:"rest_produces" json:"rest_produces,omitempty" property:"rest_produces"`
Consumes string `yaml:"rest_consumes" json:"rest_consumes,omitempty" property:"rest_consumes"`
RestConfigMap map[string]*RestConfig `yaml:"references" json:"references,omitempty" property:"references"`
}
type RestProviderConfig struct {
Server string `default:"go-restful" yaml:"rest_server" json:"rest_server,omitempty" property:"rest_server"`
Produces string `yaml:"rest_produces" json:"rest_produces,omitempty" property:"rest_produces"`
Consumes string `yaml:"rest_consumes" json:"rest_consumes,omitempty" property:"rest_consumes"`
RestConfigMap map[string]*RestConfig `yaml:"services" json:"services,omitempty" property:"services"`
}
package rest_interface
type RestConfigReader interface {
ReadConsumerConfig() *RestConsumerConfig
ReadProviderConfig() *RestProviderConfig
}
package rest_interface
type RestMethodConfig struct {
InterfaceName string
MethodName string `required:"true" yaml:"name" json:"name,omitempty" property:"name"`
Url string `yaml:"url" json:"url,omitempty" property:"url"`
Path string `yaml:"rest_path" json:"rest_path,omitempty" property:"rest_path"`
Produces string `yaml:"rest_produces" json:"rest_produces,omitempty" property:"rest_produces"`
Consumes string `yaml:"rest_consumes" json:"rest_consumes,omitempty" property:"rest_consumes"`
MethodType string `yaml:"rest_method" json:"rest_method,omitempty" property:"rest_method"`
PathParams string `yaml:"rest_path_params" json:"rest_path_params,omitempty" property:"rest_path_params"`
PathParamsMap map[int]string
QueryParams string `yaml:"rest_query_params" json:"rest_query_params,omitempty" property:"rest_query_params"`
QueryParamsMap map[int]string
Body string `yaml:"rest_body" json:"rest_body,omitempty" property:"rest_body"`
BodyMap map[int]string
}
package rest
import (
"fmt"
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/logger"
"github.com/apache/dubbo-go/protocol"
"net/http"
invocation_impl "github.com/apache/dubbo-go/protocol/invocation"
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
)
type RestInvoker struct {
protocol.BaseInvoker
client *http.Client
client rest_interface.RestClient
restMethodConfigMap map[string]*rest_interface.RestMethodConfig
}
func NewRestInvoker() *RestInvoker {
return &RestInvoker{}
func NewRestInvoker(url common.URL, client rest_interface.RestClient, restMethodConfig map[string]*rest_interface.RestMethodConfig) *RestInvoker {
return &RestInvoker{
BaseInvoker: *protocol.NewBaseInvoker(url),
client: client,
restMethodConfigMap: restMethodConfig,
}
}
func (ri *RestInvoker) Invoke(invocation protocol.Invocation) protocol.Result {
// TODO 首先,将本地调用和ReferRestConfig,结合在一起,到这一步完成了Service -> Rest的绑定;
// 第一步完成的产物是一份metadata和请求参数,本步骤将利用metadata和请求参数来构造http请求,包括参数序列化,header设定;其中参数序列化可以是Json,也可以是XML,后续可以扩展到多媒体等;
// http client发送请求。该步骤要允许用户自定义其连接参数,例如超时时间等;
//var (
// result protocol.RPCResult
//)
//req, err := http.NewRequest("method", "url", bytes.NewBuffer([]byte{}))
//resp, err := ri.client.Do(req)
//defer resp.Body.Close()
//body, err := ioutil.ReadAll(resp.Body)
//result.Rest = invocation.Reply()
//return &result
return nil
inv := invocation.(*invocation_impl.RPCInvocation)
methodConfig := ri.restMethodConfigMap[inv.MethodName()]
var result protocol.RPCResult
if methodConfig == nil {
logger.Errorf("[RestInvoker]Rest methodConfig:%s is nill", inv.MethodName())
return nil
}
pathParams := make(map[string]string)
queryParams := make(map[string]string)
bodyParams := make(map[string]interface{})
for key, value := range methodConfig.PathParamsMap {
pathParams[value] = fmt.Sprintf("%v", inv.Arguments()[key])
}
for key, value := range methodConfig.QueryParamsMap {
queryParams[value] = fmt.Sprintf("%v", inv.Arguments()[key])
}
for key, value := range methodConfig.BodyMap {
bodyParams[value] = inv.Arguments()[key]
}
req := &rest_interface.RestRequest{
Location: ri.GetUrl().Location,
Produces: methodConfig.Produces,
Consumes: methodConfig.Consumes,
Method: methodConfig.MethodType,
Path: methodConfig.Path,
PathParams: pathParams,
QueryParams: queryParams,
Body: bodyParams,
}
result.Err = ri.client.Do(req, inv.Reply())
if result.Err == nil {
result.Rest = inv.Reply()
}
return &result
}
package rest
import (
"context"
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/config"
"github.com/apache/dubbo-go/protocol/invocation"
"github.com/apache/dubbo-go/protocol/rest/rest_client"
_ "github.com/apache/dubbo-go/protocol/rest/rest_config_reader"
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
"github.com/stretchr/testify/assert"
"testing"
"time"
)
type User struct {
}
func TestRestInvoker_Invoke(t *testing.T) {
// Refer
proto := GetRestProtocol()
url, err := common.NewURL(context.Background(), "rest://127.0.0.1:8888/com.ikurento.user.UserProvider?anyhost=true&"+
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"+
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"+
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"+
"side=provider&timeout=3000&timestamp=1556509797245")
assert.NoError(t, err)
con := config.ConsumerConfig{
ConnectTimeout: 1 * time.Second,
RequestTimeout: 1 * time.Second,
RestConfigType: "default",
}
config.SetConsumerConfig(con)
configMap := make(map[string]*rest_interface.RestConfig)
methodConfigMap := make(map[string]*rest_interface.RestMethodConfig)
methodConfigMap["GetUser"] = &rest_interface.RestMethodConfig{
InterfaceName: "",
MethodName: "GetUser",
Path: "/GetUser",
Produces: "application/json",
Consumes: "application/json",
MethodType: "GET",
PathParams: "",
PathParamsMap: nil,
QueryParams: "",
QueryParamsMap: nil,
Body: "",
BodyMap: nil,
}
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestConfig{
RestMethodConfigsMap: methodConfigMap,
}
restClient := rest_client.GetRestyClient(&rest_interface.RestOptions{ConnectTimeout: 5 * time.Second, RequestTimeout: 5 * time.Second})
invoker := NewRestInvoker(url, restClient, methodConfigMap)
user := &User{}
inv := invocation.NewRPCInvocationWithOptions(invocation.WithMethodName("GetUser"),
invocation.WithArguments([]interface{}{"1", "username"}), invocation.WithReply(user))
invoker.Invoke(inv)
// make sure url
eq := invoker.GetUrl().URLEqual(url)
assert.True(t, eq)
// make sure invokers after 'Destroy'
invokersLen := len(proto.(*RestProtocol).Invokers())
assert.Equal(t, 1, invokersLen)
proto.Destroy()
invokersLen = len(proto.(*RestProtocol).Invokers())
assert.Equal(t, 0, invokersLen)
}
......@@ -2,13 +2,24 @@ package rest
import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/constant"
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/config"
"github.com/apache/dubbo-go/protocol"
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
"time"
)
var (
restProtocol *RestProtocol
)
const REST = "rest"
func init() {
extension.SetProtocol(REST, GetRestProtocol)
}
type RestProtocol struct {
protocol.BaseProtocol
}
......@@ -22,18 +33,28 @@ func (rp *RestProtocol) Export(invoker protocol.Invoker) protocol.Exporter {
// Server在Export的时候并不做什么事情。但是在接受到请求的时候,它需要负责执行反序列化的过程;
// http server是一个抽象隔离层。它内部允许使用beego或者gin来作为web服务器,接收请求,用户可以扩展自己的实现;
// create gin_server
// save gin_server in map
return nil
}
func (rp *RestProtocol) Refer(url common.URL) protocol.Invoker {
// create rest_invoker
return nil
var requestTimeout = config.GetConsumerConfig().RequestTimeout
requestTimeoutStr := url.GetParam(constant.TIMEOUT_KEY, config.GetConsumerConfig().Request_Timeout)
connectTimeout := config.GetConsumerConfig().ConnectTimeout
if t, err := time.ParseDuration(requestTimeoutStr); err == nil {
requestTimeout = t
}
restConfig := GetRestConsumerServiceConfig(url.Service())
restClient := extension.GetRestClient(restConfig.Client, &rest_interface.RestOptions{RequestTimeout: requestTimeout, ConnectTimeout: connectTimeout})
invoker := NewRestInvoker(url, restClient, restConfig.RestMethodConfigsMap)
rp.SetInvokers(invoker)
return invoker
}
func (rp *RestProtocol) Destroy() {
// destroy rest_server
rp.BaseProtocol.Destroy()
}
func GetRestProtocol() protocol.Protocol {
......
package rest
import (
"context"
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/config"
"github.com/apache/dubbo-go/protocol/rest/rest_interface"
"github.com/stretchr/testify/assert"
"testing"
"time"
)
func TestRestProtocol_Refer(t *testing.T) {
// Refer
proto := GetRestProtocol()
url, err := common.NewURL(context.Background(), "rest://127.0.0.1:20000/com.ikurento.user.UserProvider?anyhost=true&"+
"application=BDTService&category=providers&default.timeout=10000&dubbo=dubbo-provider-golang-1.0.0&"+
"environment=dev&interface=com.ikurento.user.UserProvider&ip=192.168.56.1&methods=GetUser%2C&"+
"module=dubbogo+user-info+server&org=ikurento.com&owner=ZX&pid=1447&revision=0.0.1&"+
"side=provider&timeout=3000&timestamp=1556509797245")
assert.NoError(t, err)
con := config.ConsumerConfig{
ConnectTimeout: 5 * time.Second,
RequestTimeout: 5 * time.Second,
}
config.SetConsumerConfig(con)
configMap := make(map[string]*rest_interface.RestConfig)
configMap["com.ikurento.user.UserProvider"] = &rest_interface.RestConfig{}
SetRestConsumerServiceConfigMap(configMap)
invoker := proto.Refer(url)
// make sure url
eq := invoker.GetUrl().URLEqual(url)
assert.True(t, eq)
// make sure invokers after 'Destroy'
invokersLen := len(proto.(*RestProtocol).Invokers())
assert.Equal(t, 1, invokersLen)
proto.Destroy()
invokersLen = len(proto.(*RestProtocol).Invokers())
assert.Equal(t, 0, invokersLen)
}
package rest
package rest_server
import (
"context"
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment