From 3d44588745e20c47ad6230c452a9fc4778afd607 Mon Sep 17 00:00:00 2001 From: jiangyuan04 Date: Thu, 30 Mar 2023 21:36:08 +0800 Subject: [PATCH] fix grpc MethodDescriptor fullMethodName problem Fixes gh-2910 --- .../main/asciidoc/spring-cloud-gateway.adoc | 6 ++--- .../grpc/src/main/proto/hello.pb | Bin 249 -> 442 bytes .../grpc/src/main/proto/hello.proto | 1 + .../JsonToGrpcGatewayFilterFactory.java | 24 ++++++++++++------ 4 files changed, 20 insertions(+), 11 deletions(-) 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 584ded1a4a07ebdecdf0c3f23727ee2902bb9a37..30c69524193aa7082b69890f481cc25eb6cfe7f1 100644 GIT binary patch literal 442 zcmdXcwqVASCBUU7BwcwPe literal 249 zcmd=3#>mB;k(!f}uUAl%Uy`rn!NubN;s&J_mZlb$2+449rezitm-r>-rb;j>FlulH zAq0e^xHxhWp^{8sNjP6gn~N7}QgK0kUU4c&ae7f|YDs2ZI@BaM-^dJVZE$K)S!Qyo zkQx^&*i}NjddSX^;)8J^W;z*g>Esus>lGIi0ZmOS0y?rhzbIQTIVZm~MK3+EB(*%T WQm+K)kz&2{qJrcA#w0edKaBwqVo#+2 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() {