Skip to content

Commit 642dd63

Browse files
authored
reflection: expose both v1 and v1alpha reflection services (#6329)
1 parent 3c6084b commit 642dd63

File tree

3 files changed

+411
-100
lines changed

3 files changed

+411
-100
lines changed

reflection/adapt.go

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
*
3+
* Copyright 2023 gRPC authors.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package reflection
20+
21+
import (
22+
v1grpc "google.golang.org/grpc/reflection/grpc_reflection_v1"
23+
v1pb "google.golang.org/grpc/reflection/grpc_reflection_v1"
24+
v1alphagrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
25+
v1alphapb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
26+
)
27+
28+
// asV1Alpha returns an implementation of the v1alpha version of the reflection
29+
// interface that delegates all calls to the given v1 version.
30+
func asV1Alpha(svr v1grpc.ServerReflectionServer) v1alphagrpc.ServerReflectionServer {
31+
return v1AlphaServerImpl{svr: svr}
32+
}
33+
34+
type v1AlphaServerImpl struct {
35+
svr v1grpc.ServerReflectionServer
36+
}
37+
38+
func (s v1AlphaServerImpl) ServerReflectionInfo(stream v1alphagrpc.ServerReflection_ServerReflectionInfoServer) error {
39+
return s.svr.ServerReflectionInfo(v1AlphaServerStreamAdapter{stream})
40+
}
41+
42+
type v1AlphaServerStreamAdapter struct {
43+
v1alphagrpc.ServerReflection_ServerReflectionInfoServer
44+
}
45+
46+
func (s v1AlphaServerStreamAdapter) Send(response *v1pb.ServerReflectionResponse) error {
47+
return s.ServerReflection_ServerReflectionInfoServer.Send(v1ToV1AlphaResponse(response))
48+
}
49+
50+
func (s v1AlphaServerStreamAdapter) Recv() (*v1pb.ServerReflectionRequest, error) {
51+
resp, err := s.ServerReflection_ServerReflectionInfoServer.Recv()
52+
if err != nil {
53+
return nil, err
54+
}
55+
return v1AlphaToV1Request(resp), nil
56+
}
57+
58+
func v1ToV1AlphaResponse(v1 *v1pb.ServerReflectionResponse) *v1alphapb.ServerReflectionResponse {
59+
var v1alpha v1alphapb.ServerReflectionResponse
60+
v1alpha.ValidHost = v1.ValidHost
61+
if v1.OriginalRequest != nil {
62+
v1alpha.OriginalRequest = v1ToV1AlphaRequest(v1.OriginalRequest)
63+
}
64+
switch mr := v1.MessageResponse.(type) {
65+
case *v1pb.ServerReflectionResponse_FileDescriptorResponse:
66+
if mr != nil {
67+
v1alpha.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
68+
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{
69+
FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(),
70+
},
71+
}
72+
}
73+
case *v1pb.ServerReflectionResponse_AllExtensionNumbersResponse:
74+
if mr != nil {
75+
v1alpha.MessageResponse = &v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse{
76+
AllExtensionNumbersResponse: &v1alphapb.ExtensionNumberResponse{
77+
BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(),
78+
ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(),
79+
},
80+
}
81+
}
82+
case *v1pb.ServerReflectionResponse_ListServicesResponse:
83+
if mr != nil {
84+
svcs := make([]*v1alphapb.ServiceResponse, len(mr.ListServicesResponse.GetService()))
85+
for i, svc := range mr.ListServicesResponse.GetService() {
86+
svcs[i] = &v1alphapb.ServiceResponse{
87+
Name: svc.GetName(),
88+
}
89+
}
90+
v1alpha.MessageResponse = &v1alphapb.ServerReflectionResponse_ListServicesResponse{
91+
ListServicesResponse: &v1alphapb.ListServiceResponse{
92+
Service: svcs,
93+
},
94+
}
95+
}
96+
case *v1pb.ServerReflectionResponse_ErrorResponse:
97+
if mr != nil {
98+
v1alpha.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
99+
ErrorResponse: &v1alphapb.ErrorResponse{
100+
ErrorCode: mr.ErrorResponse.GetErrorCode(),
101+
ErrorMessage: mr.ErrorResponse.GetErrorMessage(),
102+
},
103+
}
104+
}
105+
default:
106+
// no value set
107+
}
108+
return &v1alpha
109+
}
110+
111+
func v1AlphaToV1Request(v1alpha *v1alphapb.ServerReflectionRequest) *v1pb.ServerReflectionRequest {
112+
var v1 v1pb.ServerReflectionRequest
113+
v1.Host = v1alpha.Host
114+
switch mr := v1alpha.MessageRequest.(type) {
115+
case *v1alphapb.ServerReflectionRequest_FileByFilename:
116+
v1.MessageRequest = &v1pb.ServerReflectionRequest_FileByFilename{
117+
FileByFilename: mr.FileByFilename,
118+
}
119+
case *v1alphapb.ServerReflectionRequest_FileContainingSymbol:
120+
v1.MessageRequest = &v1pb.ServerReflectionRequest_FileContainingSymbol{
121+
FileContainingSymbol: mr.FileContainingSymbol,
122+
}
123+
case *v1alphapb.ServerReflectionRequest_FileContainingExtension:
124+
if mr.FileContainingExtension != nil {
125+
v1.MessageRequest = &v1pb.ServerReflectionRequest_FileContainingExtension{
126+
FileContainingExtension: &v1pb.ExtensionRequest{
127+
ContainingType: mr.FileContainingExtension.GetContainingType(),
128+
ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(),
129+
},
130+
}
131+
}
132+
case *v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType:
133+
v1.MessageRequest = &v1pb.ServerReflectionRequest_AllExtensionNumbersOfType{
134+
AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType,
135+
}
136+
case *v1alphapb.ServerReflectionRequest_ListServices:
137+
v1.MessageRequest = &v1pb.ServerReflectionRequest_ListServices{
138+
ListServices: mr.ListServices,
139+
}
140+
default:
141+
// no value set
142+
}
143+
return &v1
144+
}
145+
146+
func v1ToV1AlphaRequest(v1 *v1pb.ServerReflectionRequest) *v1alphapb.ServerReflectionRequest {
147+
var v1alpha v1alphapb.ServerReflectionRequest
148+
v1alpha.Host = v1.Host
149+
switch mr := v1.MessageRequest.(type) {
150+
case *v1pb.ServerReflectionRequest_FileByFilename:
151+
if mr != nil {
152+
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_FileByFilename{
153+
FileByFilename: mr.FileByFilename,
154+
}
155+
}
156+
case *v1pb.ServerReflectionRequest_FileContainingSymbol:
157+
if mr != nil {
158+
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_FileContainingSymbol{
159+
FileContainingSymbol: mr.FileContainingSymbol,
160+
}
161+
}
162+
case *v1pb.ServerReflectionRequest_FileContainingExtension:
163+
if mr != nil {
164+
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_FileContainingExtension{
165+
FileContainingExtension: &v1alphapb.ExtensionRequest{
166+
ContainingType: mr.FileContainingExtension.GetContainingType(),
167+
ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(),
168+
},
169+
}
170+
}
171+
case *v1pb.ServerReflectionRequest_AllExtensionNumbersOfType:
172+
if mr != nil {
173+
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType{
174+
AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType,
175+
}
176+
}
177+
case *v1pb.ServerReflectionRequest_ListServices:
178+
if mr != nil {
179+
v1alpha.MessageRequest = &v1alphapb.ServerReflectionRequest_ListServices{
180+
ListServices: mr.ListServices,
181+
}
182+
}
183+
default:
184+
// no value set
185+
}
186+
return &v1alpha
187+
}

reflection/serverreflection.go

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ import (
4848
"google.golang.org/protobuf/reflect/protoreflect"
4949
"google.golang.org/protobuf/reflect/protoregistry"
5050

51+
v1grpc "google.golang.org/grpc/reflection/grpc_reflection_v1"
52+
v1pb "google.golang.org/grpc/reflection/grpc_reflection_v1"
5153
v1alphagrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
52-
v1alphapb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
5354
)
5455

5556
// GRPCServer is the interface provided by a gRPC server. It is implemented by
@@ -63,9 +64,19 @@ type GRPCServer interface {
6364
var _ GRPCServer = (*grpc.Server)(nil)
6465

6566
// Register registers the server reflection service on the given gRPC server.
67+
// Both the v1 and v1alpha versions are registered.
6668
func Register(s GRPCServer) {
67-
svr := NewServer(ServerOptions{Services: s})
68-
v1alphagrpc.RegisterServerReflectionServer(s, svr)
69+
svr := NewServerV1(ServerOptions{Services: s})
70+
v1alphagrpc.RegisterServerReflectionServer(s, asV1Alpha(svr))
71+
v1grpc.RegisterServerReflectionServer(s, svr)
72+
}
73+
74+
// RegisterV1 registers only the v1 version of the server reflection service
75+
// on the given gRPC server. Many clients may only support v1alpha so most
76+
// users should use Register instead, at least until clients have upgraded.
77+
func RegisterV1(s GRPCServer) {
78+
svr := NewServerV1(ServerOptions{Services: s})
79+
v1grpc.RegisterServerReflectionServer(s, svr)
6980
}
7081

7182
// ServiceInfoProvider is an interface used to retrieve metadata about the
@@ -120,13 +131,27 @@ type ServerOptions struct {
120131

121132
// NewServer returns a reflection server implementation using the given options.
122133
// This can be used to customize behavior of the reflection service. Most usages
123-
// should prefer to use Register instead.
134+
// should prefer to use Register instead. For backwards compatibility reasons,
135+
// this returns the v1alpha version of the reflection server. For a v1 version
136+
// of the reflection server, see NewServerV1.
124137
//
125138
// # Experimental
126139
//
127140
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
128141
// later release.
129142
func NewServer(opts ServerOptions) v1alphagrpc.ServerReflectionServer {
143+
return asV1Alpha(NewServerV1(opts))
144+
}
145+
146+
// NewServerV1 returns a reflection server implementation using the given options.
147+
// This can be used to customize behavior of the reflection service. Most usages
148+
// should prefer to use Register instead.
149+
//
150+
// # Experimental
151+
//
152+
// Notice: This function is EXPERIMENTAL and may be changed or removed in a
153+
// later release.
154+
func NewServerV1(opts ServerOptions) v1grpc.ServerReflectionServer {
130155
if opts.DescriptorResolver == nil {
131156
opts.DescriptorResolver = protoregistry.GlobalFiles
132157
}
@@ -215,11 +240,11 @@ func (s *serverReflectionServer) allExtensionNumbersForTypeName(name string) ([]
215240
}
216241

217242
// listServices returns the names of services this server exposes.
218-
func (s *serverReflectionServer) listServices() []*v1alphapb.ServiceResponse {
243+
func (s *serverReflectionServer) listServices() []*v1pb.ServiceResponse {
219244
serviceInfo := s.s.GetServiceInfo()
220-
resp := make([]*v1alphapb.ServiceResponse, 0, len(serviceInfo))
245+
resp := make([]*v1pb.ServiceResponse, 0, len(serviceInfo))
221246
for svc := range serviceInfo {
222-
resp = append(resp, &v1alphapb.ServiceResponse{Name: svc})
247+
resp = append(resp, &v1pb.ServiceResponse{Name: svc})
223248
}
224249
sort.Slice(resp, func(i, j int) bool {
225250
return resp[i].Name < resp[j].Name
@@ -228,7 +253,7 @@ func (s *serverReflectionServer) listServices() []*v1alphapb.ServiceResponse {
228253
}
229254

230255
// ServerReflectionInfo is the reflection service handler.
231-
func (s *serverReflectionServer) ServerReflectionInfo(stream v1alphagrpc.ServerReflection_ServerReflectionInfoServer) error {
256+
func (s *serverReflectionServer) ServerReflectionInfo(stream v1grpc.ServerReflection_ServerReflectionInfoServer) error {
232257
sentFileDescriptors := make(map[string]bool)
233258
for {
234259
in, err := stream.Recv()
@@ -239,79 +264,79 @@ func (s *serverReflectionServer) ServerReflectionInfo(stream v1alphagrpc.ServerR
239264
return err
240265
}
241266

242-
out := &v1alphapb.ServerReflectionResponse{
267+
out := &v1pb.ServerReflectionResponse{
243268
ValidHost: in.Host,
244269
OriginalRequest: in,
245270
}
246271
switch req := in.MessageRequest.(type) {
247-
case *v1alphapb.ServerReflectionRequest_FileByFilename:
272+
case *v1pb.ServerReflectionRequest_FileByFilename:
248273
var b [][]byte
249274
fd, err := s.descResolver.FindFileByPath(req.FileByFilename)
250275
if err == nil {
251276
b, err = s.fileDescWithDependencies(fd, sentFileDescriptors)
252277
}
253278
if err != nil {
254-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
255-
ErrorResponse: &v1alphapb.ErrorResponse{
279+
out.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
280+
ErrorResponse: &v1pb.ErrorResponse{
256281
ErrorCode: int32(codes.NotFound),
257282
ErrorMessage: err.Error(),
258283
},
259284
}
260285
} else {
261-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
262-
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
286+
out.MessageResponse = &v1pb.ServerReflectionResponse_FileDescriptorResponse{
287+
FileDescriptorResponse: &v1pb.FileDescriptorResponse{FileDescriptorProto: b},
263288
}
264289
}
265-
case *v1alphapb.ServerReflectionRequest_FileContainingSymbol:
290+
case *v1pb.ServerReflectionRequest_FileContainingSymbol:
266291
b, err := s.fileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors)
267292
if err != nil {
268-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
269-
ErrorResponse: &v1alphapb.ErrorResponse{
293+
out.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
294+
ErrorResponse: &v1pb.ErrorResponse{
270295
ErrorCode: int32(codes.NotFound),
271296
ErrorMessage: err.Error(),
272297
},
273298
}
274299
} else {
275-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
276-
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
300+
out.MessageResponse = &v1pb.ServerReflectionResponse_FileDescriptorResponse{
301+
FileDescriptorResponse: &v1pb.FileDescriptorResponse{FileDescriptorProto: b},
277302
}
278303
}
279-
case *v1alphapb.ServerReflectionRequest_FileContainingExtension:
304+
case *v1pb.ServerReflectionRequest_FileContainingExtension:
280305
typeName := req.FileContainingExtension.ContainingType
281306
extNum := req.FileContainingExtension.ExtensionNumber
282307
b, err := s.fileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors)
283308
if err != nil {
284-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
285-
ErrorResponse: &v1alphapb.ErrorResponse{
309+
out.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
310+
ErrorResponse: &v1pb.ErrorResponse{
286311
ErrorCode: int32(codes.NotFound),
287312
ErrorMessage: err.Error(),
288313
},
289314
}
290315
} else {
291-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_FileDescriptorResponse{
292-
FileDescriptorResponse: &v1alphapb.FileDescriptorResponse{FileDescriptorProto: b},
316+
out.MessageResponse = &v1pb.ServerReflectionResponse_FileDescriptorResponse{
317+
FileDescriptorResponse: &v1pb.FileDescriptorResponse{FileDescriptorProto: b},
293318
}
294319
}
295-
case *v1alphapb.ServerReflectionRequest_AllExtensionNumbersOfType:
320+
case *v1pb.ServerReflectionRequest_AllExtensionNumbersOfType:
296321
extNums, err := s.allExtensionNumbersForTypeName(req.AllExtensionNumbersOfType)
297322
if err != nil {
298-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ErrorResponse{
299-
ErrorResponse: &v1alphapb.ErrorResponse{
323+
out.MessageResponse = &v1pb.ServerReflectionResponse_ErrorResponse{
324+
ErrorResponse: &v1pb.ErrorResponse{
300325
ErrorCode: int32(codes.NotFound),
301326
ErrorMessage: err.Error(),
302327
},
303328
}
304329
} else {
305-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_AllExtensionNumbersResponse{
306-
AllExtensionNumbersResponse: &v1alphapb.ExtensionNumberResponse{
330+
out.MessageResponse = &v1pb.ServerReflectionResponse_AllExtensionNumbersResponse{
331+
AllExtensionNumbersResponse: &v1pb.ExtensionNumberResponse{
307332
BaseTypeName: req.AllExtensionNumbersOfType,
308333
ExtensionNumber: extNums,
309334
},
310335
}
311336
}
312-
case *v1alphapb.ServerReflectionRequest_ListServices:
313-
out.MessageResponse = &v1alphapb.ServerReflectionResponse_ListServicesResponse{
314-
ListServicesResponse: &v1alphapb.ListServiceResponse{
337+
case *v1pb.ServerReflectionRequest_ListServices:
338+
out.MessageResponse = &v1pb.ServerReflectionResponse_ListServicesResponse{
339+
ListServicesResponse: &v1pb.ListServiceResponse{
315340
Service: s.listServices(),
316341
},
317342
}

0 commit comments

Comments
 (0)