mirror of https://github.com/grpc/grpc-web.git
parent
a66fc4b697
commit
d271ba0a0a
|
@ -1,43 +1,24 @@
|
|||
goog.provide('grpc.web.ClientBaseTest');
|
||||
goog.setTestOnly('grpc.web.ClientBaseTest');
|
||||
goog.provide('grpc.web.GatewayClientBaseTest');
|
||||
goog.setTestOnly('grpc.web.GatewayClientBaseTest');
|
||||
|
||||
goog.require('goog.net.streams.NodeReadableStream');
|
||||
goog.require('goog.net.streams.XhrNodeReadableStream');
|
||||
goog.require('goog.structs.Map');
|
||||
goog.require('goog.testing.PropertyReplacer');
|
||||
goog.require('goog.testing.asserts');
|
||||
goog.require('goog.testing.jsunit');
|
||||
goog.require('grpc.web.AbstractClientBase');
|
||||
goog.require('grpc.web.ClientReadableStream');
|
||||
goog.require('grpc.web.GatewayClientBase');
|
||||
|
||||
|
||||
var client;
|
||||
var callback;
|
||||
var xhr;
|
||||
var xhrReader;
|
||||
var xhrStream;
|
||||
var request;
|
||||
var response;
|
||||
var propertyReplacer;
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object} The NodeReadableStream EventType mapping
|
||||
*/
|
||||
var EventType = goog.net.streams.NodeReadableStream.EventType;
|
||||
var dataCallback;
|
||||
|
||||
|
||||
function setUp() {
|
||||
xhrReader = getMockXhrStreamReaderInstance();
|
||||
xhrStream = getMockXhrNodeReadableStreamInstance(xhrReader);
|
||||
|
||||
propertyReplacer = new goog.testing.PropertyReplacer();
|
||||
propertyReplacer.replace(goog.net.streams,
|
||||
'createXhrNodeReadableStream',
|
||||
function (xhr) {
|
||||
return xhrStream;
|
||||
});
|
||||
propertyReplacer.replace(
|
||||
goog.net.streams, 'createXhrNodeReadableStream',
|
||||
function(xhr) {
|
||||
return new MockXhrNodeReadableStream();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,404 +27,225 @@ function tearDown() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a duck-type XhrStreamReader to simulate xhr events.
|
||||
* @constructor
|
||||
* @struct
|
||||
* @final
|
||||
*/
|
||||
function MockXhrStreamReader() {
|
||||
|
||||
// mocked API
|
||||
|
||||
this.setStatusHandler = function(handler) {
|
||||
this.statusHandler_ = handler;
|
||||
};
|
||||
|
||||
this.setDataHandler = function(handler) {
|
||||
this.dataHandler_ = handler;
|
||||
};
|
||||
|
||||
this.getStatus = function() {
|
||||
return this.status_;
|
||||
};
|
||||
|
||||
// simulated events
|
||||
|
||||
this.onData = function(messages) {
|
||||
this.dataHandler_(messages);
|
||||
};
|
||||
|
||||
this.onStatus = function(status) {
|
||||
this.status_ = status;
|
||||
this.statusHandler_();
|
||||
};
|
||||
}
|
||||
// { code: 3, message: 'TestErrorMsg' }
|
||||
var RPC_STATUS_BYTES =
|
||||
[8, 3, 18, 12, 84, 101, 115, 116, 69, 114, 114, 111, 114, 77, 115, 103];
|
||||
var REQUEST_BYTES = [1,2,3];
|
||||
var FAKE_METHOD = "fake-method";
|
||||
var DATA_BYTES = "woof";
|
||||
var PROTO_FIELD_VALUE = "meow";
|
||||
var EXPECTED_HEADERS = [
|
||||
"Content-Type",
|
||||
"X-Accept-Content-Transfer-Encoding",
|
||||
"X-Accept-Response-Streaming",
|
||||
];
|
||||
var EXPECTED_HEADER_VALUES = [
|
||||
"application/x-protobuf",
|
||||
"base64",
|
||||
"true",
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Construct a mock Xhr object
|
||||
* @constructor
|
||||
* @struct
|
||||
* @final
|
||||
* @param {?Object} mockValues Set of mock values
|
||||
* Mock XhrIO object to test the outgoing values
|
||||
*/
|
||||
function MockXhr() {
|
||||
|
||||
// mocked API
|
||||
|
||||
MockXhr = function(mockValues) {
|
||||
if (!('withMetadata' in mockValues)) {
|
||||
mockValues.headersCount = 3;
|
||||
mockValues.expectedHeaders = EXPECTED_HEADERS;
|
||||
mockValues.expectedHeaderValues = EXPECTED_HEADER_VALUES;
|
||||
} else {
|
||||
var expectedHeadersWithMetadata = EXPECTED_HEADERS.slice(0);
|
||||
var expectedHeaderValuesWithMetadata = EXPECTED_HEADER_VALUES.slice(0);
|
||||
expectedHeadersWithMetadata.push("header1");
|
||||
expectedHeaderValuesWithMetadata.push("value1");
|
||||
mockValues.headersCount = 4;
|
||||
mockValues.expectedHeaders = expectedHeadersWithMetadata;
|
||||
mockValues.expectedHeaderValues = expectedHeaderValuesWithMetadata;
|
||||
}
|
||||
this.mockValues = mockValues;
|
||||
this.headers = new goog.structs.Map();
|
||||
|
||||
this.isActive = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
this.send = function(url, method, content) {
|
||||
// doesn't need to do anything in test
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} url
|
||||
* @param {string=} opt_method
|
||||
* @param {string=} opt_content
|
||||
* @param {string=} opt_headers
|
||||
*/
|
||||
MockXhr.prototype.send = function(url, opt_method, opt_content, opt_headers) {
|
||||
assertEquals(FAKE_METHOD, url);
|
||||
assertEquals("POST", opt_method);
|
||||
assertElementsEquals(REQUEST_BYTES, opt_content);
|
||||
|
||||
var headerKeys = this.headers.getKeys();
|
||||
var headerValues = this.headers.getValues();
|
||||
headerKeys.sort();
|
||||
headerValues.sort();
|
||||
assertEquals(this.mockValues.headersCount, this.headers.getCount());
|
||||
assertElementsEquals(this.mockValues.expectedHeaders, headerKeys);
|
||||
assertElementsEquals(this.mockValues.expectedHeaderValues, headerValues);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Construct a mock Request proto object
|
||||
* @constructor
|
||||
* @struct
|
||||
* @final
|
||||
* Mock XHR Node Readable Stream object
|
||||
*/
|
||||
function MockRequest() {
|
||||
|
||||
// mocked API
|
||||
|
||||
this.serialize = function() {
|
||||
return [];
|
||||
};
|
||||
this.serializeBinary = function() {
|
||||
return [];
|
||||
};
|
||||
}
|
||||
MockXhrNodeReadableStream = function() {};
|
||||
|
||||
|
||||
/**
|
||||
* Construct a mock Response proto object
|
||||
* @constructor
|
||||
* @struct
|
||||
* @final
|
||||
* @param {?Array=} opt_data The array of field values passed to the
|
||||
* proto constructor
|
||||
* @param {string} eventType
|
||||
* @param {function(?)} callback
|
||||
*/
|
||||
MockReply = function(opt_data) {
|
||||
this.opt_data = opt_data;
|
||||
MockXhrNodeReadableStream.prototype.on = function(eventType, callback) {
|
||||
dataCallback = callback;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Mock deserialize method
|
||||
* @param {?string} message The string
|
||||
* @return {!jspb.Message} the response proto
|
||||
*/
|
||||
MockReply.deserialize = function(message) {
|
||||
return new MockReply([]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Mock deserializeBinary method
|
||||
* @param {?jspb.ByteSource} message The byte array
|
||||
* @return {!jspb.Message} the response proto
|
||||
*/
|
||||
MockReply.deserializeBinary = function(message) {
|
||||
return new MockReply([]);
|
||||
};
|
||||
|
||||
var methodInfo = new grpc.web.AbstractClientBase.MethodInfo(
|
||||
MockReply,
|
||||
function(req) { return req.serializeBinary(); },
|
||||
MockReply.deserializeBinary
|
||||
);
|
||||
|
||||
/**
|
||||
* Return a client instance
|
||||
*/
|
||||
function getClientInstance() {
|
||||
return new grpc.web.GatewayClientBase();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a mock Xhr instance
|
||||
*/
|
||||
function getMockXhrInstance() {
|
||||
return new MockXhr();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a mock Request instance
|
||||
*/
|
||||
function getMockRequestInstance() {
|
||||
return new MockRequest();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a mock Xhr Stream Reader instance
|
||||
*/
|
||||
function getMockXhrStreamReaderInstance() {
|
||||
return new MockXhrStreamReader();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a mock Xhr Node Readable Stream instance
|
||||
* @param {!MockXhrStreamReader} xhrReader mock xhrReader instance
|
||||
*/
|
||||
function getMockXhrNodeReadableStreamInstance(xhrReader) {
|
||||
return new goog.net.streams.XhrNodeReadableStream(xhrReader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the mock grpc web Client
|
||||
*/
|
||||
function getMockClient() {
|
||||
client = getClientInstance();
|
||||
xhr = getMockXhrInstance();
|
||||
xhrReader = getMockXhrStreamReaderInstance();
|
||||
xhrStream = getMockXhrNodeReadableStreamInstance(xhrReader);
|
||||
|
||||
// override with mock
|
||||
function testRpcResponse() {
|
||||
var client = new grpc.web.GatewayClientBase();
|
||||
client.newXhr_ = function() {
|
||||
return xhr;
|
||||
return new MockXhr({});
|
||||
};
|
||||
|
||||
// override with mock
|
||||
client.createClientReadableStream_ = function(x, c) {
|
||||
return new grpc.web.ClientReadableStream(xhr,
|
||||
MockReply.deserializeBinary);
|
||||
};
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
function testConstructor() {
|
||||
client = getClientInstance();
|
||||
assertTrue(client instanceof grpc.web.GatewayClientBase);
|
||||
}
|
||||
|
||||
function testBasicRpcCall() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
|
||||
var delivered = false;
|
||||
|
||||
callback = function(err, r) {
|
||||
delivered = true;
|
||||
response = r;
|
||||
};
|
||||
|
||||
client.rpcCall('testMethod', request, {},
|
||||
methodInfo, callback);
|
||||
|
||||
// callback should not have been invoked at this point
|
||||
assertFalse(delivered);
|
||||
}
|
||||
|
||||
function testSetHeaders() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
var metadata = {
|
||||
'header1': 'value 1',
|
||||
'header2': 'value 2',
|
||||
};
|
||||
|
||||
var delivered = false;
|
||||
|
||||
callback = function(err, r) {
|
||||
delivered = true;
|
||||
response = r;
|
||||
};
|
||||
|
||||
client.rpcCall('testMethod', request, metadata,
|
||||
methodInfo, callback);
|
||||
|
||||
// callback should not have been invoked at this point
|
||||
assertFalse(delivered);
|
||||
// Verify that headers were set on mock XhrIo.
|
||||
assertElementsEquals([
|
||||
'value 1',
|
||||
'value 2',
|
||||
'application/x-protobuf',
|
||||
'base64',
|
||||
'true',
|
||||
], xhr.headers.getValues());
|
||||
}
|
||||
|
||||
function testRpcCallCallback() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
|
||||
var delivered = false;
|
||||
|
||||
callback = function(err, r) {
|
||||
delivered = true;
|
||||
response = r;
|
||||
};
|
||||
|
||||
client.rpcCall('testMethod', request, {},
|
||||
methodInfo, callback);
|
||||
|
||||
// simulate server sending a response for this rpc call
|
||||
xhrReader.onData([{'1':'a'}]);
|
||||
|
||||
// verify the callback is called
|
||||
assertTrue(delivered);
|
||||
|
||||
// make sure the callback is called with the response proto
|
||||
// already deserialized
|
||||
assertTrue(response instanceof MockReply);
|
||||
client.rpcCall(FAKE_METHOD, {}, {}, {
|
||||
requestSerializeFn : function(request) {
|
||||
return REQUEST_BYTES;
|
||||
},
|
||||
responseDeserializeFn : function(bytes) {
|
||||
assertEquals(DATA_BYTES, bytes);
|
||||
return {"field1": PROTO_FIELD_VALUE};
|
||||
}
|
||||
}, function(error, response) {
|
||||
assertNull(error);
|
||||
assertEquals(PROTO_FIELD_VALUE, response.field1);
|
||||
});
|
||||
dataCallback({"1": DATA_BYTES});
|
||||
}
|
||||
|
||||
|
||||
function testRpcCallResponse() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
|
||||
var delivered = false;
|
||||
|
||||
callback = function(err, r) {
|
||||
delivered = true;
|
||||
response = r;
|
||||
function testRpcError() {
|
||||
var client = new grpc.web.GatewayClientBase();
|
||||
client.newXhr_ = function() {
|
||||
return new MockXhr({});
|
||||
};
|
||||
|
||||
client.rpcCall('testMethod', request, {},
|
||||
methodInfo, callback);
|
||||
|
||||
xhrReader.onData([{'1': 'v1'}]);
|
||||
|
||||
assertTrue(delivered);
|
||||
assertTrue(response instanceof MockReply);
|
||||
client.rpcCall(FAKE_METHOD, {}, {}, {
|
||||
requestSerializeFn : function(request) {
|
||||
return REQUEST_BYTES;
|
||||
},
|
||||
responseDeserializeFn : function(bytes) {
|
||||
return {};
|
||||
}
|
||||
}, function(error, response) {
|
||||
assertNull(response);
|
||||
assertEquals(3, error.code);
|
||||
assertEquals("TestErrorMsg", error.message);
|
||||
});
|
||||
dataCallback({"2": RPC_STATUS_BYTES});
|
||||
}
|
||||
|
||||
|
||||
function testBasicServerStreaming() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
|
||||
var delivered = 0;
|
||||
|
||||
var call = client.serverStreaming('testMethod', request, {},
|
||||
methodInfo);
|
||||
|
||||
assertTrue(call instanceof grpc.web.ClientReadableStream);
|
||||
|
||||
// no callback has been attached yet
|
||||
assertEquals(0, delivered);
|
||||
}
|
||||
|
||||
|
||||
function testServerStreamingAddOnDataCallback() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
|
||||
var delivered = 0;
|
||||
|
||||
callback = function(r) {
|
||||
delivered++;
|
||||
response = r;
|
||||
function testRpcMetadata() {
|
||||
var client = new grpc.web.GatewayClientBase();
|
||||
client.newXhr_ = function() {
|
||||
return new MockXhr({
|
||||
withMetadata: true,
|
||||
});
|
||||
};
|
||||
|
||||
var call = client.serverStreaming('testMethod', request, {},
|
||||
methodInfo);
|
||||
|
||||
assertTrue(call instanceof grpc.web.ClientReadableStream);
|
||||
assertEquals(0, delivered);
|
||||
|
||||
call.on(EventType.DATA, callback);
|
||||
|
||||
// callback should still not have been called at this point
|
||||
assertEquals(0, delivered);
|
||||
client.rpcCall(FAKE_METHOD, {}, {"header1":"value1"}, {
|
||||
requestSerializeFn : function(request) {
|
||||
return REQUEST_BYTES;
|
||||
},
|
||||
responseDeserializeFn : function(bytes) {
|
||||
assertEquals(DATA_BYTES, bytes);
|
||||
return {"field1": PROTO_FIELD_VALUE};
|
||||
}
|
||||
}, function(error, response) {
|
||||
assertNull(error);
|
||||
assertEquals(PROTO_FIELD_VALUE, response.field1);
|
||||
});
|
||||
dataCallback({"1": DATA_BYTES});
|
||||
}
|
||||
|
||||
|
||||
function testServerStreamingCallback() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
|
||||
var delivered = 0;
|
||||
|
||||
callback = function(r) {
|
||||
delivered++;
|
||||
response = r;
|
||||
function testStreamingResponse() {
|
||||
var client = new grpc.web.GatewayClientBase();
|
||||
var numCalled = 0;
|
||||
client.newXhr_ = function() {
|
||||
return new MockXhr({});
|
||||
};
|
||||
|
||||
var call = client.serverStreaming('testMethod', request, {},
|
||||
methodInfo);
|
||||
|
||||
assertTrue(call instanceof grpc.web.ClientReadableStream);
|
||||
assertEquals(0, delivered);
|
||||
|
||||
call.on(EventType.DATA, callback);
|
||||
|
||||
// simulate server streaming 1 message
|
||||
xhrReader.onData([{'1': 'v'}]);
|
||||
|
||||
// verify the callback is called
|
||||
assertEquals(1, delivered);
|
||||
|
||||
// make sure the callback is called with the response proto
|
||||
// already deserialized
|
||||
assertTrue(response instanceof MockReply);
|
||||
var stream = client.serverStreaming(FAKE_METHOD, {}, {}, {
|
||||
requestSerializeFn : function(request) {
|
||||
return REQUEST_BYTES;
|
||||
},
|
||||
responseDeserializeFn : function(bytes) {
|
||||
assertEquals(DATA_BYTES, bytes);
|
||||
return {"field1": PROTO_FIELD_VALUE};
|
||||
}
|
||||
});
|
||||
stream.on('data', function(response) {
|
||||
numCalled++;
|
||||
assertEquals(PROTO_FIELD_VALUE, response.field1);
|
||||
});
|
||||
assertEquals(0, numCalled);
|
||||
dataCallback({"1": DATA_BYTES});
|
||||
dataCallback({"1": DATA_BYTES});
|
||||
assertEquals(2, numCalled);
|
||||
}
|
||||
|
||||
|
||||
function testServerStreamingResponse() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
|
||||
var delivered = 0;
|
||||
|
||||
callback = function(r) {
|
||||
delivered++;
|
||||
response = r;
|
||||
function testStreamingError() {
|
||||
var client = new grpc.web.GatewayClientBase();
|
||||
var numCalled = 0;
|
||||
client.newXhr_ = function() {
|
||||
return new MockXhr({});
|
||||
};
|
||||
|
||||
var call = client.serverStreaming('testMethod', request, {},
|
||||
methodInfo);
|
||||
|
||||
assertTrue(call instanceof grpc.web.ClientReadableStream);
|
||||
assertEquals(0, delivered);
|
||||
|
||||
call.on(EventType.DATA, callback);
|
||||
|
||||
xhrReader.onData([{'1': 'v1'}]);
|
||||
|
||||
assertEquals(1, delivered);
|
||||
assertTrue(response instanceof MockReply);
|
||||
var stream = client.serverStreaming(FAKE_METHOD, {}, {}, {
|
||||
requestSerializeFn : function(request) {
|
||||
return REQUEST_BYTES;
|
||||
},
|
||||
responseDeserializeFn : function(bytes) {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
stream.on('data', function(response) {
|
||||
numCalled++;
|
||||
});
|
||||
stream.on('status', function(status) {
|
||||
assertEquals(3, status.code);
|
||||
assertEquals("TestErrorMsg", status.details);
|
||||
});
|
||||
dataCallback({"2": RPC_STATUS_BYTES});
|
||||
assertEquals(0, numCalled);
|
||||
}
|
||||
|
||||
|
||||
function testServerStreamingResponseMultipleMessages() {
|
||||
client = getMockClient();
|
||||
request = getMockRequestInstance();
|
||||
|
||||
var delivered = 0;
|
||||
|
||||
callback = function(r) {
|
||||
delivered++;
|
||||
response = r;
|
||||
function testStreamingMetadata() {
|
||||
var client = new grpc.web.GatewayClientBase();
|
||||
var numCalled = 0;
|
||||
client.newXhr_ = function() {
|
||||
return new MockXhr({
|
||||
withMetadata: true,
|
||||
});
|
||||
};
|
||||
|
||||
var call = client.serverStreaming('testMethod', request, {},
|
||||
methodInfo);
|
||||
|
||||
assertTrue(call instanceof grpc.web.ClientReadableStream);
|
||||
assertEquals(0, delivered);
|
||||
|
||||
call.on(EventType.DATA, callback);
|
||||
|
||||
// simulate the server sending multiple messages
|
||||
xhrReader.onData([{'1': 'v1'},{'1': 'v3'}]);
|
||||
|
||||
// verify 2 messages got delivered
|
||||
assertEquals(2, delivered);
|
||||
assertTrue(response instanceof MockReply);
|
||||
var stream = client.serverStreaming(FAKE_METHOD, {}, {"header1":"value1"}, {
|
||||
requestSerializeFn : function(request) {
|
||||
return REQUEST_BYTES;
|
||||
},
|
||||
responseDeserializeFn : function(bytes) {
|
||||
assertEquals(DATA_BYTES, bytes);
|
||||
return {"field1": PROTO_FIELD_VALUE};
|
||||
}
|
||||
});
|
||||
stream.on('data', function(response) {
|
||||
numCalled++;
|
||||
assertEquals(PROTO_FIELD_VALUE, response.field1);
|
||||
});
|
||||
dataCallback({"1": DATA_BYTES});
|
||||
dataCallback({"1": DATA_BYTES});
|
||||
assertEquals(2, numCalled);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ package:
|
|||
cp compiled.js $(ROOT_DIR)/gConnector
|
||||
zip -r $(ROOT_DIR)/gConnector.zip $(ROOT_DIR)/gConnector/*
|
||||
|
||||
echo_server: echo.pb.o echo.grpc.pb.o echo_server.o
|
||||
echo_server: echo.pb.o echo.grpc.pb.o echo_server.o echo_service_impl.o
|
||||
$(CXX) $^ $(LDFLAGS) -o $@
|
||||
|
||||
echo.grpc.pb.cc: echo.proto
|
||||
|
|
|
@ -52,6 +52,10 @@ service EchoService {
|
|||
// The server returns the client message as-is.
|
||||
rpc Echo(EchoRequest) returns (EchoResponse);
|
||||
|
||||
// Sends back abort status.
|
||||
rpc EchoAbort(EchoRequest) returns (EchoResponse) {
|
||||
};
|
||||
|
||||
// One empty request, ZERO processing, followed by one empty response
|
||||
// (minimum effort to do message serialization).
|
||||
rpc NoOp(Empty) returns (Empty);
|
||||
|
@ -61,6 +65,12 @@ service EchoService {
|
|||
rpc ServerStreamingEcho(ServerStreamingEchoRequest)
|
||||
returns (stream ServerStreamingEchoResponse);
|
||||
|
||||
// One request followed by a sequence of responses (streamed download).
|
||||
// The server abort directly.
|
||||
rpc ServerStreamingEchoAbort(ServerStreamingEchoRequest)
|
||||
returns (stream ServerStreamingEchoResponse) {
|
||||
}
|
||||
|
||||
// A sequence of requests followed by one response (streamed upload).
|
||||
// The server returns the total number of messages as the result.
|
||||
rpc ClientStreamingEcho(stream ClientStreamingEchoRequest)
|
||||
|
|
|
@ -36,65 +36,10 @@
|
|||
#include <string>
|
||||
|
||||
#include "net/grpc/gateway/examples/echo/echo.grpc.pb.h"
|
||||
#include "net/grpc/gateway/examples/echo/echo_service_impl.h"
|
||||
|
||||
using grpc::Server;
|
||||
using grpc::ServerBuilder;
|
||||
using grpc::ServerContext;
|
||||
using grpc::ServerWriter;
|
||||
using grpc::Status;
|
||||
using grpc::gateway::testing::EchoRequest;
|
||||
using grpc::gateway::testing::EchoResponse;
|
||||
using grpc::gateway::testing::EchoService;
|
||||
using grpc::gateway::testing::Empty;
|
||||
using grpc::gateway::testing::ServerStreamingEchoRequest;
|
||||
using grpc::gateway::testing::ServerStreamingEchoResponse;
|
||||
|
||||
|
||||
// Logic and data behind the server's behavior.
|
||||
class EchoServiceImpl final : public EchoService::Service {
|
||||
void CopyClientMetadataToResponse(ServerContext* context) {
|
||||
for (auto& client_metadata : context->client_metadata()) {
|
||||
context->AddInitialMetadata(std::string(client_metadata.first.data(),
|
||||
client_metadata.first.length()),
|
||||
std::string(client_metadata.second.data(),
|
||||
client_metadata.second.length()));
|
||||
context->AddTrailingMetadata(
|
||||
std::string(client_metadata.first.data(),
|
||||
client_metadata.first.length()),
|
||||
std::string(client_metadata.second.data(),
|
||||
client_metadata.second.length()));
|
||||
}
|
||||
}
|
||||
|
||||
Status Echo(ServerContext* context, const EchoRequest* request,
|
||||
EchoResponse* response) override {
|
||||
CopyClientMetadataToResponse(context);
|
||||
response->set_message(request->message());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status NoOp(ServerContext* context, const Empty* request,
|
||||
Empty* response) override {
|
||||
CopyClientMetadataToResponse(context);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status ServerStreamingEcho(
|
||||
ServerContext* context, const ServerStreamingEchoRequest* request,
|
||||
ServerWriter<ServerStreamingEchoResponse>* writer) override {
|
||||
CopyClientMetadataToResponse(context);
|
||||
for (int i = 0; i < request->message_count(); i++) {
|
||||
if (context->IsCancelled()) {
|
||||
return Status::CANCELLED;
|
||||
}
|
||||
ServerStreamingEchoResponse response;
|
||||
response.set_message(request->message());
|
||||
usleep(request->message_interval() * 1000);
|
||||
writer->Write(response);
|
||||
}
|
||||
return Status::OK;
|
||||
}
|
||||
};
|
||||
|
||||
void RunServer() {
|
||||
std::string server_address("0.0.0.0:9090");
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2016, 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.
|
||||
*
|
||||
*/
|
||||
#include "net/grpc/gateway/examples/echo/echo_service_impl.h"
|
||||
|
||||
#include <grpc++/grpc++.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
|
||||
#include "net/grpc/gateway/examples/echo/echo.grpc.pb.h"
|
||||
|
||||
using grpc::ServerContext;
|
||||
using grpc::ServerWriter;
|
||||
using grpc::Status;
|
||||
using grpc::gateway::testing::EchoRequest;
|
||||
using grpc::gateway::testing::EchoResponse;
|
||||
using grpc::gateway::testing::EchoService;
|
||||
using grpc::gateway::testing::Empty;
|
||||
using grpc::gateway::testing::ServerStreamingEchoRequest;
|
||||
using grpc::gateway::testing::ServerStreamingEchoResponse;
|
||||
|
||||
|
||||
EchoServiceImpl::EchoServiceImpl() {}
|
||||
EchoServiceImpl::~EchoServiceImpl() {}
|
||||
|
||||
void EchoServiceImpl::CopyClientMetadataToResponse(ServerContext* context) {
|
||||
for (auto& client_metadata : context->client_metadata()) {
|
||||
context->AddInitialMetadata(std::string(client_metadata.first.data(),
|
||||
client_metadata.first.length()),
|
||||
std::string(client_metadata.second.data(),
|
||||
client_metadata.second.length()));
|
||||
context->AddTrailingMetadata(
|
||||
std::string(client_metadata.first.data(),
|
||||
client_metadata.first.length()),
|
||||
std::string(client_metadata.second.data(),
|
||||
client_metadata.second.length()));
|
||||
}
|
||||
}
|
||||
|
||||
Status EchoServiceImpl::Echo(ServerContext* context, const EchoRequest* request,
|
||||
EchoResponse* response) {
|
||||
CopyClientMetadataToResponse(context);
|
||||
response->set_message(request->message());
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status EchoServiceImpl::EchoAbort(ServerContext* context,
|
||||
const EchoRequest* request,
|
||||
EchoResponse* response) {
|
||||
CopyClientMetadataToResponse(context);
|
||||
response->set_message(request->message());
|
||||
return Status(grpc::StatusCode::ABORTED,
|
||||
"Aborted from server side.");
|
||||
}
|
||||
|
||||
Status EchoServiceImpl::NoOp(ServerContext* context, const Empty* request,
|
||||
Empty* response) {
|
||||
CopyClientMetadataToResponse(context);
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status EchoServiceImpl::ServerStreamingEcho(
|
||||
ServerContext* context, const ServerStreamingEchoRequest* request,
|
||||
ServerWriter<ServerStreamingEchoResponse>* writer) {
|
||||
CopyClientMetadataToResponse(context);
|
||||
for (int i = 0; i < request->message_count(); i++) {
|
||||
if (context->IsCancelled()) {
|
||||
return Status::CANCELLED;
|
||||
}
|
||||
ServerStreamingEchoResponse response;
|
||||
response.set_message(request->message());
|
||||
usleep(request->message_interval() * 1000);
|
||||
writer->Write(response);
|
||||
}
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
Status EchoServiceImpl::ServerStreamingEchoAbort(
|
||||
ServerContext* context, const ServerStreamingEchoRequest* request,
|
||||
ServerWriter<ServerStreamingEchoResponse>* writer) {
|
||||
CopyClientMetadataToResponse(context);
|
||||
ServerStreamingEchoResponse response;
|
||||
response.set_message(request->message());
|
||||
writer->Write(response);
|
||||
return Status(grpc::StatusCode::ABORTED,
|
||||
"Aborted from server side.");
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef NET_GRPC_GATEWAY_EXAMPLES_ECHO_ECHO_SERVICE_IMPL_H_
|
||||
#define NET_GRPC_GATEWAY_EXAMPLES_ECHO_ECHO_SERVICE_IMPL_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* Copyright 2016, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <grpc++/grpc++.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
|
||||
#include "net/grpc/gateway/examples/echo/echo.grpc.pb.h"
|
||||
|
||||
class EchoServiceImpl final :
|
||||
public grpc::gateway::testing::EchoService::Service {
|
||||
public:
|
||||
EchoServiceImpl();
|
||||
~EchoServiceImpl() override;
|
||||
|
||||
void CopyClientMetadataToResponse(grpc::ServerContext* context);
|
||||
grpc::Status Echo(
|
||||
grpc::ServerContext* context,
|
||||
const grpc::gateway::testing::EchoRequest* request,
|
||||
grpc::gateway::testing::EchoResponse* response) override;
|
||||
grpc::Status EchoAbort(
|
||||
grpc::ServerContext* context,
|
||||
const grpc::gateway::testing::EchoRequest* request,
|
||||
grpc::gateway::testing::EchoResponse* response) override;
|
||||
grpc::Status NoOp(
|
||||
grpc::ServerContext* context,
|
||||
const grpc::gateway::testing::Empty* request,
|
||||
grpc::gateway::testing::Empty* response) override;
|
||||
grpc::Status ServerStreamingEcho(
|
||||
grpc::ServerContext* context,
|
||||
const grpc::gateway::testing::ServerStreamingEchoRequest* request,
|
||||
grpc::ServerWriter<
|
||||
grpc::gateway::testing::ServerStreamingEchoResponse>* writer) override;
|
||||
grpc::Status ServerStreamingEchoAbort(
|
||||
grpc::ServerContext* context,
|
||||
const grpc::gateway::testing::ServerStreamingEchoRequest* request,
|
||||
grpc::ServerWriter<
|
||||
grpc::gateway::testing::ServerStreamingEchoResponse>* writer) override;
|
||||
};
|
||||
|
||||
#endif // NET_GRPC_GATEWAY_EXAMPLES_ECHO_ECHO_SERVICE_IMPL_H_
|
Loading…
Reference in New Issue