From 16c26ed252fa5a186db6e93248325b0f918c8625 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 26 Sep 2016 17:22:03 -0700 Subject: [PATCH 01/10] Add support of PUT method --- .../cronet/transport/cronet_transport.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index 366690acf2b..6c2b53f2917 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -531,7 +531,8 @@ static void create_grpc_frame(gpr_slice_buffer *write_slice_buffer, */ static void convert_metadata_to_cronet_headers( grpc_linked_mdelem *head, const char *host, char **pp_url, - cronet_bidirectional_stream_header **pp_headers, size_t *p_num_headers) { + cronet_bidirectional_stream_header **pp_headers, size_t *p_num_headers, + const char ** method) { grpc_linked_mdelem *curr = head; /* Walk the linked list and get number of header fields */ size_t num_headers_available = 0; @@ -558,11 +559,20 @@ static void convert_metadata_to_cronet_headers( curr = curr->next; const char *key = grpc_mdstr_as_c_string(mdelem->key); const char *value = grpc_mdstr_as_c_string(mdelem->value); - if (mdelem->key == GRPC_MDSTR_METHOD || mdelem->key == GRPC_MDSTR_SCHEME || + if (mdelem->key == GRPC_MDSTR_SCHEME || mdelem->key == GRPC_MDSTR_AUTHORITY) { /* Cronet populates these fields on its own */ continue; } + if (mdelem->key == GRPC_MDSTR_METHOD) { + if (mdelem->value == GRPC_MDSTR_PUT) { + *method = grpc_static_metadata_strings[74]; + } else { + /* POST method in default*/ + *method = grpc_static_metadata_strings[71]; + } + continue; + } if (mdelem->key == GRPC_MDSTR_PATH) { /* Create URL by appending :path value to the hostname */ gpr_asprintf(pp_url, "https://%s%s", host, value); @@ -760,14 +770,15 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, &cronet_callbacks); CRONET_LOG(GPR_DEBUG, "%p = cronet_bidirectional_stream_create()", s->cbs); char *url; + const char *method; s->header_array.headers = NULL; convert_metadata_to_cronet_headers( stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url, - &s->header_array.headers, &s->header_array.count); + &s->header_array.headers, &s->header_array.count, &method); s->header_array.capacity = s->header_array.count; CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_start(%p, %s)", s->cbs, url); - cronet_bidirectional_stream_start(s->cbs, url, 0, "POST", &s->header_array, + cronet_bidirectional_stream_start(s->cbs, url, 0, method, &s->header_array, false); stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true; result = ACTION_TAKEN_WITH_CALLBACK; From fdea83d42afbebfecfea1edf9143619640115824 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Tue, 27 Sep 2016 16:11:18 -0700 Subject: [PATCH 02/10] Update grpc objc API for support of PUT method --- src/objective-c/GRPCClient/GRPCCall.h | 7 ++++++- src/objective-c/GRPCClient/GRPCCall.m | 14 ++++++++++++-- .../GRPCClient/private/GRPCWrappedCall.h | 4 ++++ .../GRPCClient/private/GRPCWrappedCall.m | 14 ++++++++++++-- src/objective-c/ProtoRPC/ProtoRPC.h | 3 ++- src/objective-c/ProtoRPC/ProtoRPC.m | 9 ++++++--- src/objective-c/ProtoRPC/ProtoService.h | 3 ++- src/objective-c/ProtoRPC/ProtoService.m | 6 ++++-- 8 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index b9e741dfa8f..fc59e5f5e91 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -225,7 +225,12 @@ extern id const kGRPCTrailersKey; */ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path - requestsWriter:(GRXWriter *)requestsWriter NS_DESIGNATED_INITIALIZER; + requestsWriter:(GRXWriter *)requestsWriter; + +- (instancetype)initWithHost:(NSString *)host + path:(NSString *)path + requestsWriter:(GRXWriter *)requestsWriter + http2Method:(NSString *)http2Method NS_DESIGNATED_INITIALIZER; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index eecda4c03a0..6bd80c8b3fe 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -75,6 +75,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; NSString *_host; NSString *_path; + NSString *_http2Method; GRPCWrappedCall *_wrappedCall; GRPCConnectivityMonitor *_connectivityMonitor; @@ -109,13 +110,20 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; } - (instancetype)init { - return [self initWithHost:nil path:nil requestsWriter:nil]; + return [self initWithHost:nil path:nil requestsWriter:nil http2Method:nil]; +} + +- (instancetype)initWithHost:(NSString *)host + path:(NSString *)path + requestsWriter:(GRXWriter *)requestWriter{ + return [self initWithHost:host path:path requestsWriter:requestWriter http2Method:@"POST"]; } // Designated initializer - (instancetype)initWithHost:(NSString *)host path:(NSString *)path - requestsWriter:(GRXWriter *)requestWriter { + requestsWriter:(GRXWriter *)requestWriter + http2Method:(NSString *)http2Method { if (!host || !path) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } @@ -126,6 +134,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; if ((self = [super init])) { _host = [host copy]; _path = [path copy]; + _http2Method = http2Method; // Serial queue to invoke the non-reentrant methods of the grpc_call object. _callQueue = dispatch_queue_create("io.grpc.call", NULL); @@ -231,6 +240,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; - (void)sendHeaders:(NSDictionary *)headers { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers + http2Method:_http2Method handler:nil]]]; } diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index e37ed1b59fb..8b64b27e567 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -45,6 +45,10 @@ @interface GRPCOpSendMetadata : GRPCOperation - (instancetype)initWithMetadata:(NSDictionary *)metadata + handler:(void(^)())handler; + +- (instancetype)initWithMetadata:(NSDictionary *)metadata + http2Method:(NSString *)http2Method handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 13394296609..2836f99bf17 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -64,16 +64,26 @@ @implementation GRPCOpSendMetadata - (instancetype)init { - return [self initWithMetadata:nil handler:nil]; + return [self initWithMetadata:nil http2Method:nil handler:nil]; } -- (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)())handler { +- (instancetype)initWithMetadata:(NSDictionary *)metadata + handler:(void (^)())handler { + return [self initWithMetadata:metadata http2Method:@"POST" handler:handler]; +} + +- (instancetype)initWithMetadata:(NSDictionary *)metadata + http2Method:(NSString *)http2Method + handler:(void (^)())handler { if (self = [super init]) { _op.op = GRPC_OP_SEND_INITIAL_METADATA; _op.data.send_initial_metadata.count = metadata.count; _op.data.send_initial_metadata.metadata = metadata.grpc_metadataArray; _op.data.send_initial_metadata.maybe_compression_level.is_set = false; _op.data.send_initial_metadata.maybe_compression_level.level = 0; + if ([http2Method isEqualToString:@"PUT"]) { + _op.flags = GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; + } _handler = handler; } return self; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 04fc1e45f16..509a15abae8 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -47,7 +47,8 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) method:(GRPCProtoMethod *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable NS_DESIGNATED_INITIALIZER; + responsesWriteable:(id)responsesWriteable + http2Method:(NSString *)http2Method NS_DESIGNATED_INITIALIZER; - (void)start; @end diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 83d1b655e8d..67405d2a196 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -65,7 +65,8 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing #pragma clang diagnostic ignored "-Wobjc-designated-initializers" - (instancetype)initWithHost:(NSString *)host path:(NSString *)path - requestsWriter:(GRXWriter *)requestsWriter { + requestsWriter:(GRXWriter *)requestsWriter + http2Method:(NSString *)http2Method { [NSException raise:NSInvalidArgumentException format:@"Please use ProtoRPC's designated initializer instead."]; return nil; @@ -77,7 +78,8 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing method:(GRPCProtoMethod *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable { + responsesWriteable:(id)responsesWriteable + http2Method:(NSString *)http2Method { // Because we can't tell the type system to constrain the class, we need to check at runtime: if (![responseClass respondsToSelector:@selector(parseFromData:error:)]) { [NSException raise:NSInvalidArgumentException @@ -91,7 +93,8 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } return [proto data]; }]; - if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) { + if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter + http2Method:http2Method])) { __weak ProtoRPC *weakSelf = self; // A writeable that parses the proto messages received. diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 7faae1b49c9..80fab37fd55 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -47,7 +47,8 @@ __attribute__((deprecated("Please use GRPCProtoService."))) - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable; + responsesWriteable:(id)responsesWriteable + http2Method:(NSString *)http2Method; @end diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m index 3487fac59d3..fc3e0170728 100644 --- a/src/objective-c/ProtoRPC/ProtoService.m +++ b/src/objective-c/ProtoRPC/ProtoService.m @@ -68,7 +68,8 @@ - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable { + responsesWriteable:(id)responsesWriteable + http2Method:(NSString *)http2Method { GRPCProtoMethod *methodName = [[GRPCProtoMethod alloc] initWithPackage:_packageName service:_serviceName method:method]; @@ -76,7 +77,8 @@ method:methodName requestsWriter:requestsWriter responseClass:responseClass - responsesWriteable:responsesWriteable]; + responsesWriteable:responsesWriteable + http2Method:http2Method]; } @end From e97f7c0ba6c2f7c55e2ea650f52597a06bcfa6fd Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 28 Sep 2016 11:25:57 -0700 Subject: [PATCH 03/10] Allow more general flags to be passed to ObjC API --- src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 12 ++++++------ src/objective-c/GRPCClient/private/GRPCWrappedCall.h | 2 +- src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 10 ++++------ src/objective-c/ProtoRPC/ProtoRPC.h | 2 +- src/objective-c/ProtoRPC/ProtoRPC.m | 6 +++--- src/objective-c/ProtoRPC/ProtoService.h | 2 +- src/objective-c/ProtoRPC/ProtoService.m | 4 ++-- 8 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index fc59e5f5e91..9a58311fe16 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -230,7 +230,7 @@ extern id const kGRPCTrailersKey; - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestsWriter - http2Method:(NSString *)http2Method NS_DESIGNATED_INITIALIZER; + flags:(uint32_t)flags NS_DESIGNATED_INITIALIZER; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 6bd80c8b3fe..8a58db70514 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -75,7 +75,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; NSString *_host; NSString *_path; - NSString *_http2Method; + uint32_t _flags; GRPCWrappedCall *_wrappedCall; GRPCConnectivityMonitor *_connectivityMonitor; @@ -110,20 +110,20 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; } - (instancetype)init { - return [self initWithHost:nil path:nil requestsWriter:nil http2Method:nil]; + return [self initWithHost:nil path:nil requestsWriter:nil flags:0]; } - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestWriter{ - return [self initWithHost:host path:path requestsWriter:requestWriter http2Method:@"POST"]; + return [self initWithHost:host path:path requestsWriter:requestWriter flags:0]; } // Designated initializer - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestWriter - http2Method:(NSString *)http2Method { + flags:(uint32_t)flags { if (!host || !path) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } @@ -134,7 +134,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; if ((self = [super init])) { _host = [host copy]; _path = [path copy]; - _http2Method = http2Method; + _flags = flags; // Serial queue to invoke the non-reentrant methods of the grpc_call object. _callQueue = dispatch_queue_create("io.grpc.call", NULL); @@ -240,7 +240,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; - (void)sendHeaders:(NSDictionary *)headers { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers - http2Method:_http2Method + flags:_flags handler:nil]]]; } diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index 8b64b27e567..52233c82420 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -48,7 +48,7 @@ handler:(void(^)())handler; - (instancetype)initWithMetadata:(NSDictionary *)metadata - http2Method:(NSString *)http2Method + flags:(uint32_t)flags handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 2836f99bf17..627b6aa86dd 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -64,16 +64,16 @@ @implementation GRPCOpSendMetadata - (instancetype)init { - return [self initWithMetadata:nil http2Method:nil handler:nil]; + return [self initWithMetadata:nil flags:0 handler:nil]; } - (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)())handler { - return [self initWithMetadata:metadata http2Method:@"POST" handler:handler]; + return [self initWithMetadata:metadata flags:0 handler:handler]; } - (instancetype)initWithMetadata:(NSDictionary *)metadata - http2Method:(NSString *)http2Method + flags:(uint32_t)flags handler:(void (^)())handler { if (self = [super init]) { _op.op = GRPC_OP_SEND_INITIAL_METADATA; @@ -81,9 +81,7 @@ _op.data.send_initial_metadata.metadata = metadata.grpc_metadataArray; _op.data.send_initial_metadata.maybe_compression_level.is_set = false; _op.data.send_initial_metadata.maybe_compression_level.level = 0; - if ([http2Method isEqualToString:@"PUT"]) { - _op.flags = GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; - } + _op.flags = flags; _handler = handler; } return self; diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 509a15abae8..75c9b9bb3bc 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -48,7 +48,7 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable - http2Method:(NSString *)http2Method NS_DESIGNATED_INITIALIZER; + flags:(uint32_t)flags NS_DESIGNATED_INITIALIZER; - (void)start; @end diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 67405d2a196..2514d616f16 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -66,7 +66,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestsWriter - http2Method:(NSString *)http2Method { + flags:(uint32_t)flags { [NSException raise:NSInvalidArgumentException format:@"Please use ProtoRPC's designated initializer instead."]; return nil; @@ -79,7 +79,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable - http2Method:(NSString *)http2Method { + flags:(uint32_t)flags { // Because we can't tell the type system to constrain the class, we need to check at runtime: if (![responseClass respondsToSelector:@selector(parseFromData:error:)]) { [NSException raise:NSInvalidArgumentException @@ -94,7 +94,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing return [proto data]; }]; if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter - http2Method:http2Method])) { + flags:flags])) { __weak ProtoRPC *weakSelf = self; // A writeable that parses the proto messages received. diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 80fab37fd55..9a49ebd257b 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -48,7 +48,7 @@ __attribute__((deprecated("Please use GRPCProtoService."))) requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable - http2Method:(NSString *)http2Method; + flags:(uint32_t)flags; @end diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m index fc3e0170728..b237164a006 100644 --- a/src/objective-c/ProtoRPC/ProtoService.m +++ b/src/objective-c/ProtoRPC/ProtoService.m @@ -69,7 +69,7 @@ requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable - http2Method:(NSString *)http2Method { + flags:(uint32_t)flags { GRPCProtoMethod *methodName = [[GRPCProtoMethod alloc] initWithPackage:_packageName service:_serviceName method:method]; @@ -78,7 +78,7 @@ requestsWriter:requestsWriter responseClass:responseClass responsesWriteable:responsesWriteable - http2Method:http2Method]; + flags:flags]; } @end From d7aef05f24472977ee3a976d5321470132ec785c Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 28 Sep 2016 12:05:30 -0700 Subject: [PATCH 04/10] Readability improvement --- src/core/ext/transport/cronet/transport/cronet_transport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index 6c2b53f2917..6d5fe318ccb 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -566,10 +566,10 @@ static void convert_metadata_to_cronet_headers( } if (mdelem->key == GRPC_MDSTR_METHOD) { if (mdelem->value == GRPC_MDSTR_PUT) { - *method = grpc_static_metadata_strings[74]; + *method = (const char*)mdelem->value->slice.data.refcounted.bytes; } else { /* POST method in default*/ - *method = grpc_static_metadata_strings[71]; + *method = (const char*)(GRPC_MDSTR_POST->slice.data.refcounted.bytes); } continue; } From 9deb09fa36c80e3b3235365aa707e6d8575296b0 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Wed, 28 Sep 2016 16:03:04 -0700 Subject: [PATCH 05/10] Use NS_OPTIONS flags for ObjC API --- src/objective-c/GRPCClient/GRPCCall.h | 15 ++++++++++++++- src/objective-c/GRPCClient/GRPCCall.m | 4 ++-- src/objective-c/ProtoRPC/ProtoRPC.h | 2 +- src/objective-c/ProtoRPC/ProtoRPC.m | 4 ++-- src/objective-c/ProtoRPC/ProtoService.h | 3 ++- src/objective-c/ProtoRPC/ProtoService.m | 2 +- 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 9a58311fe16..1bf25e290d9 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -154,6 +154,19 @@ typedef NS_ENUM(NSUInteger, GRPCErrorCode) { GRPCErrorCodeDataLoss = 15, }; +/** + * Flags for options of a gRPC call + * + */ +typedef NS_OPTIONS(NSUInteger, GRPCCallFlags) { + /** Signal that the call is idempotent */ + GRPCFlagIdempotentRequest = 0x00000010, + /** Signal that the call should not return UNAVAILABLE before it has started */ + GRPCFlagIgnoreConnectivity = 0x00000020, + /** Signal that the call is cacheable. GRPC is free to use GET verb */ + GRPCFlagCacheableRequest = 0x00000040, +}; + /** * Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by * the server. @@ -230,7 +243,7 @@ extern id const kGRPCTrailersKey; - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestsWriter - flags:(uint32_t)flags NS_DESIGNATED_INITIALIZER; + flags:(GRPCCallFlags)flags NS_DESIGNATED_INITIALIZER; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 8a58db70514..eb7998ed975 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -75,7 +75,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; NSString *_host; NSString *_path; - uint32_t _flags; + GRPCCallFlags _flags; GRPCWrappedCall *_wrappedCall; GRPCConnectivityMonitor *_connectivityMonitor; @@ -123,7 +123,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestWriter - flags:(uint32_t)flags { + flags:(GRPCCallFlags)flags { if (!host || !path) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index 75c9b9bb3bc..b2c3e8def32 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -48,7 +48,7 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable - flags:(uint32_t)flags NS_DESIGNATED_INITIALIZER; + flags:(GRPCCallFlags)flags NS_DESIGNATED_INITIALIZER; - (void)start; @end diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 2514d616f16..16cb04a83bf 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -66,7 +66,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing - (instancetype)initWithHost:(NSString *)host path:(NSString *)path requestsWriter:(GRXWriter *)requestsWriter - flags:(uint32_t)flags { + flags:(GRPCCallFlags)flags { [NSException raise:NSInvalidArgumentException format:@"Please use ProtoRPC's designated initializer instead."]; return nil; @@ -79,7 +79,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable - flags:(uint32_t)flags { + flags:(GRPCCallFlags)flags { // Because we can't tell the type system to constrain the class, we need to check at runtime: if (![responseClass respondsToSelector:@selector(parseFromData:error:)]) { [NSException raise:NSInvalidArgumentException diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 9a49ebd257b..0fd5764dbc0 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -32,6 +32,7 @@ */ #import +#import "ProtoRPC.h" @class GRPCProtoCall; @protocol GRXWriteable; @@ -48,7 +49,7 @@ __attribute__((deprecated("Please use GRPCProtoService."))) requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable - flags:(uint32_t)flags; + flags:(GRPCCallFlags)flags; @end diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m index b237164a006..53337cd983e 100644 --- a/src/objective-c/ProtoRPC/ProtoService.m +++ b/src/objective-c/ProtoRPC/ProtoService.m @@ -69,7 +69,7 @@ requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass responsesWriteable:(id)responsesWriteable - flags:(uint32_t)flags { + flags:(GRPCCallFlags)flags { GRPCProtoMethod *methodName = [[GRPCProtoMethod alloc] initWithPackage:_packageName service:_serviceName method:method]; From 22f7973179b42e36ba46105fc11fa19d25fd9d07 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 30 Sep 2016 14:24:56 -0700 Subject: [PATCH 06/10] ObjC API update --- src/objective-c/GRPCClient/GRPCCall.h | 24 ++++++++------- src/objective-c/GRPCClient/GRPCCall.m | 41 ++++++++++++++++++------- src/objective-c/ProtoRPC/ProtoRPC.h | 3 +- src/objective-c/ProtoRPC/ProtoRPC.m | 9 ++---- src/objective-c/ProtoRPC/ProtoService.h | 3 +- src/objective-c/ProtoRPC/ProtoService.m | 6 ++-- 6 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 1bf25e290d9..4b28cade42e 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -158,13 +158,12 @@ typedef NS_ENUM(NSUInteger, GRPCErrorCode) { * Flags for options of a gRPC call * */ -typedef NS_OPTIONS(NSUInteger, GRPCCallFlags) { +typedef NS_ENUM(NSUInteger, GRPCCallAttr) { + GRPCCallAttrDefault = 0, /** Signal that the call is idempotent */ - GRPCFlagIdempotentRequest = 0x00000010, - /** Signal that the call should not return UNAVAILABLE before it has started */ - GRPCFlagIgnoreConnectivity = 0x00000020, + GRPCCallAttrIdempotentRequest = 1, /** Signal that the call is cacheable. GRPC is free to use GET verb */ - GRPCFlagCacheableRequest = 0x00000040, + GRPCCallAttrCacheableRequest = 2, }; /** @@ -238,12 +237,7 @@ extern id const kGRPCTrailersKey; */ - (instancetype)initWithHost:(NSString *)host path:(NSString *)path - requestsWriter:(GRXWriter *)requestsWriter; - -- (instancetype)initWithHost:(NSString *)host - path:(NSString *)path - requestsWriter:(GRXWriter *)requestsWriter - flags:(GRPCCallFlags)flags NS_DESIGNATED_INITIALIZER; + requestsWriter:(GRXWriter *)requestsWriter NS_DESIGNATED_INITIALIZER; /** * Finishes the request side of this call, notifies the server that the RPC should be cancelled, and @@ -251,6 +245,14 @@ extern id const kGRPCTrailersKey; */ - (void)cancel; +/** + * Set the call flag for a specific host path. + * + * Host parameter should not contain the scheme (http:// or https://), only the name or IP addr + * and the port number, for example @"localhost:5050". + */ ++ (void)setCallAttribute:(GRPCCallAttr)callAttr host:(NSString *)host path:(NSString *)path; + // TODO(jcanizales): Let specify a deadline. As a category of GRXWriter? @end diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index eb7998ed975..2c0b7799452 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -47,6 +47,7 @@ NSString * const kGRPCHeadersKey = @"io.grpc.HeadersKey"; NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; +static NSMutableDictionary *callFlags; @interface GRPCCall () // Make them read-write. @@ -75,7 +76,6 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; NSString *_host; NSString *_path; - GRPCCallFlags _flags; GRPCWrappedCall *_wrappedCall; GRPCConnectivityMonitor *_connectivityMonitor; @@ -107,23 +107,43 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; // TODO(jcanizales): If grpc_init is idempotent, this should be changed from load to initialize. + (void)load { grpc_init(); + callFlags = [NSMutableDictionary dictionary]; } -- (instancetype)init { - return [self initWithHost:nil path:nil requestsWriter:nil flags:0]; ++ (void)setCallAttribute:(GRPCCallAttr)callAttr host:(NSString *)host path:(NSString *)path { + NSString *hostAndPath = [NSString stringWithFormat:@"%@%@", host, path]; + switch (callAttr) { + case GRPCCallAttrDefault: + callFlags[hostAndPath] = @0; + break; + case GRPCCallAttrIdempotentRequest: + callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; + break; + case GRPCCallAttrCacheableRequest: + callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; + break; + default: + break; + } } -- (instancetype)initWithHost:(NSString *)host - path:(NSString *)path - requestsWriter:(GRXWriter *)requestWriter{ - return [self initWithHost:host path:path requestsWriter:requestWriter flags:0]; ++ (uint32_t)getCallFlag:(NSString *)host path:(NSString *)path { + NSString *hostAndPath = [NSString stringWithFormat:@"%@%@", host, path]; + if (nil != [callFlags objectForKey:hostAndPath]) { + return [callFlags[hostAndPath] intValue]; + } else { + return 0; + } +} + +- (instancetype)init { + return [self initWithHost:nil path:nil requestsWriter:nil]; } // Designated initializer - (instancetype)initWithHost:(NSString *)host path:(NSString *)path - requestsWriter:(GRXWriter *)requestWriter - flags:(GRPCCallFlags)flags { + requestsWriter:(GRXWriter *)requestWriter { if (!host || !path) { [NSException raise:NSInvalidArgumentException format:@"Neither host nor path can be nil."]; } @@ -134,7 +154,6 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; if ((self = [super init])) { _host = [host copy]; _path = [path copy]; - _flags = flags; // Serial queue to invoke the non-reentrant methods of the grpc_call object. _callQueue = dispatch_queue_create("io.grpc.call", NULL); @@ -240,7 +259,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; - (void)sendHeaders:(NSDictionary *)headers { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers - flags:_flags + flags:(uint32_t)[GRPCCall getCallFlag:_host path:_path] handler:nil]]]; } diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h index b2c3e8def32..04fc1e45f16 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.h +++ b/src/objective-c/ProtoRPC/ProtoRPC.h @@ -47,8 +47,7 @@ __attribute__((deprecated("Please use GRPCProtoCall."))) method:(GRPCProtoMethod *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable - flags:(GRPCCallFlags)flags NS_DESIGNATED_INITIALIZER; + responsesWriteable:(id)responsesWriteable NS_DESIGNATED_INITIALIZER; - (void)start; @end diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 16cb04a83bf..83d1b655e8d 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -65,8 +65,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing #pragma clang diagnostic ignored "-Wobjc-designated-initializers" - (instancetype)initWithHost:(NSString *)host path:(NSString *)path - requestsWriter:(GRXWriter *)requestsWriter - flags:(GRPCCallFlags)flags { + requestsWriter:(GRXWriter *)requestsWriter { [NSException raise:NSInvalidArgumentException format:@"Please use ProtoRPC's designated initializer instead."]; return nil; @@ -78,8 +77,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing method:(GRPCProtoMethod *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable - flags:(GRPCCallFlags)flags { + responsesWriteable:(id)responsesWriteable { // Because we can't tell the type system to constrain the class, we need to check at runtime: if (![responseClass respondsToSelector:@selector(parseFromData:error:)]) { [NSException raise:NSInvalidArgumentException @@ -93,8 +91,7 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsing } return [proto data]; }]; - if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter - flags:flags])) { + if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) { __weak ProtoRPC *weakSelf = self; // A writeable that parses the proto messages received. diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 0fd5764dbc0..5a19fb35db0 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -48,8 +48,7 @@ __attribute__((deprecated("Please use GRPCProtoService."))) - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable - flags:(GRPCCallFlags)flags; + responsesWriteable:(id)responsesWriteable; @end diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m index 53337cd983e..3487fac59d3 100644 --- a/src/objective-c/ProtoRPC/ProtoService.m +++ b/src/objective-c/ProtoRPC/ProtoService.m @@ -68,8 +68,7 @@ - (GRPCProtoCall *)RPCToMethod:(NSString *)method requestsWriter:(GRXWriter *)requestsWriter responseClass:(Class)responseClass - responsesWriteable:(id)responsesWriteable - flags:(GRPCCallFlags)flags { + responsesWriteable:(id)responsesWriteable { GRPCProtoMethod *methodName = [[GRPCProtoMethod alloc] initWithPackage:_packageName service:_serviceName method:method]; @@ -77,8 +76,7 @@ method:methodName requestsWriter:requestsWriter responseClass:responseClass - responsesWriteable:responsesWriteable - flags:flags]; + responsesWriteable:responsesWriteable]; } @end From 1bd5c77a655ade2bcc39110996dcdec16209e105 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 30 Sep 2016 15:13:58 -0700 Subject: [PATCH 07/10] Add idempotent test --- src/objective-c/tests/GRPCClientTests.m | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 916a335802a..ce6ceee586a 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -317,4 +317,37 @@ static GRPCProtoMethod *kUnaryCallMethod; } +- (void)testIdempotentProtoRPC { + __weak XCTestExpectation *response = [self expectationWithDescription:@"Expected response."]; + __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."]; + + RMTSimpleRequest *request = [RMTSimpleRequest message]; + request.responseSize = 100; + request.fillUsername = YES; + request.fillOauthScope = YES; + GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]]; + + GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress + path:kUnaryCallMethod.HTTPPath + requestsWriter:requestsWriter]; + [GRPCCall setCallAttribute:GRPCCallAttrIdempotentRequest host:kHostAddress path:kUnaryCallMethod.HTTPPath]; + + id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { + XCTAssertNotNil(value, @"nil value received as response."); + XCTAssertGreaterThan(value.length, 0, @"Empty response received."); + RMTSimpleResponse *responseProto = [RMTSimpleResponse parseFromData:value error:NULL]; + // We expect empty strings, not nil: + XCTAssertNotNil(responseProto.username, @"Response's username is nil."); + XCTAssertNotNil(responseProto.oauthScope, @"Response's OAuth scope is nil."); + [response fulfill]; + } completionHandler:^(NSError *errorOrNil) { + XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil); + [completion fulfill]; + }]; + + [call startWithWriteable:responsesWriteable]; + + [self waitForExpectationsWithTimeout:8 handler:nil]; +} + @end From 0814e3cb179513a1ef96141f51e410416c2fea62 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Fri, 30 Sep 2016 16:28:24 -0700 Subject: [PATCH 08/10] Minor fixes --- src/core/ext/transport/cronet/transport/cronet_transport.c | 4 ++-- src/objective-c/ProtoRPC/ProtoService.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index 6d5fe318ccb..6b0ed12b1e7 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -566,10 +566,10 @@ static void convert_metadata_to_cronet_headers( } if (mdelem->key == GRPC_MDSTR_METHOD) { if (mdelem->value == GRPC_MDSTR_PUT) { - *method = (const char*)mdelem->value->slice.data.refcounted.bytes; + *method = "PUT"; } else { /* POST method in default*/ - *method = (const char*)(GRPC_MDSTR_POST->slice.data.refcounted.bytes); + *method = "POST"; } continue; } diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h index 5a19fb35db0..7faae1b49c9 100644 --- a/src/objective-c/ProtoRPC/ProtoService.h +++ b/src/objective-c/ProtoRPC/ProtoService.h @@ -32,7 +32,6 @@ */ #import -#import "ProtoRPC.h" @class GRPCProtoCall; @protocol GRXWriteable; From 6c0b960a45915227410d417bee5965712331bcf9 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Sun, 2 Oct 2016 14:32:06 -0700 Subject: [PATCH 09/10] Name revision --- src/objective-c/GRPCClient/GRPCCall.h | 18 +++++++++--------- src/objective-c/GRPCClient/GRPCCall.m | 24 ++++++++++-------------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 4b28cade42e..7645bb1d34a 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -155,15 +155,15 @@ typedef NS_ENUM(NSUInteger, GRPCErrorCode) { }; /** - * Flags for options of a gRPC call - * + * Safety remark of a gRPC method as defined in RFC 2616 Section 9.1 */ -typedef NS_ENUM(NSUInteger, GRPCCallAttr) { - GRPCCallAttrDefault = 0, - /** Signal that the call is idempotent */ - GRPCCallAttrIdempotentRequest = 1, - /** Signal that the call is cacheable. GRPC is free to use GET verb */ - GRPCCallAttrCacheableRequest = 2, +typedef NS_ENUM(NSUInteger, GRPCCallSafety) { + /** Signal that there is no guarantees on how the call affects the server state. */ + GRPCCallSafetyDefault = 0, + /** Signal that the call is idempotent. gRPC is free to use PUT verb. */ + GRPCCallSafetyIdempotentRequest = 1, + /** Signal that the call is cacheable and will not affect server state. gRPC is free to use GET verb. */ + GRPCCallSafetyCacheableRequest = 2, }; /** @@ -251,7 +251,7 @@ extern id const kGRPCTrailersKey; * Host parameter should not contain the scheme (http:// or https://), only the name or IP addr * and the port number, for example @"localhost:5050". */ -+ (void)setCallAttribute:(GRPCCallAttr)callAttr host:(NSString *)host path:(NSString *)path; ++ (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path; // TODO(jcanizales): Let specify a deadline. As a category of GRXWriter? @end diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 2c0b7799452..43204345f55 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -110,16 +110,16 @@ static NSMutableDictionary *callFlags; callFlags = [NSMutableDictionary dictionary]; } -+ (void)setCallAttribute:(GRPCCallAttr)callAttr host:(NSString *)host path:(NSString *)path { - NSString *hostAndPath = [NSString stringWithFormat:@"%@%@", host, path]; - switch (callAttr) { - case GRPCCallAttrDefault: ++ (void)setCallSafety:(GRPCCallSafety)callSafety host:(NSString *)host path:(NSString *)path { + NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; + switch (callSafety) { + case GRPCCallSafetyDefault: callFlags[hostAndPath] = @0; break; - case GRPCCallAttrIdempotentRequest: + case GRPCCallSafetyIdempotentRequest: callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; break; - case GRPCCallAttrCacheableRequest: + case GRPCCallSafetyCacheableRequest: callFlags[hostAndPath] = @GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; break; default: @@ -127,13 +127,9 @@ static NSMutableDictionary *callFlags; } } -+ (uint32_t)getCallFlag:(NSString *)host path:(NSString *)path { - NSString *hostAndPath = [NSString stringWithFormat:@"%@%@", host, path]; - if (nil != [callFlags objectForKey:hostAndPath]) { - return [callFlags[hostAndPath] intValue]; - } else { - return 0; - } ++ (uint32_t)callFlagsForHost:(NSString *)host path:(NSString *)path { + NSString *hostAndPath = [NSString stringWithFormat:@"%@/%@", host, path]; + return [callFlags[hostAndPath] intValue]; } - (instancetype)init { @@ -259,7 +255,7 @@ static NSMutableDictionary *callFlags; - (void)sendHeaders:(NSDictionary *)headers { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers - flags:(uint32_t)[GRPCCall getCallFlag:_host path:_path] + flags:[GRPCCall callFlagsForHost:_host path:_path] handler:nil]]]; } From 8739e806fcc0358a404ff7e752fddb49898be409 Mon Sep 17 00:00:00 2001 From: Muxi Yan Date: Mon, 3 Oct 2016 09:41:31 -0700 Subject: [PATCH 10/10] Update test --- src/objective-c/tests/GRPCClientTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index ce6ceee586a..77640525d58 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -330,7 +330,7 @@ static GRPCProtoMethod *kUnaryCallMethod; GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress path:kUnaryCallMethod.HTTPPath requestsWriter:requestsWriter]; - [GRPCCall setCallAttribute:GRPCCallAttrIdempotentRequest host:kHostAddress path:kUnaryCallMethod.HTTPPath]; + [GRPCCall setCallSafety:GRPCCallSafetyIdempotentRequest host:kHostAddress path:kUnaryCallMethod.HTTPPath]; id responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { XCTAssertNotNil(value, @"nil value received as response.");