[3.0-Triple] Support reflection api (#10168)

* Add proto

* Update compiler

* Add v1Alpha for compatibility

* Abstract builtin service export

* Try add get fd by name

* get service by symbol now works

* Add type

* Support extension

* Ignore reflection code scan

* Remove v1
This commit is contained in:
GuoHao 2022-06-29 14:19:48 +08:00 committed by GitHub
parent bf882c1883
commit 47f7be2fd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 500 additions and 30 deletions

View File

@ -72,22 +72,25 @@ public abstract class AbstractGenerator extends Generator {
}
@Override
public List<PluginProtos.CodeGeneratorResponse.File> generateFiles(PluginProtos.CodeGeneratorRequest request) throws GeneratorException {
public List<PluginProtos.CodeGeneratorResponse.File> generateFiles(
PluginProtos.CodeGeneratorRequest request) throws GeneratorException {
final ProtoTypeMap typeMap = ProtoTypeMap.of(request.getProtoFileList());
List<FileDescriptorProto> protosToGenerate = request.getProtoFileList().stream()
.filter(protoFile -> request.getFileToGenerateList().contains(protoFile.getName()))
.collect(Collectors.toList());
.filter(protoFile -> request.getFileToGenerateList().contains(protoFile.getName()))
.collect(Collectors.toList());
List<ServiceContext> services = findServices(protosToGenerate, typeMap);
return generateFiles(services);
}
private List<ServiceContext> findServices(List<FileDescriptorProto> protos, ProtoTypeMap typeMap) {
private List<ServiceContext> findServices(List<FileDescriptorProto> protos,
ProtoTypeMap typeMap) {
List<ServiceContext> contexts = new ArrayList<>();
protos.forEach(fileProto -> {
for (int serviceNumber = 0; serviceNumber < fileProto.getServiceCount(); serviceNumber++) {
for (int serviceNumber = 0; serviceNumber < fileProto.getServiceCount();
serviceNumber++) {
ServiceContext serviceContext = buildServiceContext(
fileProto.getService(serviceNumber),
typeMap,
@ -96,8 +99,12 @@ public abstract class AbstractGenerator extends Generator {
);
serviceContext.protoName = fileProto.getName();
serviceContext.packageName = extractPackageName(fileProto);
if (!Strings.isNullOrEmpty(fileProto.getOptions().getJavaOuterClassname())) {
serviceContext.outerClassName = fileProto.getOptions().getJavaOuterClassname();
}
serviceContext.commonPackageName = extractCommonPackageName(fileProto);
serviceContext.multipleFiles = fileProto.getOptions() != null && fileProto.getOptions().getJavaMultipleFiles();
serviceContext.multipleFiles =
fileProto.getOptions() != null && fileProto.getOptions().getJavaMultipleFiles();
contexts.add(serviceContext);
}
});
@ -121,15 +128,18 @@ public abstract class AbstractGenerator extends Generator {
return Strings.nullToEmpty(proto.getPackage());
}
private ServiceContext buildServiceContext(ServiceDescriptorProto serviceProto, ProtoTypeMap typeMap, List<Location> locations, int serviceNumber) {
private ServiceContext buildServiceContext(ServiceDescriptorProto serviceProto,
ProtoTypeMap typeMap, List<Location> locations, int serviceNumber) {
ServiceContext serviceContext = new ServiceContext();
serviceContext.fileName = getClassPrefix() + serviceProto.getName() + getClassSuffix() + ".java";
serviceContext.fileName =
getClassPrefix() + serviceProto.getName() + getClassSuffix() + ".java";
serviceContext.className = getClassPrefix() + serviceProto.getName() + getClassSuffix();
serviceContext.outerClassName = serviceProto.getName() + "OuterClass";
serviceContext.interfaceFileName = serviceProto.getName() + ".java";
serviceContext.interfaceClassName = serviceProto.getName();
serviceContext.serviceName = serviceProto.getName();
serviceContext.deprecated = serviceProto.getOptions() != null && serviceProto.getOptions().getDeprecated();
serviceContext.deprecated =
serviceProto.getOptions() != null && serviceProto.getOptions().getDeprecated();
List<Location> allLocationsForService = locations.stream()
.filter(location ->
@ -143,7 +153,8 @@ public abstract class AbstractGenerator extends Generator {
.filter(location -> location.getPathCount() == SERVICE_NUMBER_OF_PATHS)
.findFirst()
.orElseGet(Location::getDefaultInstance);
serviceContext.javaDoc = getJavaDoc(getComments(serviceLocation), getServiceJavaDocPrefix());
serviceContext.javaDoc = getJavaDoc(getComments(serviceLocation),
getServiceJavaDocPrefix());
for (int methodNumber = 0; methodNumber < serviceProto.getMethodCount(); methodNumber++) {
MethodContext methodContext = buildMethodContext(
@ -160,13 +171,15 @@ public abstract class AbstractGenerator extends Generator {
return serviceContext;
}
private MethodContext buildMethodContext(MethodDescriptorProto methodProto, ProtoTypeMap typeMap, List<Location> locations, int methodNumber) {
private MethodContext buildMethodContext(MethodDescriptorProto methodProto,
ProtoTypeMap typeMap, List<Location> locations, int methodNumber) {
MethodContext methodContext = new MethodContext();
methodContext.originMethodName = methodProto.getName();
methodContext.methodName = lowerCaseFirst(methodProto.getName());
methodContext.inputType = typeMap.toJavaTypeName(methodProto.getInputType());
methodContext.outputType = typeMap.toJavaTypeName(methodProto.getOutputType());
methodContext.deprecated = methodProto.getOptions() != null && methodProto.getOptions().getDeprecated();
methodContext.deprecated =
methodProto.getOptions() != null && methodProto.getOptions().getDeprecated();
methodContext.isManyInput = methodProto.getClientStreaming();
methodContext.isManyOutput = methodProto.getServerStreaming();
methodContext.methodNumber = methodNumber;
@ -203,7 +216,8 @@ public abstract class AbstractGenerator extends Generator {
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}
private List<PluginProtos.CodeGeneratorResponse.File> generateFiles(List<ServiceContext> services) {
private List<PluginProtos.CodeGeneratorResponse.File> generateFiles(
List<ServiceContext> services) {
List<PluginProtos.CodeGeneratorResponse.File> allServiceFiles = new ArrayList<>();
for (ServiceContext context : services) {
List<PluginProtos.CodeGeneratorResponse.File> files = buildFile(context);
@ -212,7 +226,7 @@ public abstract class AbstractGenerator extends Generator {
return allServiceFiles;
}
protected boolean enableMultipleTemplateFiles(){
protected boolean enableMultipleTemplateFiles() {
return false;
}
@ -266,7 +280,8 @@ public abstract class AbstractGenerator extends Generator {
}
private String getComments(Location location) {
return location.getLeadingComments().isEmpty() ? location.getTrailingComments() : location.getLeadingComments();
return location.getLeadingComments().isEmpty() ? location.getTrailingComments()
: location.getLeadingComments();
}
private String getJavaDoc(String comments, String prefix) {
@ -288,6 +303,7 @@ public abstract class AbstractGenerator extends Generator {
* Template class for proto Service objects.
*/
private class ServiceContext {
// CHECKSTYLE DISABLE VisibilityModifier FOR 8 LINES
public String fileName;
public String interfaceFileName;
@ -300,6 +316,8 @@ public abstract class AbstractGenerator extends Generator {
public boolean deprecated;
public String javaDoc;
public boolean multipleFiles;
public String outerClassName;
public List<MethodContext> methods = new ArrayList<>();
public Set<String> methodTypes = new HashSet<>();
@ -309,11 +327,13 @@ public abstract class AbstractGenerator extends Generator {
}
public List<MethodContext> unaryMethods() {
return methods.stream().filter(m -> (!m.isManyInput && !m.isManyOutput)).collect(Collectors.toList());
return methods.stream().filter(m -> (!m.isManyInput && !m.isManyOutput))
.collect(Collectors.toList());
}
public List<MethodContext> serverStreamingMethods() {
return methods.stream().filter(m -> !m.isManyInput && m.isManyOutput).collect(Collectors.toList());
return methods.stream().filter(m -> !m.isManyInput && m.isManyOutput)
.collect(Collectors.toList());
}
public List<MethodContext> biStreamingMethods() {
@ -321,11 +341,13 @@ public abstract class AbstractGenerator extends Generator {
}
public List<MethodContext> biStreamingWithoutClientStreamMethods() {
return methods.stream().filter(m->m.isManyInput&&m.isManyOutput).collect(Collectors.toList());
return methods.stream().filter(m -> m.isManyInput && m.isManyOutput)
.collect(Collectors.toList());
}
public List<MethodContext> clientStreamingMethods() {
return methods.stream().filter(m->m.isManyInput&&!m.isManyOutput).collect(Collectors.toList());
return methods.stream().filter(m -> m.isManyInput && !m.isManyOutput)
.collect(Collectors.toList());
}
public List<MethodContext> methods() {
@ -338,6 +360,7 @@ public abstract class AbstractGenerator extends Generator {
* Template class for proto RPC objects.
*/
private class MethodContext {
// CHECKSTYLE DISABLE VisibilityModifier FOR 10 LINES
public String originMethodName;
public String methodName;
@ -358,7 +381,8 @@ public abstract class AbstractGenerator extends Generator {
for (int i = 0; i < methodName.length(); i++) {
char c = methodName.charAt(i);
s.append(Character.toUpperCase(c));
if ((i < methodName.length() - 1) && Character.isLowerCase(c) && Character.isUpperCase(methodName.charAt(i + 1))) {
if ((i < methodName.length() - 1) && Character.isLowerCase(c)
&& Character.isUpperCase(methodName.charAt(i + 1))) {
s.append('_');
}
}

View File

@ -52,6 +52,7 @@ public final class {{className}} {
private static final StubServiceDescriptor serviceDescriptor = new StubServiceDescriptor(SERVICE_NAME,{{interfaceClassName}}.class);
static {
org.apache.dubbo.rpc.protocol.tri.service.SchemaDescriptorRegistry.addSchemaDescriptor(SERVICE_NAME,{{outerClassName}}.getDescriptor());
StubSuppliers.addSupplier(SERVICE_NAME, {{className}}::newStub);
StubSuppliers.addSupplier({{interfaceClassName}}.JAVA_SERVICE_NAME, {{className}}::newStub);
StubSuppliers.addDescriptor(SERVICE_NAME, serviceDescriptor);

View File

@ -33,7 +33,6 @@ public class StubSuppliers {
public static void addDescriptor(String interfaceName, ServiceDescriptor serviceDescriptor) {
SERVICE_DESCRIPTOR_MAP.put(interfaceName, serviceDescriptor);
}
public static void addSupplier(String interfaceName, Function<Invoker<?>, Object> supplier) {
STUB_SUPPLIERS.put(interfaceName, supplier);
}

View File

@ -0,0 +1,202 @@
/*
* 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 org.apache.dubbo.rpc.protocol.tri.service;
import org.apache.dubbo.common.stream.StreamObserver;
import org.apache.dubbo.rpc.TriRpcStatus;
import com.google.protobuf.Descriptors.FileDescriptor;
import io.grpc.reflection.v1alpha.DubboServerReflectionTriple;
import io.grpc.reflection.v1alpha.ErrorResponse;
import io.grpc.reflection.v1alpha.ExtensionNumberResponse;
import io.grpc.reflection.v1alpha.ExtensionRequest;
import io.grpc.reflection.v1alpha.FileDescriptorResponse;
import io.grpc.reflection.v1alpha.ListServiceResponse;
import io.grpc.reflection.v1alpha.ServerReflectionRequest;
import io.grpc.reflection.v1alpha.ServerReflectionResponse;
import io.grpc.reflection.v1alpha.ServiceResponse;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
/**
* Provides a reflection service for Protobuf service for service test and dynamic gateway.
*
* @link https://github.com/grpc/grpc/blob/master/doc/server-reflection.md
*/
public class ReflectionV1AlphaService extends DubboServerReflectionTriple.ServerReflectionImplBase {
@Override
public StreamObserver<ServerReflectionRequest> serverReflectionInfo(
StreamObserver<ServerReflectionResponse> responseObserver) {
return new StreamObserver<ServerReflectionRequest>() {
@Override
public void onNext(ServerReflectionRequest request) {
switch (request.getMessageRequestCase()) {
case FILE_BY_FILENAME:
getFileByName(request, responseObserver);
break;
case FILE_CONTAINING_SYMBOL:
getFileContainingSymbol(request, responseObserver);
break;
case FILE_CONTAINING_EXTENSION:
getFileByExtension(request, responseObserver);
break;
case ALL_EXTENSION_NUMBERS_OF_TYPE:
getAllExtensions(request, responseObserver);
break;
case LIST_SERVICES:
listServices(request, responseObserver);
break;
default:
sendErrorResponse(
request,
TriRpcStatus.Code.UNIMPLEMENTED,
"not implemented " + request.getMessageRequestCase(), responseObserver);
}
}
@Override
public void onError(Throwable throwable) {
responseObserver.onError(throwable);
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}
private void getFileByName(ServerReflectionRequest request,
StreamObserver<ServerReflectionResponse> responseObserver) {
String name = request.getFileByFilename();
FileDescriptor fd = SchemaDescriptorRegistry.getSchemaDescriptor(name);
if (fd != null) {
responseObserver.onNext(createServerReflectionResponse(request, fd));
} else {
sendErrorResponse(request, TriRpcStatus.Code.NOT_FOUND, "File not found.",
responseObserver);
}
}
private void getFileContainingSymbol(ServerReflectionRequest request,
StreamObserver<ServerReflectionResponse> responseObserver) {
String symbol = request.getFileContainingSymbol();
FileDescriptor fd = SchemaDescriptorRegistry.getSchemaDescriptor(symbol);
if (fd != null) {
responseObserver.onNext(createServerReflectionResponse(request, fd));
} else {
sendErrorResponse(request, TriRpcStatus.Code.NOT_FOUND, "Symbol not found.",
responseObserver);
}
}
private void getFileByExtension(ServerReflectionRequest request,
StreamObserver<ServerReflectionResponse> responseObserver) {
ExtensionRequest extensionRequest = request.getFileContainingExtension();
String type = extensionRequest.getContainingType();
int extension = extensionRequest.getExtensionNumber();
FileDescriptor fd =
SchemaDescriptorRegistry.getFileDescriptorByExtensionAndNumber(type, extension);
if (fd != null) {
responseObserver.onNext(createServerReflectionResponse(request, fd));
} else {
sendErrorResponse(request, TriRpcStatus.Code.NOT_FOUND, "Extension not found.",
responseObserver);
}
}
private void getAllExtensions(ServerReflectionRequest request,
StreamObserver<ServerReflectionResponse> responseObserver) {
String type = request.getAllExtensionNumbersOfType();
Set<Integer> extensions = SchemaDescriptorRegistry.getExtensionNumbers(type);
if (extensions != null) {
ExtensionNumberResponse.Builder builder =
ExtensionNumberResponse.newBuilder()
.setBaseTypeName(type)
.addAllExtensionNumber(extensions);
responseObserver.onNext(
ServerReflectionResponse.newBuilder()
.setValidHost(request.getHost())
.setOriginalRequest(request)
.setAllExtensionNumbersResponse(builder)
.build());
} else {
sendErrorResponse(request, TriRpcStatus.Code.NOT_FOUND, "Type not found.",
responseObserver);
}
}
private void listServices(ServerReflectionRequest request,
StreamObserver<ServerReflectionResponse> responseObserver) {
ListServiceResponse.Builder builder = ListServiceResponse.newBuilder();
for (String serviceName : SchemaDescriptorRegistry.listServiceNames()) {
builder.addService(ServiceResponse.newBuilder().setName(serviceName));
}
responseObserver.onNext(
ServerReflectionResponse.newBuilder()
.setValidHost(request.getHost())
.setOriginalRequest(request)
.setListServicesResponse(builder)
.build());
}
private void sendErrorResponse(
ServerReflectionRequest request, TriRpcStatus.Code code, String message,
StreamObserver<ServerReflectionResponse> responseObserver) {
ServerReflectionResponse response =
ServerReflectionResponse.newBuilder()
.setValidHost(request.getHost())
.setOriginalRequest(request)
.setErrorResponse(
ErrorResponse.newBuilder()
.setErrorCode(code.code)
.setErrorMessage(message))
.build();
responseObserver.onNext(response);
}
private ServerReflectionResponse createServerReflectionResponse(
ServerReflectionRequest request, FileDescriptor fd) {
FileDescriptorResponse.Builder fdRBuilder = FileDescriptorResponse.newBuilder();
Set<String> seenFiles = new HashSet<>();
Queue<FileDescriptor> frontier = new ArrayDeque<>();
seenFiles.add(fd.getName());
frontier.add(fd);
while (!frontier.isEmpty()) {
FileDescriptor nextFd = frontier.remove();
fdRBuilder.addFileDescriptorProto(nextFd.toProto().toByteString());
for (FileDescriptor dependencyFd : nextFd.getDependencies()) {
if (!seenFiles.contains(dependencyFd.getName())) {
seenFiles.add(dependencyFd.getName());
frontier.add(dependencyFd);
}
}
}
return ServerReflectionResponse.newBuilder()
.setValidHost(request.getHost())
.setOriginalRequest(request)
.setFileDescriptorResponse(fdRBuilder)
.build();
}
}

View File

@ -0,0 +1,90 @@
/*
* 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 org.apache.dubbo.rpc.protocol.tri.service;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class SchemaDescriptorRegistry {
private static final Map<String, FileDescriptor> DESCRIPTORS_BY_SYMBOL = new ConcurrentHashMap<>();
private static final Map<String, Map<Integer, FileDescriptor>> EXTENSIONS = new ConcurrentHashMap<>();
private static final Set<String> SERVICES = new HashSet<>();
public static void addSchemaDescriptor(String serviceName, FileDescriptor fd) {
SERVICES.add(serviceName);
DESCRIPTORS_BY_SYMBOL.put(serviceName, fd);
for (Descriptor messageType : fd.getMessageTypes()) {
addType(messageType);
}
for (FieldDescriptor extension : fd.getExtensions()) {
addExtension(extension, fd);
}
}
private static void addType(Descriptor descriptor) {
DESCRIPTORS_BY_SYMBOL.put(descriptor.getFullName(), descriptor.getFile());
for (Descriptor nestedType : descriptor.getNestedTypes()) {
addType(nestedType);
}
}
private static void addExtension(FieldDescriptor extension, FileDescriptor fd) {
String name = extension.getContainingType().getFullName();
int number = extension.getNumber();
if (!EXTENSIONS.containsKey(name)) {
EXTENSIONS.put(name, new HashMap<>());
}
Map<Integer, FileDescriptor> fdMap = EXTENSIONS.get(name);
fdMap.put(number, fd);
}
public static FileDescriptor getFileDescriptorByExtensionAndNumber(String extension,
int number) {
return EXTENSIONS.getOrDefault(extension, Collections.emptyMap()).get(number);
}
public static Set<Integer> getExtensionNumbers(String extension) {
Map<Integer, FileDescriptor> ret = EXTENSIONS.get(extension);
if (ret == null) {
return null;
} else {
return ret.keySet();
}
}
public static FileDescriptor getSchemaDescriptor(String serviceName) {
return DESCRIPTORS_BY_SYMBOL.get(serviceName);
}
public static List<String> listServiceNames() {
return new ArrayList<>(SERVICES);
}
}

View File

@ -24,6 +24,7 @@ import org.apache.dubbo.rpc.PathResolver;
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import io.grpc.health.v1.DubboHealthTriple;
import io.grpc.health.v1.Health;
@ -44,6 +45,7 @@ public class TriBuiltinService {
private final Health healthService;
private final ReflectionV1AlphaService reflectionServiceV1Alpha;
private final HealthStatusManager healthStatusManager;
private final AtomicBoolean init = new AtomicBoolean();
@ -51,6 +53,7 @@ public class TriBuiltinService {
public TriBuiltinService(FrameworkModel frameworkModel) {
healthStatusManager = new HealthStatusManager(new TriHealthImpl());
healthService = healthStatusManager.getHealthService();
reflectionServiceV1Alpha = new ReflectionV1AlphaService();
proxyFactory = frameworkModel.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
pathResolver = frameworkModel.getExtensionLoader(PathResolver.class).getDefaultExtension();
init();
@ -58,17 +61,23 @@ public class TriBuiltinService {
public void init() {
if (init.compareAndSet(false, true)) {
URL url = new ServiceConfigURL(CommonConstants.TRIPLE, null, null, ANYHOST_VALUE, 0,
DubboHealthTriple.SERVICE_NAME)
.addParameter(PROXY_KEY, CommonConstants.NATIVE_STUB)
.setScopeModel(ApplicationModel.defaultModel().getInternalModule());
Invoker<?> invoker = proxyFactory.getInvoker(healthService, Health.class, url);
pathResolver.add(DubboHealthTriple.SERVICE_NAME, invoker);
ApplicationModel.defaultModel().getInternalModule()
.addDestroyListener(scopeModel -> pathResolver.remove(DubboHealthTriple.SERVICE_NAME));
addSingleBuiltinService(DubboHealthTriple.SERVICE_NAME, healthService, Health.class);
addSingleBuiltinService(ReflectionV1AlphaService.SERVICE_NAME, reflectionServiceV1Alpha,
ReflectionV1AlphaService.class);
}
}
private <T> void addSingleBuiltinService(String serviceName, T impl, Class<T> interfaceClass) {
ModuleModel internalModule = ApplicationModel.defaultModel().getInternalModule();
URL url = new ServiceConfigURL(CommonConstants.TRIPLE, null, null, ANYHOST_VALUE, 0,
serviceName)
.addParameter(PROXY_KEY, CommonConstants.NATIVE_STUB)
.setScopeModel(internalModule);
Invoker<?> invoker = proxyFactory.getInvoker(impl, interfaceClass, url);
pathResolver.add(serviceName, invoker);
internalModule.addDestroyListener(scopeModel -> pathResolver.remove(serviceName));
}
public HealthStatusManager getHealthStatusManager() {
return healthStatusManager;
}

View File

@ -0,0 +1,144 @@
// Copyright 2016 The gRPC Authors
//
// Licensed 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.
// Service exported by server reflection
// Warning: this entire file is deprecated. Use this instead:
// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto
syntax = "proto3";
package grpc.reflection.v1alpha;
option deprecated = true;
option java_multiple_files = true;
option java_package = "io.grpc.reflection.v1alpha";
option java_outer_classname = "ServerReflectionProto";
service ServerReflection {
// The reflection service is structured as a bidirectional stream, ensuring
// all related requests go to a single server.
rpc ServerReflectionInfo(stream ServerReflectionRequest)
returns (stream ServerReflectionResponse);
}
// The message sent by the client when calling ServerReflectionInfo method.
message ServerReflectionRequest {
string host = 1;
// To use reflection service, the client should set one of the following
// fields in message_request. The server distinguishes requests by their
// defined field and then handles them using corresponding methods.
oneof message_request {
// Find a proto file by the file name.
string file_by_filename = 3;
// Find the proto file that declares the given fully-qualified symbol name.
// This field should be a fully-qualified symbol name
// (e.g. <package>.<service>[.<method>] or <package>.<type>).
string file_containing_symbol = 4;
// Find the proto file which defines an extension extending the given
// message type with the given field number.
ExtensionRequest file_containing_extension = 5;
// Finds the tag numbers used by all known extensions of extendee_type, and
// appends them to ExtensionNumberResponse in an undefined order.
// Its corresponding method is best-effort: it's not guaranteed that the
// reflection service will implement this method, and it's not guaranteed
// that this method will provide all extensions. Returns
// StatusCode::UNIMPLEMENTED if it's not implemented.
// This field should be a fully-qualified type name. The format is
// <package>.<type>
string all_extension_numbers_of_type = 6;
// List the full names of registered services. The content will not be
// checked.
string list_services = 7;
}
}
// The type name and extension number sent by the client when requesting
// file_containing_extension.
message ExtensionRequest {
// Fully-qualified type name. The format should be <package>.<type>
string containing_type = 1;
int32 extension_number = 2;
}
// The message sent by the server to answer ServerReflectionInfo method.
message ServerReflectionResponse {
string valid_host = 1;
ServerReflectionRequest original_request = 2;
// The server set one of the following fields accroding to the message_request
// in the request.
oneof message_response {
// This message is used to answer file_by_filename, file_containing_symbol,
// file_containing_extension requests with transitive dependencies. As
// the repeated label is not allowed in oneof fields, we use a
// FileDescriptorResponse message to encapsulate the repeated fields.
// The reflection service is allowed to avoid sending FileDescriptorProtos
// that were previously sent in response to earlier requests in the stream.
FileDescriptorResponse file_descriptor_response = 4;
// This message is used to answer all_extension_numbers_of_type requst.
ExtensionNumberResponse all_extension_numbers_response = 5;
// This message is used to answer list_services request.
ListServiceResponse list_services_response = 6;
// This message is used when an error occurs.
ErrorResponse error_response = 7;
}
}
// Serialized FileDescriptorProto messages sent by the server answering
// a file_by_filename, file_containing_symbol, or file_containing_extension
// request.
message FileDescriptorResponse {
// Serialized FileDescriptorProto messages. We avoid taking a dependency on
// descriptor.proto, which uses proto2 only features, by making them opaque
// bytes instead.
repeated bytes file_descriptor_proto = 1;
}
// A list of extension numbers sent by the server answering
// all_extension_numbers_of_type request.
message ExtensionNumberResponse {
// Full name of the base type, including the package name. The format
// is <package>.<type>
string base_type_name = 1;
repeated int32 extension_number = 2;
}
// A list of ServiceResponse sent by the server answering list_services request.
message ListServiceResponse {
// The information of each service may be expanded in the future, so we use
// ServiceResponse message to encapsulate it.
repeated ServiceResponse service = 1;
}
// The information of a single service used by ListServiceResponse to answer
// list_services request.
message ServiceResponse {
// Full name of a registered service, including its package name. The format
// is <package>.<service>
string name = 1;
}
// The error code and error message sent by the server when an error occurs.
message ErrorResponse {
// This field uses the error codes defined in grpc::StatusCode.
int32 error_code = 1;
string error_message = 2;
}

View File

@ -331,6 +331,7 @@
**/com/google/rpc/*,
**/generated/**/*,
**/grpc/health/**/*,
**/grpc/reflection/**/*,
**/target/**/*,
**/*.json
</excludes>