diff options
author | 2015-08-12 20:19:20 -0700 | |
---|---|---|
committer | 2015-08-12 20:34:39 -0700 | |
commit | 0b34c89bc6f72b3cfd46c1b63840849e1df2511d (patch) | |
tree | 8c3fca2e6b44dcae83bec6d3623ebe8eee87931b /src/objective-c | |
parent | 25884b305c4b3400cd8deb6e0708c12f0f898477 (diff) |
Turn allResponseMetadata into *Headers and *Trailers
Diffstat (limited to 'src/objective-c')
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall+OAuth2.m | 2 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall.h | 21 | ||||
-rw-r--r-- | src/objective-c/GRPCClient/GRPCCall.m | 33 |
3 files changed, 33 insertions, 23 deletions
diff --git a/src/objective-c/GRPCClient/GRPCCall+OAuth2.m b/src/objective-c/GRPCClient/GRPCCall+OAuth2.m index 7f4fbacbe3..83b0de18e3 100644 --- a/src/objective-c/GRPCClient/GRPCCall+OAuth2.m +++ b/src/objective-c/GRPCClient/GRPCCall+OAuth2.m @@ -57,7 +57,7 @@ static NSString * const kChallengeHeader = @"www-authenticate"; } - (NSString *)oauth2ChallengeHeader { - return self.allResponseMetadata[kChallengeHeader]; + return self.responseHeaders[kChallengeHeader]; } @end diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 83a3ce5127..ffa133cee4 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -71,14 +71,21 @@ extern id const kGRPCStatusMetadataKey; - (NSMutableDictionary *)requestHeaders; // nonatomic - (void)setRequestHeaders:(NSDictionary *)requestHeaders; // nonatomic, copy -// This dictionary is populated with the HTTP headers received from the server. When the RPC ends, -// the HTTP trailers received are added to the dictionary too. It has the same structure as the -// request metadata dictionary. +// This dictionary is populated with the HTTP headers received from the server. This happens before +// any response message is received from the server. It has the same structure as the request +// headers dictionary: Keys are NSString header names; names ending with the suffix "-bin" have a +// NSData value; the others have a NSString value. // -// The first time this object calls |writeValue| on the writeable passed to |startWithWriteable|, -// the |responseMetadata| dictionary already contains the response headers. When it calls -// |writesFinishedWithError|, the dictionary contains both the response headers and trailers. -@property(atomic, readonly) NSDictionary *allResponseMetadata; +// The value of this property is nil until all response headers are received, and will change before +// any of -writeValue: or -writesFinishedWithError: are sent to the writeable. +@property(atomic, readonly) NSDictionary *responseHeaders; + +// Same as responseHeaders, but populated with the HTTP trailers received from the server before the +// call finishes. +// +// The value of this property is nil until all response trailers are received, and will change +// before -writesFinishedWithError: is sent to the writeable. +@property(atomic, readonly) NSDictionary *responseTrailers; // The request writer has to write NSData objects into the provided Writeable. The server will // receive each of those separately and in order as distinct messages. diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 0e5204d009..326def7f39 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -45,6 +45,9 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey"; @interface GRPCCall () <GRXWriteable> +// Make them read-write. +@property(atomic, strong) NSDictionary *responseHeaders; +@property(atomic, strong) NSDictionary *responseTrailers; @end // The following methods of a C gRPC call object aren't reentrant, and thus @@ -90,7 +93,6 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey"; GRPCCall *_retainSelf; NSMutableDictionary *_requestHeaders; - NSMutableDictionary *_allResponseMetadata; } @synthesize state = _state; @@ -122,7 +124,6 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey"; _requestWriter = requestWriter; _requestHeaders = [NSMutableDictionary dictionary]; - _allResponseMetadata = [NSMutableDictionary dictionary]; } return self; } @@ -137,10 +138,6 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey"; _requestHeaders = [NSMutableDictionary dictionaryWithDictionary:requestHeaders]; } -- (NSDictionary *)allResponseMetadata { - return _allResponseMetadata; -} - #pragma mark Finish - (void)finishWithError:(NSError *)errorOrNil { @@ -304,35 +301,41 @@ NSString * const kGRPCStatusMetadataKey = @"io.grpc.StatusMetadataKey"; // Both handlers will eventually be called, from the network queue. Writes can start immediately // after this. -// The first one (metadataHandler), when the response headers are received. +// The first one (headersHandler), when the response headers are received. // The second one (completionHandler), whenever the RPC finishes for any reason. -- (void)invokeCallWithMetadataHandler:(void(^)(NSDictionary *))metadataHandler +- (void)invokeCallWithHeadersHandler:(void(^)(NSDictionary *))headersHandler completionHandler:(void(^)(NSError *, NSDictionary *))completionHandler { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvMetadata alloc] - initWithHandler:metadataHandler]]]; + initWithHandler:headersHandler]]]; [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvStatus alloc] initWithHandler:completionHandler]]]; } - (void)invokeCall { __weak GRPCCall *weakSelf = self; - [self invokeCallWithMetadataHandler:^(NSDictionary *headers) { + [self invokeCallWithHeadersHandler:^(NSDictionary *headers) { // Response headers received. GRPCCall *strongSelf = weakSelf; if (strongSelf) { - [strongSelf->_allResponseMetadata addEntriesFromDictionary:headers]; + strongSelf.responseHeaders = headers; [strongSelf startNextRead]; } } completionHandler:^(NSError *error, NSDictionary *trailers) { GRPCCall *strongSelf = weakSelf; if (strongSelf) { - [strongSelf->_allResponseMetadata addEntriesFromDictionary:trailers]; + strongSelf.responseTrailers = trailers; if (error) { - NSMutableDictionary *userInfo = - [NSMutableDictionary dictionaryWithDictionary:error.userInfo]; - userInfo[kGRPCStatusMetadataKey] = strongSelf->_allResponseMetadata; + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (error.userInfo) { + [userInfo addEntriesFromDictionary:error.userInfo]; + } + userInfo[kGRPCStatusMetadataKey] = strongSelf.responseTrailers; + // TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be + // called before this one, so an error might end up with trailers but no headers. We + // shouldn't call finishWithError until ater both blocks are called. It is when this is done + // that we can provide a merged view of response headers and trailers in a thread-safe way. error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo]; } [strongSelf finishWithError:error]; |