mirror of https://github.com/grpc/grpc-web.git
Merge pull request #861 from vnorigoog/props-in-file
Separate Core code from Examples and interop-test code.
This commit is contained in:
commit
88d70ecbdb
|
@ -0,0 +1,112 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>grpc.testing.main</groupId>
|
||||
<artifactId>grpcweb-java-examples-greeter</artifactId>
|
||||
<version>0.1</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
<grpc-port>7080</grpc-port>
|
||||
<grpc-web-port>8080</grpc-web-port>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>3.11.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.grpcweb</groupId>
|
||||
<artifactId>grpcweb-java</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>fluent-hc</artifactId>
|
||||
<version>4.5.12</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>kr.motd.maven</groupId>
|
||||
<artifactId>os-maven-plugin</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.xolstice.maven.plugins</groupId>
|
||||
<artifactId>protobuf-maven-plugin</artifactId>
|
||||
<version>0.5.0</version>
|
||||
<configuration>
|
||||
<protocArtifact>com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier}</protocArtifact>
|
||||
<pluginId>grpc-java</pluginId>
|
||||
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.7.0:exe:${os.detected.classifier}</pluginArtifact>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>compile-custom</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>properties-maven-plugin</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>write-project-properties</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputFile>${project.build.outputDirectory}/my.properties</outputFile>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// ================================================
|
||||
//
|
||||
// This is for testing only. Just to demonstrate a simple
|
||||
// Java client to send grpc-web request and receive response
|
||||
//
|
||||
// ================================================
|
||||
|
||||
package grpcweb.examples.greeter;
|
||||
|
||||
import grpcweb.examples.greeter.GreeterOuterClass.HelloRequest;
|
||||
import java.io.IOException;
|
||||
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 {
|
||||
static byte[] sendGrpcWebReqAndReceiveResponse() throws IOException {
|
||||
// create a HelloRequest obj
|
||||
HelloRequest reqObj = HelloRequest.newBuilder().setName("foo").build();
|
||||
byte[] packagedBytes = Util.packageReqObjIntoGrpcwebProtocol(reqObj);
|
||||
|
||||
// send request to the grpc-web server
|
||||
ContentType contentType = ContentType.create("application/grpc-web");
|
||||
int grpcWebPort = Util.getGrpcwebServicePortNum();
|
||||
return Request.Post("http://localhost:" + grpcWebPort +
|
||||
"/grpcweb.examples.greeter.Greeter/SayHello")
|
||||
.useExpectContinue()
|
||||
.version(HttpVersion.HTTP_1_1)
|
||||
.bodyByteArray(packagedBytes, contentType)
|
||||
.execute().returnContent().asBytes();
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("Response to Hello Request is: " +
|
||||
new String(sendGrpcWebReqAndReceiveResponse()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// ================================================
|
||||
//
|
||||
// This is for testing only. Just to demonstrate a simple
|
||||
// Java client to send grpc-web request and receive response
|
||||
// and validate the response.
|
||||
//
|
||||
// ================================================
|
||||
|
||||
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 java.lang.invoke.MethodHandles;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A simple client that requests a greeting from the {@link GreeterService}.
|
||||
*/
|
||||
public class GreeterClientTest {
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(MethodHandles.lookup().lookupClass().getName());
|
||||
|
||||
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 {
|
||||
new StartServiceAndGrpcwebProxy().start();
|
||||
byte[] response = GreeterClient.sendGrpcWebReqAndReceiveResponse();
|
||||
validateResponse(response);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
|
@ -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<HelloReply> responseObserver) {
|
||||
System.out.println("Greeter Service responding in sayhello() method");
|
||||
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
* 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 void startGrpcService(int port) throws Exception {
|
||||
Server grpcServer = ServerBuilder.forPort(port)
|
||||
.addService((BindableService) new GreeterService())
|
||||
.build();
|
||||
grpcServer.start();
|
||||
System.out.println("**** started gRPC Service on port# " + port);
|
||||
}
|
||||
|
||||
void start() throws Exception {
|
||||
int grpcPort = Util.getGrpcServicePortNum();
|
||||
int grpcWebPort = Util.getGrpcwebServicePortNum();
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package grpcweb.examples.greeter;
|
||||
|
||||
import grpcweb.examples.greeter.GreeterOuterClass.HelloRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
class Util {
|
||||
static byte[] packageReqObjIntoGrpcwebProtocol(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 int getIntPropertyValue(String s) throws IOException {
|
||||
java.io.InputStream inputStream =
|
||||
Thread.currentThread().getContextClassLoader().getResourceAsStream("my.properties");
|
||||
java.util.Properties properties = new Properties();
|
||||
properties.load(inputStream);
|
||||
return Integer.parseInt(properties.getProperty(s));
|
||||
}
|
||||
|
||||
static int getGrpcServicePortNum() throws IOException {
|
||||
return getIntPropertyValue("grpc-port");
|
||||
}
|
||||
|
||||
static int getGrpcwebServicePortNum() throws IOException {
|
||||
return getIntPropertyValue("grpc-web-port");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
// 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
|
||||
// https://github.com/grpc/grpc-web/blob/master/net/grpc/gateway/
|
||||
// examples/helloworld/helloworld.proto
|
||||
//
|
||||
// TODO: can the original be directly used without making copy here
|
||||
// =======================================
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>grpc.testing.main</groupId>
|
||||
<artifactId>grpcweb-java-examples-interop-test</artifactId>
|
||||
<version>0.1</version>
|
||||
<name>grpcweb-java-examples-interop-test</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
<grpc-port>7080</grpc-port>
|
||||
<grpc-web-port>8080</grpc-web-port>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
<version>3.11.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.grpcweb</groupId>
|
||||
<artifactId>grpcweb-java</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>kr.motd.maven</groupId>
|
||||
<artifactId>os-maven-plugin</artifactId>
|
||||
<version>1.6.2</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.xolstice.maven.plugins</groupId>
|
||||
<artifactId>protobuf-maven-plugin</artifactId>
|
||||
<version>0.5.0</version>
|
||||
<configuration>
|
||||
<protocArtifact>com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier}</protocArtifact>
|
||||
<pluginId>grpc-java</pluginId>
|
||||
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.7.0:exe:${os.detected.classifier}</pluginArtifact>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>compile-custom</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>properties-maven-plugin</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>write-project-properties</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputFile>${project.build.outputDirectory}/my.properties</outputFile>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>my-execution</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>grpcweb.examples.StartServiceAndGrpcwebProxy</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
|
|
@ -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<Messages.SimpleContext> METADATA_KEY =
|
||||
Metadata.Key.of(
|
||||
"grpc.testing.SimpleContext" + Metadata.BINARY_HEADER_SUFFIX,
|
||||
ProtoLiteUtils.metadataMarshaller(Messages.SimpleContext.getDefaultInstance()));
|
||||
private static final Metadata.Key<String> ECHO_INITIAL_METADATA_KEY
|
||||
= Metadata.Key.of("x-grpc-test-echo-initial", Metadata.ASCII_STRING_MARSHALLER);
|
||||
private static final Metadata.Key<byte[]> 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<ServerInterceptor> 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));
|
||||
}
|
||||
|
||||
/**
|
|
@ -0,0 +1,44 @@
|
|||
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.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* 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 void startGrpcService(int port) throws Exception {
|
||||
Server grpcServer = ServerBuilder.forPort(port)
|
||||
.addService(
|
||||
ServerInterceptors.intercept(
|
||||
(BindableService) new InteropTestService(Executors.newSingleThreadScheduledExecutor()),
|
||||
InteropTestService.interceptors()))
|
||||
.build();
|
||||
grpcServer.start();
|
||||
System.out.println("**** started gRPC Service on port# " + port);
|
||||
}
|
||||
|
||||
void start() throws Exception {
|
||||
int grpcPort = Util.getGrpcServicePortNum();
|
||||
int grpcWebPort = Util.getGrpcwebServicePortNum();
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package grpcweb.examples;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
class Util {
|
||||
private static int getIntPropertyValue(String s) throws IOException {
|
||||
java.io.InputStream inputStream =
|
||||
Thread.currentThread().getContextClassLoader().getResourceAsStream("my.properties");
|
||||
java.util.Properties properties = new Properties();
|
||||
properties.load(inputStream);
|
||||
return Integer.parseInt(properties.getProperty(s));
|
||||
}
|
||||
|
||||
static int getGrpcServicePortNum() throws IOException {
|
||||
return getIntPropertyValue("grpc-port");
|
||||
}
|
||||
|
||||
static int getGrpcwebServicePortNum() throws IOException {
|
||||
return getIntPropertyValue("grpc-web-port");
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
|
|
@ -5,10 +5,9 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.google.grpcweb</groupId>
|
||||
<artifactId>grpcweb</artifactId>
|
||||
<version>0.1</version>
|
||||
|
||||
<name>grpcweb</name>
|
||||
<artifactId>grpcweb-java</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>grpcweb-java</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
@ -91,39 +90,9 @@
|
|||
</extensions>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.xolstice.maven.plugins</groupId>
|
||||
<artifactId>protobuf-maven-plugin</artifactId>
|
||||
<version>0.5.0</version>
|
||||
<configuration>
|
||||
<protocArtifact>com.google.protobuf:protoc:3.4.0:exe:${os.detected.classifier}</protocArtifact>
|
||||
<pluginId>grpc-java</pluginId>
|
||||
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.7.0:exe:${os.detected.classifier}</pluginArtifact>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>compile-custom</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>my-execution</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>java</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<mainClass>grpc.testing.main.TestServiceAndProxy</mainClass>
|
||||
</configuration>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
|
|
@ -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<String> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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<Messages.SimpleContext> METADATA_KEY =
|
||||
Metadata.Key.of(
|
||||
"grpc.testing.SimpleContext" + Metadata.BINARY_HEADER_SUFFIX,
|
||||
ProtoLiteUtils.metadataMarshaller(Messages.SimpleContext.getDefaultInstance()));
|
||||
public static final Metadata.Key<String> ECHO_INITIAL_METADATA_KEY
|
||||
= Metadata.Key.of("x-grpc-test-echo-initial", Metadata.ASCII_STRING_MARSHALLER);
|
||||
public static final Metadata.Key<byte[]> ECHO_TRAILING_METADATA_KEY
|
||||
= Metadata.Key.of("x-grpc-test-echo-trailing-bin", Metadata.BINARY_BYTE_MARSHALLER);
|
||||
}
|
Loading…
Reference in New Issue