This is an automated email from the ASF dual-hosted git repository.

Alanxtl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-go-samples.git


The following commit(s) were added to refs/heads/main by this push:
     new 4bb14f2e [feat] Add REST protocol samples (#1109)
4bb14f2e is described below

commit 4bb14f2ef83f36e68e30ab29f75f372d6c92182f
Author: Xuetao Li <[email protected]>
AuthorDate: Thu Aug 6 02:10:17 2026 +0000

    [feat] Add REST protocol samples (#1109)
    
    * add rest samples
    
    * fix mod
    
    * detete useless
    
    * Replace fmt.Errorf with logger.Errorf for errors
    
    * fix
    
    * import format
    
    * add panic
    
    * import
---
 README.md                        |   1 +
 README_CN.md                     |   1 +
 rpc/rest/README.md               |  76 +++++++++++++++++++
 rpc/rest/README_CN.md            |  88 ++++++++++++++++++++++
 rpc/rest/api/greeting.go         |  41 +++++++++++
 rpc/rest/api/registry.go         |  71 ++++++++++++++++++
 rpc/rest/api/rest_config.go      |  63 ++++++++++++++++
 rpc/rest/go-client/cmd/client.go | 122 +++++++++++++++++++++++++++++++
 rpc/rest/go-server/cmd/server.go | 154 +++++++++++++++++++++++++++++++++++++++
 start_integrate_test.sh          |   1 +
 10 files changed, 618 insertions(+)

diff --git a/README.md b/README.md
index 10ecbdd0..d6923e27 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 a2084e6a..841d90c8 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/rpc/rest/README.md b/rpc/rest/README.md
new file mode 100644
index 00000000..fc7c1712
--- /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 identifies the Dubbo service endpoint (address + interface), 
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 00000000..dbccb2c6
--- /dev/null
+++ b/rpc/rest/README_CN.md
@@ -0,0 +1,88 @@
+# 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 用于标识可调用的 Dubbo 服务端点(地址 + 
接口),例如:`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 00000000..277329fc
--- /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 00000000..a95eec21
--- /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/rest_config.go b/rpc/rest/api/rest_config.go
new file mode 100644
index 00000000..28cf5d1a
--- /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 00000000..1ce50b2c
--- /dev/null
+++ b/rpc/rest/go-client/cmd/client.go
@@ -0,0 +1,122 @@
+/*
+ * 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)
+       }
+
+       if resp.UserID != 101 || resp.Name != "dubbo-go" || resp.TraceID != 
"trace-rest-basic" {
+               panic(fmt.Errorf("gets an unexpected result: userID=%d name=%s 
traceID=%s message=%s greeting=%q",
+                       resp.UserID, resp.Name, resp.TraceID, resp.Message, 
resp.Greeting))
+       }
+
+       logger.Infof("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 00000000..e57b440e
--- /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 649e46fe..2f17f0b5 100755
--- a/start_integrate_test.sh
+++ b/start_integrate_test.sh
@@ -71,6 +71,7 @@ array+=("rpc/triple/reflection")
 array+=("rpc/triple/registry")
 array+=("rpc/triple/stream")
 array+=("rpc/triple/openapi")
+array+=("rpc/rest")
 
 # tls
 array+=("tls")

Reply via email to