Skip to content

Commit 63d1fcc

Browse files
andrasczjohanbrandhorst
authored andcommitted
return error if an external HTTP rule has no matching method
1 parent d1093df commit 63d1fcc

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

protoc-gen-grpc-gateway/descriptor/registry.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,29 @@ func (r *Registry) AddExternalHTTPRule(qualifiedMethodName string, rule *annotat
268268
r.externalHTTPRules[qualifiedMethodName] = append(r.externalHTTPRules[qualifiedMethodName], rule)
269269
}
270270

271+
// UnboundExternalHTTPRules returns the list of External HTTPRules
272+
// which does not have a matching method in the registry
273+
func (r *Registry) UnboundExternalHTTPRules() []string {
274+
allServiceMethods := make(map[string]struct{})
275+
for _, f := range r.files {
276+
for _, s := range f.GetService() {
277+
svc := &Service{File: f, ServiceDescriptorProto: s}
278+
for _, m := range s.GetMethod() {
279+
method := &Method{Service: svc, MethodDescriptorProto: m}
280+
allServiceMethods[method.FQMN()] = struct{}{}
281+
}
282+
}
283+
}
284+
285+
var missingMethods []string
286+
for httpRuleMethod := range r.externalHTTPRules {
287+
if _, ok := allServiceMethods[httpRuleMethod]; !ok {
288+
missingMethods = append(missingMethods, httpRuleMethod)
289+
}
290+
}
291+
return missingMethods
292+
}
293+
271294
// AddPkgMap adds a mapping from a .proto file to proto package name.
272295
func (r *Registry) AddPkgMap(file, protoPkg string) {
273296
r.pkgMap[file] = protoPkg

protoc-gen-grpc-gateway/descriptor/registry_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,3 +586,43 @@ func TestLoadGoPackageInputPath(t *testing.T) {
586586
t.Errorf("file.GoPkg = %#v; want %#v", got, want)
587587
}
588588
}
589+
590+
func TestUnboundExternalHTTPRules(t *testing.T) {
591+
reg := NewRegistry()
592+
methodName := ".example.ExampleService.Echo"
593+
reg.AddExternalHTTPRule(methodName, nil)
594+
assertStringSlice(t, "unbound external HTTP rules", reg.UnboundExternalHTTPRules(), []string{methodName})
595+
loadFile(t, reg, `
596+
name: "path/to/example.proto",
597+
package: "example"
598+
message_type <
599+
name: "StringMessage"
600+
field <
601+
name: "string"
602+
number: 1
603+
label: LABEL_OPTIONAL
604+
type: TYPE_STRING
605+
>
606+
>
607+
service <
608+
name: "ExampleService"
609+
method <
610+
name: "Echo"
611+
input_type: "StringMessage"
612+
output_type: "StringMessage"
613+
>
614+
>
615+
`)
616+
assertStringSlice(t, "unbound external HTTP rules", reg.UnboundExternalHTTPRules(), []string{})
617+
}
618+
619+
func assertStringSlice(t *testing.T, message string, got, want []string) {
620+
if len(got) != len(want) {
621+
t.Errorf("%s = %#v len(%d); want %#v len(%d)", message, got, len(got), want, len(want))
622+
}
623+
for i := range want {
624+
if got[i] != want[i] {
625+
t.Errorf("%s[%d] = %#v; want %#v", message, i, got[i], want[i])
626+
}
627+
}
628+
}

protoc-gen-grpc-gateway/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ func main() {
103103
emitError(err)
104104
return
105105
}
106+
unboundHTTPRules := reg.UnboundExternalHTTPRules()
107+
if len(unboundHTTPRules) != 0 {
108+
emitError(fmt.Errorf("HTTP rules without a matching selector: %s", strings.Join(unboundHTTPRules, ", ")))
109+
return
110+
}
106111

107112
var targets []*descriptor.File
108113
for _, target := range req.FileToGenerate {

0 commit comments

Comments
 (0)