Add error handling to a few error conditions

This commit is contained in:
Stanley Cheung 2020-07-16 23:29:47 -07:00 committed by Stanley Cheung
parent e994bb108b
commit 5276b1e36d
3 changed files with 120 additions and 5 deletions

View File

@ -300,8 +300,15 @@ class GrpcWebClientBase {
stream.on('end', function() {
if (!errorEmitted) {
if (responseReceived == null) {
callback({
code: StatusCode.UNKNOWN,
message: 'Incomplete response',
});
} else {
callback(null, responseReceived);
}
}
if (useUnaryResponse) {
callback(null, null); // trigger unaryResponse
}

View File

@ -158,17 +158,34 @@ class GrpcWebClientReadableStream {
});
return;
}
var messages = self.parser_.parse(byteSource);
var messages = null;
try {
messages = self.parser_.parse(byteSource);
} catch (err) {
self.handleError_({
code: StatusCode.UNKNOWN,
message: 'Error in parsing response body',
metadata: {},
});
}
if (messages) {
var FrameType = GrpcWebStreamParser.FrameType;
for (var i = 0; i < messages.length; i++) {
if (FrameType.DATA in messages[i]) {
var data = messages[i][FrameType.DATA];
if (data) {
try {
var response = self.responseDeserializeFn_(data);
if (response) {
self.sendDataCallbacks_(response);
}
} catch (err) {
self.handleError_({
code: StatusCode.UNKNOWN,
message: 'Error in response deserializer function.',
metadata: {},
});
}
}
}
if (FrameType.TRAILER in messages[i]) {

View File

@ -328,6 +328,97 @@ describe('grpc-web generated code (commonjs+grpcwebtext)', function() {
});
});
it('should error out on incomplete response', function(done) {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
const {EchoRequest} = require(protoGenCodePath);
var echoService = new EchoServiceClient('MyHostname', null, null);
var request = new EchoRequest();
MockXMLHttpRequest.onSend = function(xhr) {
xhr.respond(200, {'Content-Type': 'application/grpc-web-text'},
// An incomplete response. The frame length indicates
// 26 bytes, but the rest of the frame only contains
// 18 bytes.
'AAAAABoKCwgBEgdGaWN0aW9uCgsIAhI');
};
var call = echoService.echo(
request, {}, function(err, response) {
if (response) {
assert.fail('should not receive response');
}
assert.equal(2, err.code);
assert.equal(true, err.message.toLowerCase().includes(
'incomplete response'));
done();
});
call.on('data', (response) => {
assert.fail('should not receive response this way');
});
call.on('error', (error) => {
assert.fail('should not receive error this way');
});
});
it('should error out on invalid proto response', function(done) {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
const {EchoRequest} = require(protoGenCodePath);
var echoService = new EchoServiceClient('MyHostname', null, null);
var request = new EchoRequest();
MockXMLHttpRequest.onSend = function(xhr) {
xhr.respond(200, {'Content-Type': 'application/grpc-web-text'},
// A valid grpc-web frame, but contains an invalid
// protobuf payload.
'AAAAAAUKCgoKCg==');
};
var call = echoService.echo(
request, {}, function(err, response) {
if (response) {
assert.fail('should not receive response');
}
assert.equal(2, err.code);
assert.equal(true, err.message.toLowerCase().includes('deserialize'));
assert.equal(true, err.message.toLowerCase().includes('error'));
done();
});
call.on('data', (response) => {
assert.fail('should not receive response this way');
});
call.on('error', (error) => {
assert.fail('should not receive error this way');
});
});
it('should error out on invalid response body', function(done) {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
const {EchoRequest} = require(protoGenCodePath);
var echoService = new EchoServiceClient('MyHostname', null, null);
var request = new EchoRequest();
MockXMLHttpRequest.onSend = function(xhr) {
xhr.respond(200, {'Content-Type': 'application/grpc-web-text'},
// An invalid response body. Should trip up in the
// stream parser.
'ZZZZZ');
};
var call = echoService.echo(
request, {}, function(err, response) {
if (response) {
assert.fail('should not receive response');
}
assert.equal(2, err.code);
assert.equal(true, err.message.toLowerCase().includes(
'error in parsing response body'));
done();
});
call.on('data', (response) => {
assert.fail('should not receive response this way');
});
call.on('error', (error) => {
assert.fail('should not receive error this way');
});
});
it('should not receive response on non-ok status', function(done) {
done = multiDone(done, 2);
execSync(genCodeCmd);