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")