Merge pull request #3237 from jcanizales/server-error-for-bad-protos-beta

End RPC with internal error if a response proto can't be parsed. (Beta branch)
pull/3238/head
Michael Lumish 9 years ago
commit 674d623abd
  1. 33
      src/objective-c/ProtoRPC/ProtoRPC.m

@ -37,6 +37,22 @@
#import <RxLibrary/GRXWriteable.h> #import <RxLibrary/GRXWriteable.h>
#import <RxLibrary/GRXWriter+Transformations.h> #import <RxLibrary/GRXWriter+Transformations.h>
static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) {
NSDictionary *info = @{
NSLocalizedDescriptionKey: @"Unable to parse response from the server",
NSLocalizedRecoverySuggestionErrorKey: @"If this RPC is idempotent, retry "
@"with exponential backoff. Otherwise, query the server status before "
@"retrying.",
NSUnderlyingErrorKey: parsingError,
@"Expected class": expectedClass,
@"Received value": proto,
};
// TODO(jcanizales): Use kGRPCErrorDomain and GRPCErrorCodeInternal when they're public.
return [NSError errorWithDomain:@"io.grpc"
code:13
userInfo:info];
}
@implementation ProtoRPC { @implementation ProtoRPC {
id<GRXWriteable> _responseWriteable; id<GRXWriteable> _responseWriteable;
} }
@ -65,14 +81,25 @@
} }
// A writer that serializes the proto messages to send. // A writer that serializes the proto messages to send.
GRXWriter *bytesWriter = [requestsWriter map:^id(GPBMessage *proto) { GRXWriter *bytesWriter = [requestsWriter map:^id(GPBMessage *proto) {
// TODO(jcanizales): Fail with an understandable error message if the requestsWriter isn't if (![proto isKindOfClass:GPBMessage.class]) {
// sending GPBMessages. [NSException raise:NSInvalidArgumentException
format:@"Request must be a proto message: %@", proto];
}
return [proto data]; return [proto data];
}]; }];
if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) { if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) {
__weak ProtoRPC *weakSelf = self;
// A writeable that parses the proto messages received. // A writeable that parses the proto messages received.
_responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { _responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
[responsesWriteable writeValue:[responseClass parseFromData:value error:NULL]]; // TODO(jcanizales): This is done in the main thread, and needs to happen in another thread.
NSError *error = nil;
id parsed = [responseClass parseFromData:value error:&error];
if (parsed) {
[responsesWriteable writeValue:parsed];
} else {
[weakSelf finishWithError:ErrorForBadProto(value, responseClass, error)];
}
} completionHandler:^(NSError *errorOrNil) { } completionHandler:^(NSError *errorOrNil) {
[responsesWriteable writesFinishedWithError:errorOrNil]; [responsesWriteable writesFinishedWithError:errorOrNil];
}]; }];

Loading…
Cancel
Save