From 2822e9ea387ab26be927dec04af6b94e9257791f Mon Sep 17 00:00:00 2001 From: Matthew Davis Date: Thu, 3 Sep 2015 12:18:00 -0700 Subject: [PATCH 1/2] added support for retrieving HTTP response headers in obj-c. Also added a +sharedAPI class method for easy initialization of an API class without passing headers --- .../main/resources/objc/ApiClient-body.mustache | 17 ++++++++++++++++- .../resources/objc/ApiClient-header.mustache | 3 +++ .../src/main/resources/objc/api-body.mustache | 11 ++++++++++- .../src/main/resources/objc/api-header.mustache | 1 + 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/objc/ApiClient-body.mustache b/modules/swagger-codegen/src/main/resources/objc/ApiClient-body.mustache index b7643de6ddd..5b2a290ab85 100644 --- a/modules/swagger-codegen/src/main/resources/objc/ApiClient-body.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/ApiClient-body.mustache @@ -9,6 +9,13 @@ static bool cacheEnabled = false; static AFNetworkReachabilityStatus reachabilityStatus = AFNetworkReachabilityStatusNotReachable; static void (^reachabilityChangeBlock)(int); + +@interface {{classPrefix}}ApiClient () + +@property (readwrite, nonatomic) NSDictionary *HTTPResponseHeaders; + +@end + @implementation {{classPrefix}}ApiClient - (instancetype)init { @@ -385,6 +392,8 @@ static void (^reachabilityChangeBlock)(int); if([[{{classPrefix}}Configuration sharedConfig] debug]) { [self logResponse:operation forRequest:request error:nil]; } + NSDictionary *responseHeaders = [[operation response] allHeaderFields]; + self.HTTPResponseHeaders = responseHeaders; completionBlock(response, nil); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { @@ -398,6 +407,10 @@ static void (^reachabilityChangeBlock)(int); if([[{{classPrefix}}Configuration sharedConfig] debug]) [self logResponse:nil forRequest:request error:augmentedError]; + + NSDictionary *responseHeaders = [[operation response] allHeaderFields]; + self.HTTPResponseHeaders = responseHeaders; + completionBlock(nil, augmentedError); } }]; @@ -441,6 +454,7 @@ static void (^reachabilityChangeBlock)(int); NSURL *file = [NSURL fileURLWithPath:filepath]; [operation.responseData writeToURL:file atomically:YES]; + self.HTTPResponseHeaders = headers; completionBlock(file, nil); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { @@ -455,7 +469,8 @@ static void (^reachabilityChangeBlock)(int); if ([[{{classPrefix}}Configuration sharedConfig] debug]) { [self logResponse:nil forRequest:request error:augmentedError]; } - + NSDictionary *responseHeaders = [[operation response] allHeaderFields]; + self.HTTPResponseHeaders = responseHeaders; completionBlock(nil, augmentedError); } }]; diff --git a/modules/swagger-codegen/src/main/resources/objc/ApiClient-header.mustache b/modules/swagger-codegen/src/main/resources/objc/ApiClient-header.mustache index eba62705879..fef1a2b79e7 100644 --- a/modules/swagger-codegen/src/main/resources/objc/ApiClient-header.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/ApiClient-header.mustache @@ -31,6 +31,9 @@ extern NSString *const {{classPrefix}}ResponseObjectErrorKey; @property(nonatomic, assign) NSTimeInterval timeoutInterval; @property(nonatomic, readonly) NSOperationQueue* queue; +/// In order to ensure the HTTPResponseHeaders are correct, it is recommended to initialize one {{classPrefix}}ApiClient instance per thread. +@property(nonatomic, readonly) NSDictionary* HTTPResponseHeaders; + /** * Clears Cache */ diff --git a/modules/swagger-codegen/src/main/resources/objc/api-body.mustache b/modules/swagger-codegen/src/main/resources/objc/api-body.mustache index 534c887fe7b..1aa22a0a0c6 100644 --- a/modules/swagger-codegen/src/main/resources/objc/api-body.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/api-body.mustache @@ -11,6 +11,8 @@ @implementation {{classname}} +static {{classname}}* singletonAPI = nil; + #pragma mark - Initialize methods - (id) init { @@ -38,7 +40,6 @@ #pragma mark - +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { - static {{classname}}* singletonAPI = nil; if (singletonAPI == nil) { singletonAPI = [[{{classname}} alloc] init]; @@ -47,6 +48,14 @@ return singletonAPI; } ++({{classname}}*) sharedAPI { + + if (singletonAPI == nil) { + singletonAPI = [[{{classname}} alloc] init]; + } + return singletonAPI; +} + -(void) addHeader:(NSString*)value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; } diff --git a/modules/swagger-codegen/src/main/resources/objc/api-header.mustache b/modules/swagger-codegen/src/main/resources/objc/api-header.mustache index d9f691f7227..29c7d9477f2 100644 --- a/modules/swagger-codegen/src/main/resources/objc/api-header.mustache +++ b/modules/swagger-codegen/src/main/resources/objc/api-header.mustache @@ -20,6 +20,7 @@ -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; ++({{classname}}*) sharedAPI; {{#operation}} /// /// From f067b86fa036a67148b89c49086213c59e917812 Mon Sep 17 00:00:00 2001 From: Matthew Davis Date: Thu, 3 Sep 2015 12:31:30 -0700 Subject: [PATCH 2/2] re-built sample objc-petstore --- samples/client/petstore/objc/README.md | 4 ++++ .../petstore/objc/SwaggerClient/SWGApiClient.h | 3 +++ .../petstore/objc/SwaggerClient/SWGApiClient.m | 17 ++++++++++++++++- .../petstore/objc/SwaggerClient/SWGPetApi.h | 1 + .../petstore/objc/SwaggerClient/SWGPetApi.m | 11 ++++++++++- .../petstore/objc/SwaggerClient/SWGStoreApi.h | 1 + .../petstore/objc/SwaggerClient/SWGStoreApi.m | 11 ++++++++++- .../petstore/objc/SwaggerClient/SWGUserApi.h | 3 ++- .../petstore/objc/SwaggerClient/SWGUserApi.m | 13 +++++++++++-- 9 files changed, 58 insertions(+), 6 deletions(-) diff --git a/samples/client/petstore/objc/README.md b/samples/client/petstore/objc/README.md index 4cce2c882bb..10e44984683 100644 --- a/samples/client/petstore/objc/README.md +++ b/samples/client/petstore/objc/README.md @@ -12,6 +12,10 @@ To install it, put the API client library in your project and then simply add th pod "SwaggerClient", :path => "/path/to/lib" ``` +## Recommendation + +It's recommended to create an instance of ApiClient per thread in a multithreaded environment to avoid any potential issue. + ## Author apiteam@swagger.io diff --git a/samples/client/petstore/objc/SwaggerClient/SWGApiClient.h b/samples/client/petstore/objc/SwaggerClient/SWGApiClient.h index 84f28faa8c6..580efa739a0 100644 --- a/samples/client/petstore/objc/SwaggerClient/SWGApiClient.h +++ b/samples/client/petstore/objc/SwaggerClient/SWGApiClient.h @@ -35,6 +35,9 @@ extern NSString *const SWGResponseObjectErrorKey; @property(nonatomic, assign) NSTimeInterval timeoutInterval; @property(nonatomic, readonly) NSOperationQueue* queue; +/// In order to ensure the HTTPResponseHeaders are correct, it is recommended to initialize one SWGApiClient instance per thread. +@property(nonatomic, readonly) NSDictionary* HTTPResponseHeaders; + /** * Clears Cache */ diff --git a/samples/client/petstore/objc/SwaggerClient/SWGApiClient.m b/samples/client/petstore/objc/SwaggerClient/SWGApiClient.m index 906169f4d12..826443453b0 100644 --- a/samples/client/petstore/objc/SwaggerClient/SWGApiClient.m +++ b/samples/client/petstore/objc/SwaggerClient/SWGApiClient.m @@ -9,6 +9,13 @@ static bool cacheEnabled = false; static AFNetworkReachabilityStatus reachabilityStatus = AFNetworkReachabilityStatusNotReachable; static void (^reachabilityChangeBlock)(int); + +@interface SWGApiClient () + +@property (readwrite, nonatomic) NSDictionary *HTTPResponseHeaders; + +@end + @implementation SWGApiClient - (instancetype)init { @@ -385,6 +392,8 @@ static void (^reachabilityChangeBlock)(int); if([[SWGConfiguration sharedConfig] debug]) { [self logResponse:operation forRequest:request error:nil]; } + NSDictionary *responseHeaders = [[operation response] allHeaderFields]; + self.HTTPResponseHeaders = responseHeaders; completionBlock(response, nil); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { @@ -398,6 +407,10 @@ static void (^reachabilityChangeBlock)(int); if([[SWGConfiguration sharedConfig] debug]) [self logResponse:nil forRequest:request error:augmentedError]; + + NSDictionary *responseHeaders = [[operation response] allHeaderFields]; + self.HTTPResponseHeaders = responseHeaders; + completionBlock(nil, augmentedError); } }]; @@ -441,6 +454,7 @@ static void (^reachabilityChangeBlock)(int); NSURL *file = [NSURL fileURLWithPath:filepath]; [operation.responseData writeToURL:file atomically:YES]; + self.HTTPResponseHeaders = headers; completionBlock(file, nil); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { @@ -455,7 +469,8 @@ static void (^reachabilityChangeBlock)(int); if ([[SWGConfiguration sharedConfig] debug]) { [self logResponse:nil forRequest:request error:augmentedError]; } - + NSDictionary *responseHeaders = [[operation response] allHeaderFields]; + self.HTTPResponseHeaders = responseHeaders; completionBlock(nil, augmentedError); } }]; diff --git a/samples/client/petstore/objc/SwaggerClient/SWGPetApi.h b/samples/client/petstore/objc/SwaggerClient/SWGPetApi.h index f7e67d0aa1f..7ea1821e575 100644 --- a/samples/client/petstore/objc/SwaggerClient/SWGPetApi.h +++ b/samples/client/petstore/objc/SwaggerClient/SWGPetApi.h @@ -18,6 +18,7 @@ -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGPetApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; ++(SWGPetApi*) sharedAPI; /// /// /// Update an existing pet diff --git a/samples/client/petstore/objc/SwaggerClient/SWGPetApi.m b/samples/client/petstore/objc/SwaggerClient/SWGPetApi.m index d79584f90bf..4b8eba70562 100644 --- a/samples/client/petstore/objc/SwaggerClient/SWGPetApi.m +++ b/samples/client/petstore/objc/SwaggerClient/SWGPetApi.m @@ -9,6 +9,8 @@ @implementation SWGPetApi +static SWGPetApi* singletonAPI = nil; + #pragma mark - Initialize methods - (id) init { @@ -36,7 +38,6 @@ #pragma mark - +(SWGPetApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { - static SWGPetApi* singletonAPI = nil; if (singletonAPI == nil) { singletonAPI = [[SWGPetApi alloc] init]; @@ -45,6 +46,14 @@ return singletonAPI; } ++(SWGPetApi*) sharedAPI { + + if (singletonAPI == nil) { + singletonAPI = [[SWGPetApi alloc] init]; + } + return singletonAPI; +} + -(void) addHeader:(NSString*)value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; } diff --git a/samples/client/petstore/objc/SwaggerClient/SWGStoreApi.h b/samples/client/petstore/objc/SwaggerClient/SWGStoreApi.h index 09e67e38ed0..e1c644ef5f4 100644 --- a/samples/client/petstore/objc/SwaggerClient/SWGStoreApi.h +++ b/samples/client/petstore/objc/SwaggerClient/SWGStoreApi.h @@ -18,6 +18,7 @@ -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGStoreApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; ++(SWGStoreApi*) sharedAPI; /// /// /// Returns pet inventories by status diff --git a/samples/client/petstore/objc/SwaggerClient/SWGStoreApi.m b/samples/client/petstore/objc/SwaggerClient/SWGStoreApi.m index 792147ebed1..5fdf86b43af 100644 --- a/samples/client/petstore/objc/SwaggerClient/SWGStoreApi.m +++ b/samples/client/petstore/objc/SwaggerClient/SWGStoreApi.m @@ -9,6 +9,8 @@ @implementation SWGStoreApi +static SWGStoreApi* singletonAPI = nil; + #pragma mark - Initialize methods - (id) init { @@ -36,7 +38,6 @@ #pragma mark - +(SWGStoreApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { - static SWGStoreApi* singletonAPI = nil; if (singletonAPI == nil) { singletonAPI = [[SWGStoreApi alloc] init]; @@ -45,6 +46,14 @@ return singletonAPI; } ++(SWGStoreApi*) sharedAPI { + + if (singletonAPI == nil) { + singletonAPI = [[SWGStoreApi alloc] init]; + } + return singletonAPI; +} + -(void) addHeader:(NSString*)value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; } diff --git a/samples/client/petstore/objc/SwaggerClient/SWGUserApi.h b/samples/client/petstore/objc/SwaggerClient/SWGUserApi.h index a6e69a8947d..21f314684fd 100644 --- a/samples/client/petstore/objc/SwaggerClient/SWGUserApi.h +++ b/samples/client/petstore/objc/SwaggerClient/SWGUserApi.h @@ -18,6 +18,7 @@ -(void) addHeader:(NSString*)value forKey:(NSString*)key; -(unsigned long) requestQueueSize; +(SWGUserApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key; ++(SWGUserApi*) sharedAPI; /// /// /// Create user @@ -98,7 +99,7 @@ /// Get user by user name /// /// -/// @param username The name that needs to be fetched. Use user1 for testing. +/// @param username The name that needs to be fetched. Use user1 for testing. /// /// /// @return SWGUser* diff --git a/samples/client/petstore/objc/SwaggerClient/SWGUserApi.m b/samples/client/petstore/objc/SwaggerClient/SWGUserApi.m index 92dd00fa28d..75cf8d51b0e 100644 --- a/samples/client/petstore/objc/SwaggerClient/SWGUserApi.m +++ b/samples/client/petstore/objc/SwaggerClient/SWGUserApi.m @@ -9,6 +9,8 @@ @implementation SWGUserApi +static SWGUserApi* singletonAPI = nil; + #pragma mark - Initialize methods - (id) init { @@ -36,7 +38,6 @@ #pragma mark - +(SWGUserApi*) apiWithHeader:(NSString*)headerValue key:(NSString*)key { - static SWGUserApi* singletonAPI = nil; if (singletonAPI == nil) { singletonAPI = [[SWGUserApi alloc] init]; @@ -45,6 +46,14 @@ return singletonAPI; } ++(SWGUserApi*) sharedAPI { + + if (singletonAPI == nil) { + singletonAPI = [[SWGUserApi alloc] init]; + } + return singletonAPI; +} + -(void) addHeader:(NSString*)value forKey:(NSString*)key { [self.defaultHeaders setValue:value forKey:key]; } @@ -461,7 +470,7 @@ /// /// Get user by user name /// -/// @param username The name that needs to be fetched. Use user1 for testing. +/// @param username The name that needs to be fetched. Use user1 for testing. /// /// @returns SWGUser* ///