From 4bca016c39f993599b878229609f4c5d8e1c661d Mon Sep 17 00:00:00 2001 From: alanxtl Date: Mon, 1 Jun 2026 18:41:16 +0800 Subject: [PATCH 1/3] add rest samples --- README.md | 1 + README_CN.md | 1 + go.mod | 2 + rpc/rest/README.md | 76 +++++++++++++++ rpc/rest/README_CN.md | 92 ++++++++++++++++++ rpc/rest/api/greeting.go | 41 ++++++++ rpc/rest/api/registry.go | 71 ++++++++++++++ rpc/rest/api/registry_test.go | 29 ++++++ rpc/rest/api/rest_config.go | 63 +++++++++++++ rpc/rest/go-client/cmd/client.go | 117 +++++++++++++++++++++++ rpc/rest/go-server/cmd/server.go | 154 +++++++++++++++++++++++++++++++ start_integrate_test.sh | 1 + 12 files changed, 648 insertions(+) create mode 100644 rpc/rest/README.md create mode 100644 rpc/rest/README_CN.md create mode 100644 rpc/rest/api/greeting.go create mode 100644 rpc/rest/api/registry.go create mode 100644 rpc/rest/api/registry_test.go create mode 100644 rpc/rest/api/rest_config.go create mode 100644 rpc/rest/go-client/cmd/client.go create mode 100644 rpc/rest/go-server/cmd/server.go diff --git a/README.md b/README.md index 6dbf4cff4..c19d288d2 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ Please refer to [HOWTO.md](HOWTO.md) for detailed instructions on running the sa * `rpc/jsonrpc`: JSON-RPC protocol example. * `rpc/triple`: Triple protocol example with multiple serialization formats. * `rpc/triple/openapi`: Demonstrates how to enable OpenAPI documentation for Triple protocol services, including versioned services and non-IDL services. + * `rpc/rest`: Rest protocol example. * `streaming`: Streaming RPC example, also includes Go–Java interoperability when both use streaming. * `task`: Task scheduling and execution example. * `timeout`: Demonstrates timeout handling in Dubbo-go. diff --git a/README_CN.md b/README_CN.md index 5a6fb186d..2372e5236 100644 --- a/README_CN.md +++ b/README_CN.md @@ -70,6 +70,7 @@ * `rpc/jsonrpc`:基于 JSON-RPC 协议的示例。 * `rpc/triple`:Triple 协议示例,涵盖多种序列化方式。 * `rpc/triple/openapi`:演示如何为 Triple 协议服务启用 OpenAPI 文档,包括多版本服务和非 IDL 服务的注册。 + * `rpc/rest`:基于 Rest 协议的示例。 * `streaming`:流式 RPC 调用示例,并包含了Dubbo-go与Dubbo-java同时使用流式传输的互操作示例。 * `task`:任务调度与执行示例。 * `timeout`:Dubbo-go 超时处理示例。 diff --git a/go.mod b/go.mod index c7518bec9..d8d268841 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/apache/dubbo-go-samples go 1.25.0 +replace dubbo.apache.org/dubbo-go/v3 v3.3.1 => ../dubbo-go + require ( dubbo.apache.org/dubbo-go/v3 v3.3.2-20260419 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 diff --git a/rpc/rest/README.md b/rpc/rest/README.md new file mode 100644 index 000000000..d678bbf61 --- /dev/null +++ b/rpc/rest/README.md @@ -0,0 +1,76 @@ +# Dubbo-Go REST sample + +This sample validates the Dubbo-Go REST protocol with direct URL, interface-level registry, and application-level service discovery. It uses an explicit REST mapping for path, query, header, and body arguments. + +## Run + +Start the provider with the default Nacos application-level service discovery mode: + +```bash +go run ./rpc/rest/go-server/cmd +``` + +Run the Dubbo-Go REST consumer in another terminal: + +```bash +go run ./rpc/rest/go-client/cmd +``` + +Expected client output: + +```text +REST response: userID=101 name=dubbo-go traceID=trace-rest-basic message=body-from-dubbo-rest-client greeting="hello dubbo-go, userID=101, traceID=trace-rest-basic, message=body-from-dubbo-rest-client" +``` + +The same provider is also a normal HTTP endpoint: + +```bash +curl -s \ + -X POST 'http://127.0.0.1:20080/api/v1/users/202/greeting?name=curl' \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'X-Trace-ID: trace-curl' \ + -d '{"message":"body-from-curl"}' +``` + +## What this proves + +The provider URL only supplies the network target, for example `rest://127.0.0.1:20080/org.apache.dubbo.samples.rest.GreetingService`. + +The actual REST call shape comes from the REST method config in `api/rest_config.go`: + +- method: `POST` +- path: `/api/v1/users/{userID}/greeting` +- path parameter: argument `0` -> `userID` +- query parameter: argument `1` -> `name` +- header: argument `2` -> `X-Trace-ID` +- body: argument `3` + +So this sample intentionally separates "provider address" from "REST HTTP mapping". + +## Registry service discovery + +The provider and consumer support these flags: + +- `-registry=direct|zookeeper|nacos` +- `-registry-type=interface|service|all` + +The default is `-registry=nacos -registry-type=service`. + +`interface` means the registry stores the callable `rest://...` provider URL directly. `service` means the registry stores the application instance; the consumer finds the application by service mapping, fetches metadata from the provider metadata service, then reconstructs the `rest://...` provider URL from the discovered instance and service metadata. `all` registers both forms. + +Run direct URL mode: + +```bash +go run ./rpc/rest/go-server/cmd -registry=direct +go run ./rpc/rest/go-client/cmd -registry=direct +``` + +Run ZooKeeper interface-level registration: + +```bash +go run ./rpc/rest/go-server/cmd -registry=zookeeper -registry-type=interface +go run ./rpc/rest/go-client/cmd -registry=zookeeper -registry-type=interface +``` + +All modes should print the same `REST response: ...` line from the consumer. diff --git a/rpc/rest/README_CN.md b/rpc/rest/README_CN.md new file mode 100644 index 000000000..d0db4979c --- /dev/null +++ b/rpc/rest/README_CN.md @@ -0,0 +1,92 @@ +# Dubbo-Go REST 示例 + +这个示例用于验证 Dubbo-Go REST 协议的三种地址获取方式: + +- 直连 URL +- 接口级注册 +- 应用级服务发现 + +示例通过本地 REST 配置显式声明 HTTP 方法、路径参数、查询参数、请求头和请求体映射。 + +## 运行 + +默认模式是 Nacos 应用级服务发现: + +```bash +go run ./rpc/rest/go-server/cmd +``` + +在另一个终端运行消费者: + +```bash +go run ./rpc/rest/go-client/cmd +``` + +期望输出: + +```text +REST response: userID=101 name=dubbo-go traceID=trace-rest-basic message=body-from-dubbo-rest-client greeting="hello dubbo-go, userID=101, traceID=trace-rest-basic, message=body-from-dubbo-rest-client" +``` + +Provider 同时也是一个普通 HTTP 服务,可以直接用 `curl` 调用: + +```bash +curl -s \ + -X POST 'http://127.0.0.1:20080/api/v1/users/202/greeting?name=curl' \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'X-Trace-ID: trace-curl' \ + -d '{"message":"body-from-curl"}' +``` + +## REST 映射 + +Provider URL 只提供网络目标,例如: + +```text +rest://127.0.0.1:20080/org.apache.dubbo.samples.rest.GreetingService +``` + +真正的 REST 调用形态来自 `api/rest_config.go`: + +- HTTP 方法:`POST` +- 路径:`/api/v1/users/{userID}/greeting` +- 路径参数:参数 `0` -> `userID` +- 查询参数:参数 `1` -> `name` +- 请求头:参数 `2` -> `X-Trace-ID` +- 请求体:参数 `3` + +也就是说,这个示例刻意区分了“服务地址发现”和“REST HTTP 映射”。 + +## 服务发现模式 + +Provider 和 Consumer 都支持以下参数: + +- `-registry=direct|zookeeper|nacos` +- `-registry-type=interface|service|all` + +默认值是: + +```bash +-registry=nacos -registry-type=service +``` + +`interface` 表示注册中心直接保存可调用的 `rest://...` provider URL。 +`service` 表示注册中心保存应用实例;consumer 先通过 service mapping 找到应用,再通过 metadata service 获取服务元数据,最后根据应用实例和 `ServiceInfo` 重建 `rest://...` provider URL。 +`all` 表示同时注册接口级和应用级两种数据。 + +## 直连模式 + +```bash +go run ./rpc/rest/go-server/cmd -registry=direct +go run ./rpc/rest/go-client/cmd -registry=direct +``` + +## ZooKeeper 接口级注册 + +```bash +go run ./rpc/rest/go-server/cmd -registry=zookeeper -registry-type=interface +go run ./rpc/rest/go-client/cmd -registry=zookeeper -registry-type=interface +``` + +所有模式下,consumer 都应该输出相同的 `REST response: ...`。 diff --git a/rpc/rest/api/greeting.go b/rpc/rest/api/greeting.go new file mode 100644 index 000000000..277329fca --- /dev/null +++ b/rpc/rest/api/greeting.go @@ -0,0 +1,41 @@ +/* + * 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 api + +const ( + InterfaceName = "org.apache.dubbo.samples.rest.GreetingService" + MethodGetGreeting = "GetGreeting" +) + +type GreetingService struct{} + +func (*GreetingService) Reference() string { + return InterfaceName +} + +type GreetingRequest struct { + Message string `json:"message"` +} + +type GreetingResponse struct { + UserID int `json:"userID"` + Name string `json:"name"` + TraceID string `json:"traceID"` + Message string `json:"message"` + Greeting string `json:"greeting"` +} diff --git a/rpc/rest/api/registry.go b/rpc/rest/api/registry.go new file mode 100644 index 000000000..a95eec219 --- /dev/null +++ b/rpc/rest/api/registry.go @@ -0,0 +1,71 @@ +/* + * 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 api + +import ( + "fmt" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/registry" +) + +const ( + ServerAppName = "dubbo_rest_basic_server" + ClientAppName = "dubbo_rest_basic_client" + + RegistryDirect = "direct" + RegistryZookeeper = "zookeeper" + RegistryNacos = "nacos" + + RegistryTypeInterface = "interface" + RegistryTypeService = "service" + RegistryTypeAll = "all" + + DefaultRegistry = RegistryNacos + DefaultRegistryType = RegistryTypeService +) + +func RegistryOptions(name string, registryType string) ([]registry.Option, error) { + if name == RegistryDirect || name == "" { + return nil, nil + } + + var opts []registry.Option + switch name { + case RegistryZookeeper: + opts = append(opts, registry.WithZookeeper(), registry.WithAddress("127.0.0.1:2181")) + case RegistryNacos: + opts = append(opts, registry.WithNacos(), registry.WithAddress("127.0.0.1:8848")) + default: + return nil, fmt.Errorf("unsupported registry %q, use direct, zookeeper, or nacos", name) + } + + opts = append(opts, registry.WithoutUseAsConfigCenter()) + switch registryType { + case "", RegistryTypeInterface: + opts = append(opts, registry.WithRegisterInterface()) + case RegistryTypeService: + opts = append(opts, registry.WithRegisterService()) + case RegistryTypeAll: + opts = append(opts, registry.WithRegisterServiceAndInterface()) + default: + return nil, fmt.Errorf("unsupported registry type %q, use interface, service, or all", registryType) + } + return opts, nil +} diff --git a/rpc/rest/api/registry_test.go b/rpc/rest/api/registry_test.go new file mode 100644 index 000000000..33f56d482 --- /dev/null +++ b/rpc/rest/api/registry_test.go @@ -0,0 +1,29 @@ +/* + * 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 api + +import "testing" + +func TestDefaultRegistryMode(t *testing.T) { + if DefaultRegistry != RegistryNacos { + t.Fatalf("DefaultRegistry = %q, want %q", DefaultRegistry, RegistryNacos) + } + if DefaultRegistryType != RegistryTypeService { + t.Fatalf("DefaultRegistryType = %q, want %q", DefaultRegistryType, RegistryTypeService) + } +} diff --git a/rpc/rest/api/rest_config.go b/rpc/rest/api/rest_config.go new file mode 100644 index 000000000..28cf5d1a7 --- /dev/null +++ b/rpc/rest/api/rest_config.go @@ -0,0 +1,63 @@ +/* + * 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 api + +import ( + "net/http" +) + +import ( + "dubbo.apache.org/dubbo-go/v3/common/constant" + restconfig "dubbo.apache.org/dubbo-go/v3/protocol/rest/config" +) + +const RestPath = "/api/v1/users/{userID}/greeting" + +func InstallProviderRestConfig() { + restconfig.SetRestProviderServiceConfigMap(map[string]*restconfig.RestServiceConfig{ + InterfaceName: newRestServiceConfig(constant.DefaultRestServer, ""), + }) +} + +func InstallConsumerRestConfig() { + restconfig.SetRestConsumerServiceConfigMap(map[string]*restconfig.RestServiceConfig{ + InterfaceName: newRestServiceConfig("", constant.DefaultRestClient), + }) +} + +func newRestServiceConfig(serverType string, clientType string) *restconfig.RestServiceConfig { + return &restconfig.RestServiceConfig{ + InterfaceName: InterfaceName, + Server: serverType, + Client: clientType, + RestMethodConfigsMap: map[string]*restconfig.RestMethodConfig{ + MethodGetGreeting: { + InterfaceName: InterfaceName, + MethodName: MethodGetGreeting, + Path: RestPath, + MethodType: http.MethodPost, + PathParamsMap: map[int]string{0: "userID"}, + QueryParamsMap: map[int]string{1: "name"}, + HeadersMap: map[int]string{2: "X-Trace-ID"}, + Body: 3, + Consumes: "application/json", + Produces: "application/json", + }, + }, + } +} diff --git a/rpc/rest/go-client/cmd/client.go b/rpc/rest/go-client/cmd/client.go new file mode 100644 index 000000000..06475d1c6 --- /dev/null +++ b/rpc/rest/go-client/cmd/client.go @@ -0,0 +1,117 @@ +/* + * 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 main + +import ( + "context" + "flag" + "fmt" + "time" +) + +import ( + "dubbo.apache.org/dubbo-go/v3" + "dubbo.apache.org/dubbo-go/v3/client" + _ "dubbo.apache.org/dubbo-go/v3/cluster/cluster/failover" + _ "dubbo.apache.org/dubbo-go/v3/cluster/cluster/zoneaware" + _ "dubbo.apache.org/dubbo-go/v3/cluster/loadbalance/random" + _ "dubbo.apache.org/dubbo-go/v3/cluster/router/condition" + "dubbo.apache.org/dubbo-go/v3/common/constant" + _ "dubbo.apache.org/dubbo-go/v3/filter/graceful_shutdown" + _ "dubbo.apache.org/dubbo-go/v3/metadata/mapping/metadata" + _ "dubbo.apache.org/dubbo-go/v3/metadata/report/nacos" + _ "dubbo.apache.org/dubbo-go/v3/metadata/report/zookeeper" + _ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo" + _ "dubbo.apache.org/dubbo-go/v3/protocol/rest" + _ "dubbo.apache.org/dubbo-go/v3/registry/directory" + _ "dubbo.apache.org/dubbo-go/v3/registry/nacos" + _ "dubbo.apache.org/dubbo-go/v3/registry/protocol" + _ "dubbo.apache.org/dubbo-go/v3/registry/servicediscovery" + _ "dubbo.apache.org/dubbo-go/v3/registry/zookeeper" + + "github.com/dubbogo/gost/log/logger" +) + +import ( + "github.com/apache/dubbo-go-samples/rpc/rest/api" +) + +func main() { + registryName := flag.String("registry", api.DefaultRegistry, "registry mode: direct, zookeeper, or nacos") + registryType := flag.String("registry-type", api.DefaultRegistryType, "registry type: interface, service, or all") + flag.Parse() + + api.InstallConsumerRestConfig() + + instanceOpts := []dubbo.InstanceOption{ + dubbo.WithName(api.ClientAppName), + } + registryOpts, err := api.RegistryOptions(*registryName, *registryType) + if err != nil { + panic(err) + } + if len(registryOpts) > 0 { + instanceOpts = append(instanceOpts, dubbo.WithRegistry(registryOpts...)) + } + + ins, err := dubbo.NewInstance(instanceOpts...) + if err != nil { + panic(err) + } + + clientOpts := []client.ClientOption{ + client.WithClientNoCheck(), + client.WithClientRequestTimeout(5 * time.Second), + } + if *registryName == api.RegistryDirect || *registryName == "" { + clientOpts = append(clientOpts, client.WithClientURL("rest://127.0.0.1:20080")) + } + + cli, err := ins.NewClient(clientOpts...) + if err != nil { + panic(err) + } + + conn, err := cli.Dial( + api.InterfaceName, + client.WithProtocol(constant.RESTProtocol), + ) + if err != nil { + panic(err) + } + + resp := new(api.GreetingResponse) + err = conn.CallUnary( + context.Background(), + []any{ + 101, + "dubbo-go", + "trace-rest-basic", + &api.GreetingRequest{Message: "body-from-dubbo-rest-client"}, + }, + resp, + api.MethodGetGreeting, + ) + if err != nil { + logger.Error(err) + panic(err) + } + + fmt.Printf("REST response: userID=%d name=%s traceID=%s message=%s greeting=%q\n", + resp.UserID, resp.Name, resp.TraceID, resp.Message, resp.Greeting) +} diff --git a/rpc/rest/go-server/cmd/server.go b/rpc/rest/go-server/cmd/server.go new file mode 100644 index 000000000..e57b440e5 --- /dev/null +++ b/rpc/rest/go-server/cmd/server.go @@ -0,0 +1,154 @@ +/* + * 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 main + +import ( + "context" + "flag" + "fmt" + "strconv" +) + +import ( + "dubbo.apache.org/dubbo-go/v3" + _ "dubbo.apache.org/dubbo-go/v3/filter/echo" + _ "dubbo.apache.org/dubbo-go/v3/metadata/mapping/metadata" + _ "dubbo.apache.org/dubbo-go/v3/metadata/report/nacos" + _ "dubbo.apache.org/dubbo-go/v3/metadata/report/zookeeper" + "dubbo.apache.org/dubbo-go/v3/protocol" + _ "dubbo.apache.org/dubbo-go/v3/protocol/dubbo" + _ "dubbo.apache.org/dubbo-go/v3/protocol/rest" + _ "dubbo.apache.org/dubbo-go/v3/proxy/proxy_factory" + _ "dubbo.apache.org/dubbo-go/v3/registry/nacos" + _ "dubbo.apache.org/dubbo-go/v3/registry/protocol" + _ "dubbo.apache.org/dubbo-go/v3/registry/servicediscovery" + _ "dubbo.apache.org/dubbo-go/v3/registry/zookeeper" + dubboserver "dubbo.apache.org/dubbo-go/v3/server" + + "github.com/dubbogo/gost/log/logger" +) + +import ( + "github.com/apache/dubbo-go-samples/rpc/rest/api" +) + +type GreetingProvider struct { + api.GreetingService +} + +func (p *GreetingProvider) GetGreeting(_ context.Context, args []any) (*api.GreetingResponse, error) { + if len(args) != 4 { + return nil, fmt.Errorf("expected 4 REST arguments, got %d", len(args)) + } + + userID, err := toInt(args[0]) + if err != nil { + return nil, fmt.Errorf("parse userID: %w", err) + } + + name := fmt.Sprint(args[1]) + traceID := fmt.Sprint(args[2]) + message := bodyMessage(args[3]) + + return &api.GreetingResponse{ + UserID: userID, + Name: name, + TraceID: traceID, + Message: message, + Greeting: fmt.Sprintf("hello %s, userID=%d, traceID=%s, message=%s", name, userID, traceID, message), + }, nil +} + +func toInt(v any) (int, error) { + switch val := v.(type) { + case int: + return val, nil + case int32: + return int(val), nil + case int64: + return int(val), nil + case string: + return strconv.Atoi(val) + default: + return strconv.Atoi(fmt.Sprint(val)) + } +} + +func bodyMessage(v any) string { + switch body := v.(type) { + case map[string]any: + return fmt.Sprint(body["message"]) + case map[string]string: + return body["message"] + case *api.GreetingRequest: + return body.Message + case api.GreetingRequest: + return body.Message + default: + return fmt.Sprint(v) + } +} + +func main() { + registryName := flag.String("registry", api.DefaultRegistry, "registry mode: direct, zookeeper, or nacos") + registryType := flag.String("registry-type", api.DefaultRegistryType, "registry type: interface, service, or all") + flag.Parse() + + api.InstallProviderRestConfig() + + instanceOpts := []dubbo.InstanceOption{ + dubbo.WithName(api.ServerAppName), + dubbo.WithProtocol( + protocol.WithREST(), + protocol.WithIp("127.0.0.1"), + protocol.WithPort(20080), + ), + } + + registryOpts, err := api.RegistryOptions(*registryName, *registryType) + if err != nil { + panic(err) + } + if len(registryOpts) > 0 { + instanceOpts = append(instanceOpts, dubbo.WithRegistry(registryOpts...)) + } + + ins, err := dubbo.NewInstance(instanceOpts...) + if err != nil { + panic(err) + } + + srv, err := ins.NewServer() + if err != nil { + panic(err) + } + + if err := srv.RegisterService( + &GreetingProvider{}, + dubboserver.WithInterface(api.InterfaceName), + dubboserver.WithFilter("echo"), + ); err != nil { + panic(err) + } + + logger.Infof("REST provider is listening on http://127.0.0.1:20080%s, registry=%s, registry-type=%s", + api.RestPath, *registryName, *registryType) + if err := srv.Serve(); err != nil { + panic(err) + } +} diff --git a/start_integrate_test.sh b/start_integrate_test.sh index 8998862e5..1b0d9e38a 100755 --- a/start_integrate_test.sh +++ b/start_integrate_test.sh @@ -69,6 +69,7 @@ array+=("rpc/triple/reflection") array+=("rpc/triple/registry") array+=("rpc/triple/stream") array+=("rpc/triple/openapi") +array+=("rpc/rest") # tls array+=("tls") From dbc277a0700d15e9cbb25509dab70f9bb4169bb7 Mon Sep 17 00:00:00 2001 From: alanxtl Date: Mon, 1 Jun 2026 18:41:58 +0800 Subject: [PATCH 2/3] fix mod --- go.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.mod b/go.mod index d8d268841..c7518bec9 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/apache/dubbo-go-samples go 1.25.0 -replace dubbo.apache.org/dubbo-go/v3 v3.3.1 => ../dubbo-go - require ( dubbo.apache.org/dubbo-go/v3 v3.3.2-20260419 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 From 3a0d99bdc8d27f085a3f5de09c484373f0446e2c Mon Sep 17 00:00:00 2001 From: alanxtl Date: Mon, 1 Jun 2026 19:36:10 +0800 Subject: [PATCH 3/3] detete useless --- rpc/rest/api/registry_test.go | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 rpc/rest/api/registry_test.go diff --git a/rpc/rest/api/registry_test.go b/rpc/rest/api/registry_test.go deleted file mode 100644 index 33f56d482..000000000 --- a/rpc/rest/api/registry_test.go +++ /dev/null @@ -1,29 +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 api - -import "testing" - -func TestDefaultRegistryMode(t *testing.T) { - if DefaultRegistry != RegistryNacos { - t.Fatalf("DefaultRegistry = %q, want %q", DefaultRegistry, RegistryNacos) - } - if DefaultRegistryType != RegistryTypeService { - t.Fatalf("DefaultRegistryType = %q, want %q", DefaultRegistryType, RegistryTypeService) - } -}