From fdbfdb1aeb34d2f09db9fb0789d459b4796aafb3 Mon Sep 17 00:00:00 2001 From: Vasu Nori Date: Sun, 21 Jun 2020 16:43:22 -0700 Subject: [PATCH] separate base files from example code --- .../grpc-web-java/greeter-service/pom.xml | 117 ++++++++++++++++++ .../examples/greeter/GreeterClient.java | 106 ++++++++++++++++ .../examples/greeter/GreeterService.java | 31 +++++ .../greeter/StartServiceAndGrpcwebProxy.java | 51 ++++++++ .../src/main/proto/greeter.proto | 34 +++++ .../interop-test-service/pom.xml | 108 ++++++++++++++++ .../grpcweb/examples/InteropTestService.java | 23 +++- .../examples/StartServiceAndGrpcwebProxy.java | 57 +++++++++ .../src/main/proto/grpc/testing/empty.proto | 0 .../main/proto/grpc/testing/messages.proto | 0 .../src/main/proto/grpc/testing/test.proto | 5 + src/connector/pom.xml | 43 +------ .../java/com/google/grpcweb/DebugInfo.java | 8 +- .../com/google/grpcweb/GrpcPortNumRelay.java | 14 +++ .../grpcweb/GrpcWebClientInterceptor.java | 6 +- .../google/grpcweb/GrpcWebGuiceModule.java | 10 +- .../JettyWebserverForGrpcwebTraffic.java | 38 ++++++ .../com/google/grpcweb/MessageDeframer.java | 13 +- .../java/com/google/grpcweb/MetadataUtil.java | 1 - .../com/google/grpcweb/RequestHandler.java | 5 +- .../java/com/google/grpcweb/SendResponse.java | 4 +- .../testing/main/TestServiceAndProxy.java | 55 -------- .../src/main/java/grpc/testing/main/Util.java | 39 ------ 23 files changed, 608 insertions(+), 160 deletions(-) create mode 100644 net/grpc/gateway/examples/grpc-web-java/greeter-service/pom.xml create mode 100644 net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/GreeterClient.java create mode 100644 net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/GreeterService.java create mode 100644 net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/StartServiceAndGrpcwebProxy.java create mode 100644 net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/proto/greeter.proto create mode 100644 net/grpc/gateway/examples/grpc-web-java/interop-test-service/pom.xml rename src/connector/src/main/java/grpc/testing/main/TestServiceImpl.java => net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/java/grpcweb/examples/InteropTestService.java (94%) create mode 100644 net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/java/grpcweb/examples/StartServiceAndGrpcwebProxy.java rename {src/connector => net/grpc/gateway/examples/grpc-web-java/interop-test-service}/src/main/proto/grpc/testing/empty.proto (100%) rename {src/connector => net/grpc/gateway/examples/grpc-web-java/interop-test-service}/src/main/proto/grpc/testing/messages.proto (100%) rename {src/connector => net/grpc/gateway/examples/grpc-web-java/interop-test-service}/src/main/proto/grpc/testing/test.proto (99%) create mode 100644 src/connector/src/main/java/com/google/grpcweb/GrpcPortNumRelay.java create mode 100644 src/connector/src/main/java/com/google/grpcweb/JettyWebserverForGrpcwebTraffic.java delete mode 100644 src/connector/src/main/java/grpc/testing/main/TestServiceAndProxy.java delete mode 100644 src/connector/src/main/java/grpc/testing/main/Util.java diff --git a/net/grpc/gateway/examples/grpc-web-java/greeter-service/pom.xml b/net/grpc/gateway/examples/grpc-web-java/greeter-service/pom.xml new file mode 100644 index 0000000..028309c --- /dev/null +++ b/net/grpc/gateway/examples/grpc-web-java/greeter-service/pom.xml @@ -0,0 +1,117 @@ + + + + 4.0.0 + + grpc.testing.main + grpcweb-java-examples-greeter + 0.1 + + + UTF-8 + 1.7 + 1.7 + 7080 + 8080 + + + + + com.google.protobuf + protobuf-java + 3.11.4 + + + junit + junit + 4.13 + + + com.google.grpcweb + grpcweb-java + 0.1-SNAPSHOT + + + org.apache.httpcomponents + fluent-hc + 4.5.12 + + + + + + + kr.motd.maven + os-maven-plugin + 1.6.2 + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.5.0 + + com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier} + grpc-java + io.grpc:protoc-gen-grpc-java:1.7.0:exe:${os.detected.classifier} + + + + + compile + compile-custom + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0.0 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/my.properties + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + + my-execution + test + + java + + + + + grpcweb.examples.greeter.GreeterClient + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + + + diff --git a/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/GreeterClient.java b/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/GreeterClient.java new file mode 100644 index 0000000..2e38d05 --- /dev/null +++ b/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/GreeterClient.java @@ -0,0 +1,106 @@ +/* + * Copyright 2020 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. + */ + +package grpcweb.examples.greeter; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.google.protobuf.InvalidProtocolBufferException; +import grpcweb.examples.greeter.GreeterOuterClass.HelloReply; +import grpcweb.examples.greeter.GreeterOuterClass.HelloRequest; +import java.lang.invoke.MethodHandles; +import java.nio.ByteBuffer; +import java.util.logging.Logger; +import org.apache.http.HttpVersion; +import org.apache.http.client.fluent.Request; +import org.apache.http.entity.ContentType; + +/** + * A simple client that requests a greeting from the {@link GreeterService}. + */ +public class GreeterClient { + private static final Logger LOG = + Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); + + private static byte[] packageReqObj(HelloRequest req) { + byte[] reqObjBytes = req.toByteArray(); + int len = reqObjBytes.length; + byte[] packagedBytes = new byte[5 + len]; + packagedBytes[0] = (byte) 0x00; + packagedBytes[1] = (byte) ((len >> 24) & 0xff); + packagedBytes[2] = (byte) ((len >> 16) & 0xff); + packagedBytes[3] = (byte) ((len >> 8) & 0xff); + packagedBytes[4] = (byte) ((len >> 0) & 0xff); + System.arraycopy(reqObjBytes, 0, packagedBytes, 5, len); + return packagedBytes; + } + + private static void validateResponse(byte[] response) throws InvalidProtocolBufferException { + LOG.info("Response length = " + response.length); + LOG.info("Response is: " + new String(response)); + + // validate the 1st byte + assertEquals((byte)0x00, response[0]); + + int len = ByteBuffer.wrap(response, 1, 4).getInt(); + assertEquals(11, len); + + // copy len bytes into a byte array, which can be xlated into HelloResponse + byte[] protoBytes = new byte[len]; + System.arraycopy(response, 5, protoBytes, 0, len); + HelloReply reply = HelloReply.parseFrom(protoBytes); + assertEquals("Hello foo", reply.getMessage()); + + // if there is more data in the response, it should be a trailer. + int offset = len + 5; + int trailerBlockLen = response.length - offset; + if (trailerBlockLen == 0) { + // don't have any more bytes. we are done + return; + } + assertEquals((byte)0x80, response[offset]); + offset++; + int trailerLen = ByteBuffer.wrap(response, offset, 4).getInt(); + assertTrue(trailerLen > 0); + + byte[] trailer = new byte[trailerLen]; + System.arraycopy(response, offset+4, trailer, 0, trailerLen); + String trailerStr = new String(trailer); + LOG.info("received trailer: " + trailerStr); + assertTrue(trailerStr.startsWith("grpc-status:0")); + } + + public static void main(String[] args) throws Exception { + StartServiceAndGrpcwebProxy proxyStarter = new StartServiceAndGrpcwebProxy(); + proxyStarter.start(); + + // create a HelloRequest obj + HelloRequest reqObj = HelloRequest.newBuilder().setName("foo").build(); + byte[] packagedBytes = packageReqObj(reqObj); + + // send request to the grpc-web server + ContentType contentType = ContentType.create("application/grpc-web"); + byte[] response = Request.Post("http://localhost:" + proxyStarter.getGrpcwebPortNum() + + "/grpcweb.examples.greeter.Greeter/SayHello") + .useExpectContinue() + .version(HttpVersion.HTTP_1_1) + .bodyByteArray(packagedBytes, contentType) + .execute().returnContent().asBytes(); + validateResponse(response); + System.exit(0); + } +} diff --git a/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/GreeterService.java b/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/GreeterService.java new file mode 100644 index 0000000..8bb7d5d --- /dev/null +++ b/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/GreeterService.java @@ -0,0 +1,31 @@ +/* + * Copyright 2020 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. + */ + +package grpcweb.examples.greeter; + +import grpcweb.examples.greeter.GreeterOuterClass.HelloReply; +import grpcweb.examples.greeter.GreeterOuterClass.HelloRequest; +import io.grpc.stub.StreamObserver; + +public class GreeterService extends GreeterGrpc.GreeterImplBase { + @Override + public void sayHello(HelloRequest req, StreamObserver responseObserver) { + System.out.println("Greeter Service responding in sayhello() method"); + HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } +} diff --git a/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/StartServiceAndGrpcwebProxy.java b/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/StartServiceAndGrpcwebProxy.java new file mode 100644 index 0000000..ef7bd6f --- /dev/null +++ b/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/java/grpcweb/examples/greeter/StartServiceAndGrpcwebProxy.java @@ -0,0 +1,51 @@ +package grpcweb.examples.greeter; + +import com.google.grpcweb.GrpcPortNumRelay; +import com.google.grpcweb.JettyWebserverForGrpcwebTraffic; +import io.grpc.BindableService; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import java.lang.invoke.MethodHandles; +import java.util.Properties; +import java.util.logging.Logger; + +/** + * This class starts the service on a port (property: grpc-port) + * and starts the grpc-web proxy on a different port (property: grpc-web-port). + */ +class StartServiceAndGrpcwebProxy { + private static final Logger LOG = + Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); + java.util.Properties properties; + private int grpcWebPort; + + private void startGrpcService(int port) throws Exception { + Server grpcServer = ServerBuilder.forPort(port) + .addService((BindableService) new GreeterService()) + .build(); + grpcServer.start(); + LOG.info("**** started gRPC Service on port# " + port); + } + + int getGrpcwebPortNum() { + return grpcWebPort; + } + + void start() throws Exception { + java.io.InputStream inputStream = + Thread.currentThread().getContextClassLoader().getResourceAsStream("my.properties"); + properties = new Properties(); + properties.load(inputStream); + int grpcPort = Integer.parseInt(properties.getProperty("grpc-port")); + grpcWebPort = Integer.parseInt(properties.getProperty("grpc-web-port")); + LOG.info("grpc-port = " + grpcPort + ", grpc-web-port = " + grpcWebPort); + + // Start the Grpc service on grpc-port + startGrpcService(grpcPort); + + // Start the grpc-web proxy on grpc-web-port. + (new JettyWebserverForGrpcwebTraffic(grpcWebPort)).start(); + // grpc-web proxy needs to know the grpc-port# so it could connect to the grpc service. + GrpcPortNumRelay.setGrpcPortNum(grpcPort); + } +} diff --git a/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/proto/greeter.proto b/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/proto/greeter.proto new file mode 100644 index 0000000..b61bd3f --- /dev/null +++ b/net/grpc/gateway/examples/grpc-web-java/greeter-service/src/main/proto/greeter.proto @@ -0,0 +1,34 @@ +// Copyright 2020 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. +syntax = "proto3"; + +option java_package = "grpcweb.examples.greeter"; + +package grpcweb.examples.greeter; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/net/grpc/gateway/examples/grpc-web-java/interop-test-service/pom.xml b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/pom.xml new file mode 100644 index 0000000..1765dde --- /dev/null +++ b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/pom.xml @@ -0,0 +1,108 @@ + + + + 4.0.0 + + grpc.testing.main + grpcweb-java-examples-interop-test + 0.1 + grpcweb-java-examples-interop-test + + + UTF-8 + 1.7 + 1.7 + 7080 + 8080 + + + + + com.google.protobuf + protobuf-java + 3.11.4 + + + com.google.grpcweb + grpcweb-java + 0.1-SNAPSHOT + + + + + + + kr.motd.maven + os-maven-plugin + 1.6.2 + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.5.0 + + com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier} + grpc-java + io.grpc:protoc-gen-grpc-java:1.7.0:exe:${os.detected.classifier} + + + + + compile + compile-custom + + + + + + org.codehaus.mojo + properties-maven-plugin + 1.0.0 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/my.properties + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + + my-execution + test + + java + + + + + grpcweb.examples.StartServiceAndGrpcwebProxy + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + + + diff --git a/src/connector/src/main/java/grpc/testing/main/TestServiceImpl.java b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/java/grpcweb/examples/InteropTestService.java similarity index 94% rename from src/connector/src/main/java/grpc/testing/main/TestServiceImpl.java rename to net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/java/grpcweb/examples/InteropTestService.java index 3d7e136..4f25b35 100644 --- a/src/connector/src/main/java/grpc/testing/main/TestServiceImpl.java +++ b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/java/grpcweb/examples/InteropTestService.java @@ -18,7 +18,7 @@ // This is copy of the following: // github.com/grpc/grpc-java/blob/master/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java -package grpc.testing.main; +package grpcweb.examples; import com.google.common.base.Preconditions; import com.google.common.collect.Queues; @@ -30,6 +30,7 @@ import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; import io.grpc.Status; import io.grpc.internal.LogExceptionRunnable; +import io.grpc.protobuf.lite.ProtoLiteUtils; import io.grpc.stub.ServerCallStreamObserver; import io.grpc.stub.StreamObserver; import grpc.testing.EmptyProtos; @@ -59,16 +60,26 @@ import javax.annotation.concurrent.GuardedBy; * Implementation of the business logic for the TestService. Uses an executor to schedule chunks * sent in response streams. */ -public class TestServiceImpl extends TestServiceGrpc.TestServiceImplBase { +public class InteropTestService extends TestServiceGrpc.TestServiceImplBase { private final Random random = new Random(); private final ScheduledExecutorService executor; private final ByteString compressableBuffer; + private static final Metadata.Key METADATA_KEY = + Metadata.Key.of( + "grpc.testing.SimpleContext" + Metadata.BINARY_HEADER_SUFFIX, + ProtoLiteUtils.metadataMarshaller(Messages.SimpleContext.getDefaultInstance())); + private static final Metadata.Key ECHO_INITIAL_METADATA_KEY + = Metadata.Key.of("x-grpc-test-echo-initial", Metadata.ASCII_STRING_MARSHALLER); + private static final Metadata.Key ECHO_TRAILING_METADATA_KEY + = Metadata.Key.of("x-grpc-test-echo-trailing-bin", Metadata.BINARY_BYTE_MARSHALLER); + + /** * Constructs a controller using the given executor for scheduling response stream chunks. */ - public TestServiceImpl(ScheduledExecutorService executor) { + public InteropTestService(ScheduledExecutorService executor) { this.executor = executor; this.compressableBuffer = ByteString.copyFrom(new byte[1024]); } @@ -445,9 +456,9 @@ public class TestServiceImpl extends TestServiceGrpc.TestServiceImplBase { /** Returns interceptors necessary for full service implementation. */ public static List interceptors() { return Arrays.asList( - echoRequestHeadersInterceptor(Util.METADATA_KEY), - echoRequestMetadataInHeaders(Util.ECHO_INITIAL_METADATA_KEY), - echoRequestMetadataInTrailers(Util.ECHO_TRAILING_METADATA_KEY)); + echoRequestHeadersInterceptor(METADATA_KEY), + echoRequestMetadataInHeaders(ECHO_INITIAL_METADATA_KEY), + echoRequestMetadataInTrailers(ECHO_TRAILING_METADATA_KEY)); } /** diff --git a/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/java/grpcweb/examples/StartServiceAndGrpcwebProxy.java b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/java/grpcweb/examples/StartServiceAndGrpcwebProxy.java new file mode 100644 index 0000000..8f544a9 --- /dev/null +++ b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/java/grpcweb/examples/StartServiceAndGrpcwebProxy.java @@ -0,0 +1,57 @@ +package grpcweb.examples; + +import com.google.grpcweb.GrpcPortNumRelay; +import com.google.grpcweb.JettyWebserverForGrpcwebTraffic; +import io.grpc.BindableService; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.ServerInterceptors; +import java.lang.invoke.MethodHandles; +import java.util.Properties; +import java.util.concurrent.Executors; +import java.util.logging.Logger; + +/** + * This class starts the service on a port (property: grpc-port) + * and starts the grpc-web proxy on a different port (property: grpc-web-port). + */ +class StartServiceAndGrpcwebProxy { + private static final Logger LOG = + Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); + java.util.Properties properties; + private int grpcWebPort; + + private void startGrpcService(int port) throws Exception { + Server grpcServer = ServerBuilder.forPort(port) + .addService( + ServerInterceptors.intercept( + (BindableService) new InteropTestService(Executors.newSingleThreadScheduledExecutor()), + InteropTestService.interceptors())) + .build(); + grpcServer.start(); + LOG.info("**** started gRPC Service on port# " + port); + } + + void start() throws Exception { + java.io.InputStream inputStream = + Thread.currentThread().getContextClassLoader().getResourceAsStream("my.properties"); + properties = new Properties(); + properties.load(inputStream); + int grpcPort = Integer.parseInt(properties.getProperty("grpc-port")); + grpcWebPort = Integer.parseInt(properties.getProperty("grpc-web-port")); + LOG.info("grpc-port = " + grpcPort + ", grpc-web-port = " + grpcWebPort); + + // Start the Grpc service on grpc-port + startGrpcService(grpcPort); + + // Start the grpc-web proxy on grpc-web-port. + (new JettyWebserverForGrpcwebTraffic(grpcWebPort)).start(); + + // grpc-web proxy needs to know the grpc-port# so it could connect to the grpc service. + GrpcPortNumRelay.setGrpcPortNum(grpcPort); + } + + public static void main(String[] args) throws Exception { + new StartServiceAndGrpcwebProxy().start(); + } +} diff --git a/src/connector/src/main/proto/grpc/testing/empty.proto b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/proto/grpc/testing/empty.proto similarity index 100% rename from src/connector/src/main/proto/grpc/testing/empty.proto rename to net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/proto/grpc/testing/empty.proto diff --git a/src/connector/src/main/proto/grpc/testing/messages.proto b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/proto/grpc/testing/messages.proto similarity index 100% rename from src/connector/src/main/proto/grpc/testing/messages.proto rename to net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/proto/grpc/testing/messages.proto diff --git a/src/connector/src/main/proto/grpc/testing/test.proto b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/proto/grpc/testing/test.proto similarity index 99% rename from src/connector/src/main/proto/grpc/testing/test.proto rename to net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/proto/grpc/testing/test.proto index c1e31ce..26347d5 100644 --- a/src/connector/src/main/proto/grpc/testing/test.proto +++ b/net/grpc/gateway/examples/grpc-web-java/interop-test-service/src/main/proto/grpc/testing/test.proto @@ -13,9 +13,14 @@ // limitations under the License. // An integration test service that covers all the method signature permutations // of unary/streaming requests/responses. +// +// // ******************* DO NOT EDIT +// // This is copy of the following: // github.com/grpc/grpc-java/blob/master/interop-testing/src/main/proto/grpc/testing/test.proto +// +// ********************* syntax = "proto3"; diff --git a/src/connector/pom.xml b/src/connector/pom.xml index 392d0a7..d1990ed 100644 --- a/src/connector/pom.xml +++ b/src/connector/pom.xml @@ -5,10 +5,9 @@ 4.0.0 com.google.grpcweb - grpcweb - 0.1 - - grpcweb + grpcweb-java + 0.1-SNAPSHOT + grpcweb-java UTF-8 @@ -91,39 +90,9 @@ - org.xolstice.maven.plugins - protobuf-maven-plugin - 0.5.0 - - com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier} - grpc-java - io.grpc:protoc-gen-grpc-java:1.7.0:exe:${os.detected.classifier} - - - - - compile - compile-custom - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.4.0 - - - my-execution - test - - java - - - - - grpc.testing.main.TestServiceAndProxy - + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 org.apache.maven.plugins diff --git a/src/connector/src/main/java/com/google/grpcweb/DebugInfo.java b/src/connector/src/main/java/com/google/grpcweb/DebugInfo.java index eb35f16..79f11c7 100644 --- a/src/connector/src/main/java/com/google/grpcweb/DebugInfo.java +++ b/src/connector/src/main/java/com/google/grpcweb/DebugInfo.java @@ -16,16 +16,18 @@ package com.google.grpcweb; +import java.lang.invoke.MethodHandles; import java.util.Enumeration; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.http.HttpServletRequest; class DebugInfo { - private static final Logger LOGGER = Logger.getLogger(DebugInfo.class.getName()); + private static final Logger LOG = + Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); static void printRequest(HttpServletRequest req) { - if (!LOGGER.isLoggable(Level.FINE)) return; + if (!LOG.isLoggable(Level.FINE)) return; StringBuilder sb = new StringBuilder(); Enumeration headerNames = req.getHeaderNames(); @@ -54,6 +56,6 @@ class DebugInfo { sb.append("\n\t ServerPort: ").append(req.getServerPort()); sb.append("\n\t ServletPath: ").append(req.getServletPath()); sb.append("\n\t Method: ").append(req.getMethod()); - LOGGER.fine(sb.toString()); + LOG.fine(sb.toString()); } } diff --git a/src/connector/src/main/java/com/google/grpcweb/GrpcPortNumRelay.java b/src/connector/src/main/java/com/google/grpcweb/GrpcPortNumRelay.java new file mode 100644 index 0000000..f2e0c50 --- /dev/null +++ b/src/connector/src/main/java/com/google/grpcweb/GrpcPortNumRelay.java @@ -0,0 +1,14 @@ +package com.google.grpcweb; + +public class GrpcPortNumRelay { + private static int sGrpcPortNum = 0; + + public static void setGrpcPortNum(int i) { + // make sure this is set only once + if (sGrpcPortNum == 0) sGrpcPortNum = i; + } + + static int getGrpcPortNum() { + return sGrpcPortNum; + } +} diff --git a/src/connector/src/main/java/com/google/grpcweb/GrpcWebClientInterceptor.java b/src/connector/src/main/java/com/google/grpcweb/GrpcWebClientInterceptor.java index 2cba80d..10351af 100644 --- a/src/connector/src/main/java/com/google/grpcweb/GrpcWebClientInterceptor.java +++ b/src/connector/src/main/java/com/google/grpcweb/GrpcWebClientInterceptor.java @@ -27,11 +27,10 @@ import io.grpc.Metadata; import io.grpc.MethodDescriptor; import io.grpc.Status; import java.util.concurrent.CountDownLatch; -import java.util.logging.Logger; import javax.servlet.http.HttpServletResponse; class GrpcWebClientInterceptor implements ClientInterceptor { - private static final Logger LOG = Logger.getLogger(GrpcWebClientInterceptor.class.getName()); + private final CountDownLatch mLatch; private final HttpServletResponse mResp; private final SendResponse mSendResponse; @@ -72,8 +71,7 @@ class GrpcWebClientInterceptor implements ClientInterceptor { // seems, sometimes onHeaders() is not called before this method is called! // so far, they are the error cases. let onError() method in ClientListener // handle this call. Could ignore this. - // TODO is this correct? what if onError() never gets called? maybe here it should - // be handled: send headers first and then send the trailers. + // TODO is this correct? what if onError() never gets called? } else { mSendResponse.writeTrailer(s, t); mLatch.countDown(); diff --git a/src/connector/src/main/java/com/google/grpcweb/GrpcWebGuiceModule.java b/src/connector/src/main/java/com/google/grpcweb/GrpcWebGuiceModule.java index 3a9fafc..9c99a98 100644 --- a/src/connector/src/main/java/com/google/grpcweb/GrpcWebGuiceModule.java +++ b/src/connector/src/main/java/com/google/grpcweb/GrpcWebGuiceModule.java @@ -17,16 +17,10 @@ package com.google.grpcweb; import com.google.inject.AbstractModule; -public class GrpcWebGuiceModule extends AbstractModule { - private static int sGrpcPortNum = 0; - - public static void setGrpcPortNum(int i) { - if (sGrpcPortNum == 0) sGrpcPortNum = i; - } - +class GrpcWebGuiceModule extends AbstractModule { @Override protected void configure() { bind(GrpcServiceConnectionManager.class) - .toInstance(new GrpcServiceConnectionManager(sGrpcPortNum)); + .toInstance(new GrpcServiceConnectionManager(GrpcPortNumRelay.getGrpcPortNum())); } } diff --git a/src/connector/src/main/java/com/google/grpcweb/JettyWebserverForGrpcwebTraffic.java b/src/connector/src/main/java/com/google/grpcweb/JettyWebserverForGrpcwebTraffic.java new file mode 100644 index 0000000..fbb83be --- /dev/null +++ b/src/connector/src/main/java/com/google/grpcweb/JettyWebserverForGrpcwebTraffic.java @@ -0,0 +1,38 @@ +package com.google.grpcweb; + +import java.lang.invoke.MethodHandles; +import java.util.EnumSet; +import java.util.logging.Logger; +import javax.servlet.DispatcherType; +import org.eclipse.jetty.servlet.ServletHandler; + +public class JettyWebserverForGrpcwebTraffic { + private static final Logger LOG = + Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); + + private final int mGrpcwebPort; + + public JettyWebserverForGrpcwebTraffic(int grpcwebPort) { + mGrpcwebPort = grpcwebPort; + } + + public org.eclipse.jetty.server.Server start() { + // Start a jetty server to listen on the grpc-web port# + org.eclipse.jetty.server.Server jServer = new org.eclipse.jetty.server.Server(mGrpcwebPort); + ServletHandler handler = new ServletHandler(); + jServer.setHandler(handler); + handler.addFilterWithMapping(CorsFilter.class, "/*", + EnumSet.of(DispatcherType.REQUEST)); + handler.addServletWithMapping(GrpcWebTrafficServlet.class, "/*"); + try { + jServer.start(); + } catch (Exception e) { + LOG.warning("Jetty Server couldn't be started. " + e.getLocalizedMessage()); + e.printStackTrace(); + return null; + } + LOG.info("**** started gRPC-web Service on port# " + mGrpcwebPort); + jServer.setStopAtShutdown(true); + return jServer; + } +} diff --git a/src/connector/src/main/java/com/google/grpcweb/MessageDeframer.java b/src/connector/src/main/java/com/google/grpcweb/MessageDeframer.java index 1fd84c6..ee9422b 100644 --- a/src/connector/src/main/java/com/google/grpcweb/MessageDeframer.java +++ b/src/connector/src/main/java/com/google/grpcweb/MessageDeframer.java @@ -18,6 +18,7 @@ package com.google.grpcweb; import com.google.grpcweb.MessageHandler.ContentType; import java.io.IOException; import java.io.InputStream; +import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; @@ -29,7 +30,9 @@ import org.apache.commons.io.IOUtils; * Reads frames from the input bytes and returns a single message. */ class MessageDeframer { - private static final Logger LOGGER = Logger.getLogger(MessageDeframer.class.getName()); + private static final Logger LOG = + Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); + static final byte DATA_BYTE = (byte) 0x00; // TODO: fix this code to be able to handle upto 4GB input size. @@ -55,11 +58,11 @@ class MessageDeframer { inBytes = IOUtils.toByteArray(inStream); } catch (IOException e) { e.printStackTrace(); - LOGGER.warning("invalid input"); + LOG.warning("invalid input"); return false; } if (inBytes.length < 5) { - LOGGER.fine("invalid input. Expected minimum of 5 bytes"); + LOG.fine("invalid input. Expected minimum of 5 bytes"); return false; } @@ -88,7 +91,7 @@ class MessageDeframer { // Firstbyte should be 0x00 (for this to be a DATA frame) int firstByteValue = inBytes[mReadSoFar] | DATA_BYTE; if (firstByteValue != 0) { - LOGGER.fine("done with DATA bytes"); + LOG.fine("done with DATA bytes"); return false; } @@ -106,7 +109,7 @@ class MessageDeframer { // Make sure we have enough bytes in the inputstream int expectedNumBytes = len + 5 + mReadSoFar; if (inBytes.length < expectedNumBytes) { - LOGGER.warning(String.format("input doesn't have enough bytes. expected: %d, found %d", + LOG.warning(String.format("input doesn't have enough bytes. expected: %d, found %d", expectedNumBytes, inBytes.length)); return false; } diff --git a/src/connector/src/main/java/com/google/grpcweb/MetadataUtil.java b/src/connector/src/main/java/com/google/grpcweb/MetadataUtil.java index e469afd..65234ab 100644 --- a/src/connector/src/main/java/com/google/grpcweb/MetadataUtil.java +++ b/src/connector/src/main/java/com/google/grpcweb/MetadataUtil.java @@ -16,7 +16,6 @@ package com.google.grpcweb; import io.grpc.Metadata; -import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; diff --git a/src/connector/src/main/java/com/google/grpcweb/RequestHandler.java b/src/connector/src/main/java/com/google/grpcweb/RequestHandler.java index 9a8d47d..fa0382c 100644 --- a/src/connector/src/main/java/com/google/grpcweb/RequestHandler.java +++ b/src/connector/src/main/java/com/google/grpcweb/RequestHandler.java @@ -21,6 +21,7 @@ import io.grpc.Metadata; import io.grpc.Status; import io.grpc.stub.MetadataUtils; import io.grpc.stub.StreamObserver; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -32,7 +33,8 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; class RequestHandler { - private static final Logger LOG = Logger.getLogger(RequestHandler.class.getName()); + private static final Logger LOG = + Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); private final MessageHandler mMessageHandler; private final GrpcServiceConnectionManager mGrpcServiceConnectionManager; @@ -56,6 +58,7 @@ class RequestHandler { String methodName = classAndMethodNames.getRight(); Class cls = getClassObject(className); if (cls == null) { + LOG.info("incorrect classname in the request: " + className); // incorrect classname specified in the request. sendResponse.returnUnimplementedStatusCode(); return; diff --git a/src/connector/src/main/java/com/google/grpcweb/SendResponse.java b/src/connector/src/main/java/com/google/grpcweb/SendResponse.java index 6296f08..096ce2f 100644 --- a/src/connector/src/main/java/com/google/grpcweb/SendResponse.java +++ b/src/connector/src/main/java/com/google/grpcweb/SendResponse.java @@ -19,6 +19,7 @@ import com.google.grpcweb.MessageHandler.ContentType; import io.grpc.Metadata; import io.grpc.Status; import java.io.IOException; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.logging.Logger; import javax.servlet.ServletOutputStream; @@ -27,7 +28,8 @@ import javax.servlet.http.HttpServletResponse; import java.util.Base64; class SendResponse { - private static final Logger LOG = Logger.getLogger(SendResponse.class.getName()); + private static final Logger LOG = + Logger.getLogger(MethodHandles.lookup().lookupClass().getName()); private final String mContentType; private final HttpServletResponse mResp; diff --git a/src/connector/src/main/java/grpc/testing/main/TestServiceAndProxy.java b/src/connector/src/main/java/grpc/testing/main/TestServiceAndProxy.java deleted file mode 100644 index 04132e5..0000000 --- a/src/connector/src/main/java/grpc/testing/main/TestServiceAndProxy.java +++ /dev/null @@ -1,55 +0,0 @@ -package grpc.testing.main; - -import com.google.grpcweb.CorsFilter; -import com.google.grpcweb.GrpcWebGuiceModule; -import com.google.grpcweb.GrpcWebTrafficServlet; -import io.grpc.BindableService; -import io.grpc.Server; -import io.grpc.ServerBuilder; -import io.grpc.ServerInterceptors; -import java.util.EnumSet; -import java.util.concurrent.Executors; -import java.util.logging.Logger; -import javax.servlet.DispatcherType; -import org.eclipse.jetty.servlet.ServletHandler; - -/** - * This class starts the service on a port (GRPC_PORT) and starts the grpc-web proxy on - * a different port (GRPC_WEB_PORT). - */ -public class TestServiceAndProxy { - private static final Logger LOGGER = Logger.getLogger(TestServiceAndProxy.class.getName()); - private static final int GRPC_PORT = 7074; - private static final int GRPC_WEB_PORT = 8080; - - private static Server startGrpcService(int port) throws Exception { - Server grpcServer = ServerBuilder.forPort(port) - .addService( - ServerInterceptors.intercept( - (BindableService) new TestServiceImpl(Executors.newSingleThreadScheduledExecutor()), - TestServiceImpl.interceptors())) - .build(); - grpcServer.start(); - LOGGER.info("**** started gRPC Service on port# " + port); - return grpcServer; - } - - private static void listenForGrpcWebReq(int grpcWebPort) throws Exception { - // Start a jetty server to listen on the grpc-web port# - org.eclipse.jetty.server.Server jServer = new org.eclipse.jetty.server.Server(grpcWebPort); - ServletHandler handler = new ServletHandler(); - jServer.setHandler(handler); - handler.addFilterWithMapping(CorsFilter.class, "/*", - EnumSet.of(DispatcherType.REQUEST)); - handler.addServletWithMapping(GrpcWebTrafficServlet.class, "/*"); - jServer.start(); - LOGGER.info("**** started gRPC-web Service on port# " + grpcWebPort); - } - - public static void main(String[] args) throws Exception { - GrpcWebGuiceModule.setGrpcPortNum(GRPC_PORT); - Server grpcServer = startGrpcService(GRPC_PORT); - listenForGrpcWebReq(GRPC_WEB_PORT); - grpcServer.awaitTermination(); - } -} diff --git a/src/connector/src/main/java/grpc/testing/main/Util.java b/src/connector/src/main/java/grpc/testing/main/Util.java deleted file mode 100644 index a047429..0000000 --- a/src/connector/src/main/java/grpc/testing/main/Util.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2020 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. - */ -// ******************* DO NOT EDIT -// This is copy of the following: -// github.com/grpc/grpc-java/blob/master/interop-testing/src/main/java/io/grpc/testing/integration/Util.java - -package grpc.testing.main; - -import io.grpc.Metadata; -import io.grpc.protobuf.lite.ProtoLiteUtils; -import grpc.testing.Messages; - -/** - * Utility methods to support integration testing. - */ -public class Util { - - public static final Metadata.Key METADATA_KEY = - Metadata.Key.of( - "grpc.testing.SimpleContext" + Metadata.BINARY_HEADER_SUFFIX, - ProtoLiteUtils.metadataMarshaller(Messages.SimpleContext.getDefaultInstance())); - public static final Metadata.Key ECHO_INITIAL_METADATA_KEY - = Metadata.Key.of("x-grpc-test-echo-initial", Metadata.ASCII_STRING_MARSHALLER); - public static final Metadata.Key ECHO_TRAILING_METADATA_KEY - = Metadata.Key.of("x-grpc-test-echo-trailing-bin", Metadata.BINARY_BYTE_MARSHALLER); -}