diff --git a/docs/src/main/asciidoc/spring-cloud-gateway.adoc b/docs/src/main/asciidoc/spring-cloud-gateway.adoc index fdb5ac3aa..d6c5fb8b6 100644 --- a/docs/src/main/asciidoc/spring-cloud-gateway.adoc +++ b/docs/src/main/asciidoc/spring-cloud-gateway.adoc @@ -1849,7 +1849,7 @@ src/main/resources/proto/hello.proto * `protoFile` Proto definition file. -* `service` Fully qualified name of the service that will handle the request. +* `service` Short name of the service that will handle the request. * `method` Method name in the service that will handle the request. @@ -1887,12 +1887,12 @@ spring: args: protoDescriptor: file:proto/hello.pb protoFile: file:proto/hello.proto - service: com.example.grpcserver.hello.HelloService + service: HelloService method: hello ---- -When a request is made through the gateway to `/json/hello` the request will be transformed using the definition provided in `hello.proto`, sent to `com.example.grpcserver.hello.HelloService/hello`, and transform the response back to JSON. +When a request is made through the gateway to `/json/hello` the request will be transformed using the definition provided in `hello.proto`, sent to `HelloService/hello`, and transform the response back to JSON. By default, it will create a `NettyChannel` using the default `TrustManagerFactory`. However, this `TrustManager` can be customized by creating a bean of type `GrpcSslConfigurer`: diff --git a/spring-cloud-gateway-integration-tests/grpc/src/main/proto/hello.pb b/spring-cloud-gateway-integration-tests/grpc/src/main/proto/hello.pb index 584ded1a4..30c695241 100644 Binary files a/spring-cloud-gateway-integration-tests/grpc/src/main/proto/hello.pb and b/spring-cloud-gateway-integration-tests/grpc/src/main/proto/hello.pb differ diff --git a/spring-cloud-gateway-integration-tests/grpc/src/main/proto/hello.proto b/spring-cloud-gateway-integration-tests/grpc/src/main/proto/hello.proto index 24a347494..400d46017 100644 --- a/spring-cloud-gateway-integration-tests/grpc/src/main/proto/hello.proto +++ b/spring-cloud-gateway-integration-tests/grpc/src/main/proto/hello.proto @@ -1,6 +1,7 @@ syntax = "proto3"; option java_multiple_files = true; option java_package = "org.springframework.cloud.gateway.tests.grpc"; +package org.springframework.cloud.gateway.tests.grpc; message HelloRequest { optional string firstName = 1; diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/JsonToGrpcGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/JsonToGrpcGatewayFilterFactory.java index aed1911e7..2b0286e07 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/JsonToGrpcGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/JsonToGrpcGatewayFilterFactory.java @@ -192,9 +192,12 @@ public class JsonToGrpcGatewayFilterFactory descriptor = DescriptorProtos.FileDescriptorProto.parseFrom(descriptorFile.getInputStream()) .getDescriptorForType(); - Descriptors.Descriptor outputType = getOutputTypeDescriptor(config, descriptorFile.getInputStream()); + Descriptors.MethodDescriptor methodDescriptor = getMethodDescriptor(config, + descriptorFile.getInputStream()); + Descriptors.ServiceDescriptor serviceDescriptor = methodDescriptor.getService(); + Descriptors.Descriptor outputType = methodDescriptor.getOutputType(); - clientCall = createClientCallForType(config, outputType); + clientCall = createClientCallForType(config, serviceDescriptor, outputType); ProtobufSchema schema = ProtobufSchemaLoader.std.load(protoFile.getInputStream()); ProtobufSchema responseType = schema.withRootType(outputType.getName()); @@ -220,18 +223,19 @@ public class JsonToGrpcGatewayFilterFactory } private ClientCall createClientCallForType(Config config, - Descriptors.Descriptor outputType) { + Descriptors.ServiceDescriptor serviceDescriptor, Descriptors.Descriptor outputType) { MethodDescriptor.Marshaller marshaller = ProtoUtils .marshaller(DynamicMessage.newBuilder(outputType).build()); MethodDescriptor methodDescriptor = MethodDescriptor .newBuilder().setType(MethodDescriptor.MethodType.UNKNOWN) - .setFullMethodName(MethodDescriptor.generateFullMethodName(config.getService(), config.getMethod())) + .setFullMethodName(MethodDescriptor.generateFullMethodName(serviceDescriptor.getFullName(), + config.getMethod())) .setRequestMarshaller(marshaller).setResponseMarshaller(marshaller).build(); Channel channel = createChannel(); return channel.newCall(methodDescriptor, CallOptions.DEFAULT); } - private Descriptors.Descriptor getOutputTypeDescriptor(Config config, InputStream descriptorFile) + private Descriptors.MethodDescriptor getMethodDescriptor(Config config, InputStream descriptorFile) throws IOException, Descriptors.DescriptorValidationException { DescriptorProtos.FileDescriptorSet fileDescriptorSet = DescriptorProtos.FileDescriptorSet .parseFrom(descriptorFile); @@ -239,11 +243,15 @@ public class JsonToGrpcGatewayFilterFactory Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom(fileProto, new Descriptors.FileDescriptor[0]); - List methods = fileDescriptor.findServiceByName(config.getService()) - .getMethods(); + Descriptors.ServiceDescriptor serviceDescriptor = fileDescriptor.findServiceByName(config.getService()); + if (serviceDescriptor == null) { + throw new NoSuchElementException("No Service found"); + } + + List methods = serviceDescriptor.getMethods(); return methods.stream().filter(method -> method.getName().equals(config.getMethod())).findFirst() - .orElseThrow(() -> new NoSuchElementException("No Method found")).getOutputType(); + .orElseThrow(() -> new NoSuchElementException("No Method found")); } private ManagedChannel createChannel() {