Repository: caicloud/nirvana
Pull request #405 (2020-12-01 05:55:50)

[release-0.3] fix(rpc): disallow duplicated rpc path
This is an automated cherry-pick of #404

/assign iawia002

caicloud-bot: @caicloud-bot: Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our [release note process](https://git.k8s.io/community/contributors/guide/release-notes.md) to remove it.

<details>

Instructions for interacting with me using PR comments are available [here](https://github.com/caicloud/engineering/blob/master/guidelines/caicloud_bot.md).  If you have questions or suggestions related to my behavior, please file an issue against the [caicloud/tools](https://github.com/caicloud/tools/issues/new?title=Prow%20issue:) repository.
</details>
caicloud-bot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: 
To fully approve this pull request, please assign additional approvers.
We suggest the following additional approver: **kdada**

Assign the PR to them by writing `/assign @kdada` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://github.com/caicloud/engineering/blob/master/guidelines/caicloud_bot.md#bot-commands).

The pull request process is described [here](https://github.com/caicloud/engineering/blob/master/guidelines/caicloud_bot.md#typical-workflow)

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/caicloud/nirvana/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["kdada"]} -->
iawia002: /release-note-none
/lgtm
caicloud-bot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/caicloud/nirvana/pull/405#issuecomment-736241696" title="LGTM">iawia002</a>*

The full list of commands accepted by this bot can be found [here](https://github.com/caicloud/engineering/blob/master/guidelines/caicloud_bot.md#bot-commands).

The pull request process is described [here](https://github.com/caicloud/engineering/blob/master/guidelines/caicloud_bot.md#typical-workflow)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/caicloud/nirvana/blob/master/OWNERS)~~ [iawia002]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/service/rpc/builder.go b/service/rpc/builder.go
index ab388e8..b90f60a 100644
--- a/service/rpc/builder.go
+++ b/service/rpc/builder.go
@@ -107,7 +107,11 @@ func (b *builder) AddDescriptor(descriptors ...interface{}) error {
 			path = "/"
 		}
 		for _, action := range descriptor.Actions {
-			b.bindings[genRPCPath(path, action.Version, action.Name)] = &binding{
+			rpcPath := genRPCPath(path, action.Version, action.Name)
+			if _, ok := b.bindings[rpcPath]; ok {
+				return fmt.Errorf("duplicated rpc path: %s", rpcPath)
+			}
+			b.bindings[rpcPath] = &binding{
 				middlewares: descriptor.Middlewares,
 				definition:  b.genDefinition(action, descriptor.Consumes, descriptor.Produces, descriptor.Tags),
 			}


Test patch:
diff --git a/service/rpc/builder_test.go b/service/rpc/builder_test.go
index fbd90a8..bc3f42c 100644
--- a/service/rpc/builder_test.go
+++ b/service/rpc/builder_test.go
@@ -303,6 +303,33 @@ func TestDefinitions(t *testing.T) {
 	}
 }
 
+func TestDuplicatedRPCPath(t *testing.T) {
+	const version = "2020-10-10"
+	action := definition.RPCAction{
+		Name:    "GetFoo",
+		Version: version,
+		Function: func() (string, error) {
+			return "", nil
+		},
+		Results: definition.DataErrorResults(""),
+	}
+	desc := definition.RPCDescriptor{
+		Path:        "/",
+		Description: "Test",
+		Consumes:    []string{definition.MIMEAll},
+		Produces:    []string{definition.MIMEAll},
+		Actions:     []definition.RPCAction{action, action},
+	}
+	builder := NewBuilder()
+	err := builder.AddDescriptor(desc)
+	if err == nil {
+		t.Fatal("Unexpected success")
+	}
+	if !strings.Contains(err.Error(), "duplicated rpc path") {
+		t.Fatalf("Unexpected error: %v", err)
+	}
+}
+
 func BenchmarkServer(b *testing.B) {
 	u, _ := url.Parse("/?Action=GetEcho&Version=2020-01-01&name=alice")