Add simple HelloWord example handling custom header

This commit is contained in:
zhaohaifeng 2015-03-16 18:32:39 +08:00 committed by Eric Anderson
parent f3ccdd99f1
commit 63db06850e
4 changed files with 360 additions and 0 deletions

View File

@ -0,0 +1,104 @@
/*
* Copyright 2015, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.grpc.examples.header;
import io.grpc.Channel;
import io.grpc.ChannelImpl;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.examples.helloworld.HelloResponse;
import io.grpc.transport.netty.NegotiationType;
import io.grpc.transport.netty.NettyChannelBuilder;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A simple client that like {@link io.grpc.examples.helloworld.HelloWorldClient}.
* This client can help you create custom headers.
*/
public class CustomHeaderClient {
private static final Logger logger = Logger.getLogger(CustomHeaderClient.class.getName());
private final ChannelImpl originChannel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
/**
* A custom client.
*/
private CustomHeaderClient(String host, int port) {
originChannel =
NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT)
.build();
ClientInterceptor interceptor = new HeaderClientInterceptor();
Channel channel = ClientInterceptors.intercept(originChannel, interceptor);
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
private void shutdown() throws InterruptedException {
originChannel.shutdown().awaitTerminated(5, TimeUnit.SECONDS);
}
/**
* A simple client method that like {@link io.grpc.examples.helloworld.HelloWorldClient}.
*/
private void greet(String name) {
try {
logger.info("Will try to greet " + name + " ...");
HelloRequest request = HelloRequest.newBuilder().setName(name).build();
HelloResponse response = blockingStub.sayHello(request);
logger.info("Greeting: " + response.getMessage());
} catch (RuntimeException e) {
logger.log(Level.WARNING, "RPC failed", e);
}
}
/**
* Main start the client from the command line.
*/
public static void main(String[] args) throws Exception {
CustomHeaderClient client = new CustomHeaderClient("localhost", 50051);
try {
/* Access a service running on the local machine on port 50051 */
String user = "world";
if (args.length > 0) {
user = args[0]; /* Use the arg as the name to greet if provided */
}
client.greet(user);
} finally {
client.shutdown();
}
}
}

View File

@ -0,0 +1,94 @@
/*
* Copyright 2015, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.grpc.examples.header;
import io.grpc.ServerImpl;
import io.grpc.ServerInterceptors;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.examples.helloworld.HelloResponse;
import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.NettyServerBuilder;
import java.util.logging.Logger;
/**
* A simple server that like {@link io.grpc.examples.helloworld.HelloWorldServer}.
* You can get and response any header in {@link io.grpc.examples.header.HeaderServerInterceptor}.
*/
public class CustomHeaderServer {
private static final Logger logger = Logger.getLogger(CustomHeaderServer.class.getName());
/* The port on which the server should run */
private static final int port = 50051;
private ServerImpl server;
private void start() throws Exception {
server = NettyServerBuilder.forPort(port).addService(ServerInterceptors
.intercept(GreeterGrpc.bindService(new GreeterImpl()), new HeaderServerInterceptor()))
.build().start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
CustomHeaderServer.this.stop();
System.err.println("*** server shut down");
}
});
}
private void stop() {
if (server != null) {
server.shutdown();
}
}
/**
* Main launches the server from the command line.
*/
public static void main(String[] args) throws Exception {
final CustomHeaderServer server = new CustomHeaderServer();
server.start();
}
private class GreeterImpl implements GreeterGrpc.Greeter {
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloResponse> responseObserver) {
HelloResponse reply = HelloResponse.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onValue(reply);
responseObserver.onCompleted();
}
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright 2015, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.grpc.examples.header;
import io.grpc.Call;
import io.grpc.Channel;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import java.util.logging.Logger;
/**
* A interceptor to handle client header.
*/
public class HeaderClientInterceptor implements ClientInterceptor {
private static final Logger logger = Logger.getLogger(HeaderClientInterceptor.class.getName());
private static Metadata.Key<String> customHeadKey =
Metadata.Key.of("custom_client_header_key", Metadata.ASCII_STRING_MARSHALLER);
@Override
public <ReqT, RespT> Call<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method,
Channel next) {
return new ClientInterceptors.ForwardingCall<ReqT, RespT>(next.newCall(method)) {
@Override
public void start(Listener<RespT> responseListener, Metadata.Headers headers) {
/* put custom header */
headers.put(customHeadKey, "customRequestValue");
super.start(new ClientInterceptors.ForwardingListener<RespT>(responseListener) {
@Override
public void onHeaders(Metadata.Headers headers) {
/**
* if you don't need receive header from server,
* you can use {@link io.grpc.stub.MetadataUtils attachHeaders}
* directly to send header
*/
logger.info("header received from server:" + headers.toString());
super.onHeaders(headers);
}
}, headers);
}
};
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2015, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.grpc.examples.header;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import io.grpc.ServerInterceptors;
import io.grpc.Status;
import java.util.logging.Logger;
/**
* A interceptor to handle server header.
*/
public class HeaderServerInterceptor implements ServerInterceptor {
private static final Logger logger = Logger.getLogger(HeaderServerInterceptor.class.getName());
private static Metadata.Key<String> customHeadKey =
Metadata.Key.of("custom_server_header_key", Metadata.ASCII_STRING_MARSHALLER);
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
String method,
ServerCall<RespT> call,
final Metadata.Headers requestHeaders,
ServerCallHandler<ReqT, RespT> next) {
logger.info("header received from client:" + requestHeaders.toString());
return next.startCall(method, new ServerInterceptors.ForwardingServerCall<RespT>(call) {
boolean sentHeaders = false;
@Override
public void sendHeaders(Metadata.Headers responseHeaders) {
responseHeaders.put(customHeadKey, "customRespondValue");
super.sendHeaders(responseHeaders);
sentHeaders = true;
}
@Override
public void sendPayload(RespT payload) {
if (!sentHeaders) {
sendHeaders(new Metadata.Headers());
}
super.sendPayload(payload);
}
@Override
public void close(Status status, Metadata.Trailers trailers) {
super.close(status, trailers);
}
}, requestHeaders);
}
}