Merge pull request #2078 from yang-g/grpc_cli_headers

Support sending and showing received metadata in grpc_cli
pull/2106/head
Nicolas Noble 10 years ago
commit b62cdbc18c
  1. 24
      test/cpp/util/cli_call.cc
  2. 12
      test/cpp/util/cli_call.h
  3. 20
      test/cpp/util/cli_call_test.cc
  4. 74
      test/cpp/util/grpc_cli.cc

@ -52,11 +52,20 @@ namespace {
void* tag(int i) { return (void*)(gpr_intptr) i; }
} // namespace
void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
const grpc::string& method, const grpc::string& request,
grpc::string* response) {
Status CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
const grpc::string& method, const grpc::string& request,
grpc::string* response, const MetadataContainer& metadata,
MetadataContainer* server_initial_metadata,
MetadataContainer* server_trailing_metadata) {
std::unique_ptr<grpc::GenericStub> stub(new grpc::GenericStub(channel));
grpc::ClientContext ctx;
if (!metadata.empty()) {
for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
metadata.begin();
iter != metadata.end(); ++iter) {
ctx.AddMetadata(iter->first, iter->second);
}
}
grpc::CompletionQueue cq;
std::unique_ptr<grpc::GenericClientAsyncReaderWriter> call(
stub->Call(&ctx, method, &cq, tag(1)));
@ -79,7 +88,7 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
cq.Next(&got_tag, &ok);
if (!ok) {
std::cout << "Failed to read response." << std::endl;
return;
return Status(StatusCode::INTERNAL, "Failed to read response");
}
grpc::Status status;
call->Finish(&status, tag(5));
@ -87,7 +96,6 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
GPR_ASSERT(ok);
if (status.ok()) {
std::cout << "RPC finished with OK status." << std::endl;
std::vector<grpc::Slice> slices;
recv_buffer.Dump(&slices);
@ -96,10 +104,10 @@ void CliCall::Call(std::shared_ptr<grpc::ChannelInterface> channel,
response->append(reinterpret_cast<const char*>(slices[i].begin()),
slices[i].size());
}
} else {
std::cout << "RPC finished with status code " << status.error_code()
<< " details: " << status.error_message() << std::endl;
}
*server_initial_metadata = ctx.GetServerInitialMetadata();
*server_trailing_metadata = ctx.GetServerTrailingMetadata();
return status;
}
} // namespace testing

@ -34,17 +34,23 @@
#ifndef GRPC_TEST_CPP_UTIL_CLI_CALL_H
#define GRPC_TEST_CPP_UTIL_CLI_CALL_H
#include <map>
#include <grpc++/channel_interface.h>
#include <grpc++/config.h>
#include <grpc++/status.h>
namespace grpc {
namespace testing {
class CliCall GRPC_FINAL {
public:
static void Call(std::shared_ptr<grpc::ChannelInterface> channel,
const grpc::string& method, const grpc::string& request,
grpc::string* response);
typedef std::multimap<grpc::string, grpc::string> MetadataContainer;
static Status Call(std::shared_ptr<grpc::ChannelInterface> channel,
const grpc::string& method, const grpc::string& request,
grpc::string* response, const MetadataContainer& metadata,
MetadataContainer* server_initial_metadata,
MetadataContainer* server_trailing_metadata);
};
} // namespace testing

@ -60,6 +60,14 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
public:
Status Echo(ServerContext* context, const EchoRequest* request,
EchoResponse* response) GRPC_OVERRIDE {
if (!context->client_metadata().empty()) {
for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
context->client_metadata().begin();
iter != context->client_metadata().end(); ++iter) {
context->AddInitialMetadata(iter->first, iter->second);
}
}
context->AddTrailingMetadata("trailing_key", "trailing_value");
response->set_message(request->message());
return Status::OK;
}
@ -106,6 +114,7 @@ TEST_F(CliCallTest, SimpleRpc) {
request.set_message("Hello");
ClientContext context;
context.AddMetadata("key1", "val1");
Status s = stub_->Echo(&context, request, &response);
EXPECT_EQ(response.message(), request.message());
EXPECT_TRUE(s.ok());
@ -114,8 +123,17 @@ TEST_F(CliCallTest, SimpleRpc) {
grpc::string request_bin, response_bin, expected_response_bin;
EXPECT_TRUE(request.SerializeToString(&request_bin));
EXPECT_TRUE(response.SerializeToString(&expected_response_bin));
CliCall::Call(channel_, kMethod, request_bin, &response_bin);
std::multimap<grpc::string, grpc::string> client_metadata,
server_initial_metadata, server_trailing_metadata;
client_metadata.insert(std::pair<grpc::string, grpc::string>("key1", "val1"));
Status s2 = CliCall::Call(channel_, kMethod, request_bin, &response_bin,
client_metadata, &server_initial_metadata,
&server_trailing_metadata);
EXPECT_TRUE(s2.ok());
EXPECT_EQ(expected_response_bin, response_bin);
EXPECT_EQ(context.GetServerInitialMetadata(), server_initial_metadata);
EXPECT_EQ(context.GetServerTrailingMetadata(), server_trailing_metadata);
}
} // namespace testing

@ -41,8 +41,8 @@
body: "hello world"
}
b. under grpc/ run
protoc --proto_path=test/cpp/interop/ \
--encode=grpc.testing.SimpleRequest test/cpp/interop/messages.proto \
protoc --proto_path=test/proto/ \
--encode=grpc.testing.SimpleRequest test/proto/messages.proto \
< input.txt > input.bin
2. Start a server
make interop_server && bins/opt/interop_server --port=50051
@ -51,10 +51,12 @@
/grpc.testing.TestService/UnaryCall --enable_ssl=false \
--input_binary_file=input.bin --output_binary_file=output.bin
4. Decode response
protoc --proto_path=test/cpp/interop/ \
--decode=grpc.testing.SimpleResponse test/cpp/interop/messages.proto \
protoc --proto_path=test/proto/ \
--decode=grpc.testing.SimpleResponse test/proto/messages.proto \
< output.bin > output.txt
5. Now the text form of response should be in output.txt
Optionally, metadata can be passed to server via flag --metadata, e.g.
--metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
*/
#include <fstream>
@ -77,6 +79,44 @@ DEFINE_string(input_binary_file, "",
"Path to input file containing serialized request.");
DEFINE_string(output_binary_file, "output.bin",
"Path to output file to write serialized response.");
DEFINE_string(metadata, "",
"Metadata to send to server, in the form of key1:val1:key2:val2");
void ParseMetadataFlag(
std::multimap<grpc::string, grpc::string>* client_metadata) {
if (FLAGS_metadata.empty()) {
return;
}
std::vector<grpc::string> fields;
grpc::string delim(":");
size_t cur, next = -1;
do {
cur = next + 1;
next = FLAGS_metadata.find_first_of(delim, cur);
fields.push_back(FLAGS_metadata.substr(cur, next - cur));
} while (next != grpc::string::npos);
if (fields.size() % 2) {
std::cout << "Failed to parse metadata flag" << std::endl;
exit(1);
}
for (size_t i = 0; i < fields.size(); i += 2) {
client_metadata->insert(
std::pair<grpc::string, grpc::string>(fields[i], fields[i + 1]));
}
}
void PrintMetadata(const std::multimap<grpc::string, grpc::string>& m,
const grpc::string& message) {
if (m.empty()) {
return;
}
std::cout << message << std::endl;
for (std::multimap<grpc::string, grpc::string>::const_iterator iter =
m.begin();
iter != m.end(); ++iter) {
std::cout << iter->first << " : " << iter->second << std::endl;
}
}
int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
@ -118,11 +158,27 @@ int main(int argc, char** argv) {
grpc::CreateChannel(server_address, creds, grpc::ChannelArguments());
grpc::string response;
grpc::testing::CliCall::Call(channel, method, input_stream.str(), &response);
if (!response.empty()) {
std::ofstream output_file(FLAGS_output_binary_file,
std::ios::trunc | std::ios::binary);
output_file << response;
std::multimap<grpc::string, grpc::string> client_metadata,
server_initial_metadata, server_trailing_metadata;
ParseMetadataFlag(&client_metadata);
PrintMetadata(client_metadata, "Sending client initial metadata:");
grpc::Status s = grpc::testing::CliCall::Call(
channel, method, input_stream.str(), &response, client_metadata,
&server_initial_metadata, &server_trailing_metadata);
PrintMetadata(server_initial_metadata,
"Received initial metadata from server:");
PrintMetadata(server_trailing_metadata,
"Received trailing metadata from server:");
if (s.ok()) {
std::cout << "Rpc succeeded with OK status" << std::endl;
if (!response.empty()) {
std::ofstream output_file(FLAGS_output_binary_file,
std::ios::trunc | std::ios::binary);
output_file << response;
}
} else {
std::cout << "Rpc failed with status code " << s.error_code()
<< " error message " << s.error_message() << std::endl;
}
return 0;

Loading…
Cancel
Save