forked from loafle/openapi-generator-original
505 lines
20 KiB
Plaintext
505 lines
20 KiB
Plaintext
#import "{{classPrefix}}ApiClient.h"
|
||
|
||
NSString *const {{classPrefix}}ResponseObjectErrorKey = @"{{classPrefix}}ResponseObject";
|
||
|
||
static NSUInteger requestId = 0;
|
||
static bool offlineState = false;
|
||
static NSMutableSet * queuedRequests = nil;
|
||
static bool cacheEnabled = false;
|
||
static AFNetworkReachabilityStatus reachabilityStatus = AFNetworkReachabilityStatusNotReachable;
|
||
static void (^reachabilityChangeBlock)(int);
|
||
|
||
|
||
static NSDictionary * {{classPrefix}}__headerFieldsForResponse(NSURLResponse *response) {
|
||
if(![response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||
return nil;
|
||
}
|
||
return ((NSHTTPURLResponse*)response).allHeaderFields;
|
||
}
|
||
|
||
static NSString * {{classPrefix}}__fileNameForResponse(NSURLResponse *response) {
|
||
NSDictionary * headers = {{classPrefix}}__headerFieldsForResponse(response);
|
||
if(!headers[@"Content-Disposition"]) {
|
||
return [NSString stringWithFormat:@"%@", [[NSProcessInfo processInfo] globallyUniqueString]];
|
||
}
|
||
NSString *pattern = @"filename=['\"]?([^'\"\\s]+)['\"]?";
|
||
NSRegularExpression *regexp = [NSRegularExpression regularExpressionWithPattern:pattern
|
||
options:NSRegularExpressionCaseInsensitive
|
||
error:nil];
|
||
NSString *contentDispositionHeader = headers[@"Content-Disposition"];
|
||
NSTextCheckingResult *match = [regexp firstMatchInString:contentDispositionHeader
|
||
options:0
|
||
range:NSMakeRange(0, [contentDispositionHeader length])];
|
||
return [contentDispositionHeader substringWithRange:[match rangeAtIndex:1]];
|
||
}
|
||
|
||
|
||
@interface {{classPrefix}}ApiClient ()
|
||
|
||
@property (nonatomic, strong) NSDictionary* HTTPResponseHeaders;
|
||
|
||
@end
|
||
|
||
@implementation {{classPrefix}}ApiClient
|
||
|
||
- (instancetype)init {
|
||
NSString *baseUrl = [[{{classPrefix}}Configuration sharedConfig] host];
|
||
return [self initWithBaseURL:[NSURL URLWithString:baseUrl]];
|
||
}
|
||
|
||
- (instancetype)initWithBaseURL:(NSURL *)url {
|
||
self = [super initWithBaseURL:url];
|
||
if (self) {
|
||
self.timeoutInterval = 60;
|
||
self.requestSerializer = [AFJSONRequestSerializer serializer];
|
||
self.responseSerializer = [AFJSONResponseSerializer serializer];
|
||
self.securityPolicy = [self customSecurityPolicy];
|
||
self.responseDeserializer = [[{{classPrefix}}ResponseDeserializer alloc] init];
|
||
self.sanitizer = [[{{classPrefix}}Sanitizer alloc] init];
|
||
// configure reachability
|
||
[self configureCacheReachibility];
|
||
}
|
||
return self;
|
||
}
|
||
|
||
+ (void)initialize {
|
||
if (self == [{{classPrefix}}ApiClient class]) {
|
||
queuedRequests = [[NSMutableSet alloc] init];
|
||
// initialize URL cache
|
||
[self configureCacheWithMemoryAndDiskCapacity:4*1024*1024 diskSize:32*1024*1024];
|
||
}
|
||
}
|
||
|
||
#pragma mark - Setter Methods
|
||
|
||
+ (void) setOfflineState:(BOOL) state {
|
||
offlineState = state;
|
||
}
|
||
|
||
+ (void) setCacheEnabled:(BOOL)enabled {
|
||
cacheEnabled = enabled;
|
||
}
|
||
|
||
+(void) setReachabilityStatus:(AFNetworkReachabilityStatus)status {
|
||
reachabilityStatus = status;
|
||
}
|
||
|
||
- (void)setHeaderValue:(NSString*) value forKey:(NSString*) forKey {
|
||
[self.requestSerializer setValue:value forHTTPHeaderField:forKey];
|
||
}
|
||
|
||
- (void)setRequestSerializer:(AFHTTPRequestSerializer<AFURLRequestSerialization> *)requestSerializer {
|
||
[super setRequestSerializer:requestSerializer];
|
||
requestSerializer.timeoutInterval = self.timeoutInterval;
|
||
}
|
||
|
||
#pragma mark - Cache Methods
|
||
|
||
+(void)clearCache {
|
||
[[NSURLCache sharedURLCache] removeAllCachedResponses];
|
||
}
|
||
|
||
+(void)configureCacheWithMemoryAndDiskCapacity: (unsigned long) memorySize
|
||
diskSize: (unsigned long) diskSize {
|
||
NSAssert(memorySize > 0, @"invalid in-memory cache size");
|
||
NSAssert(diskSize >= 0, @"invalid disk cache size");
|
||
|
||
NSURLCache *cache =
|
||
[[NSURLCache alloc]
|
||
initWithMemoryCapacity:memorySize
|
||
diskCapacity:diskSize
|
||
diskPath:@"swagger_url_cache"];
|
||
|
||
[NSURLCache setSharedURLCache:cache];
|
||
}
|
||
|
||
#pragma mark - Request Methods
|
||
|
||
+(NSUInteger)requestQueueSize {
|
||
return [queuedRequests count];
|
||
}
|
||
|
||
+(NSNumber*) nextRequestId {
|
||
@synchronized(self) {
|
||
return @(++requestId);
|
||
}
|
||
}
|
||
|
||
+(NSNumber*) queueRequest {
|
||
NSNumber* requestId = [[self class] nextRequestId];
|
||
{{classPrefix}}DebugLog(@"added %@ to request queue", requestId);
|
||
[queuedRequests addObject:requestId];
|
||
return requestId;
|
||
}
|
||
|
||
+(void) cancelRequest:(NSNumber*)requestId {
|
||
[queuedRequests removeObject:requestId];
|
||
}
|
||
|
||
-(Boolean) executeRequestWithId:(NSNumber*) requestId {
|
||
NSSet* matchingItems = [queuedRequests objectsPassingTest:^BOOL(id obj, BOOL *stop) {
|
||
return [obj intValue] == [requestId intValue];
|
||
}];
|
||
|
||
if (matchingItems.count == 1) {
|
||
{{classPrefix}}DebugLog(@"removed request id %@", requestId);
|
||
[queuedRequests removeObject:requestId];
|
||
return YES;
|
||
} else {
|
||
return NO;
|
||
}
|
||
}
|
||
|
||
#pragma mark - Reachability Methods
|
||
|
||
+(AFNetworkReachabilityStatus) getReachabilityStatus {
|
||
return reachabilityStatus;
|
||
}
|
||
|
||
+(BOOL) getOfflineState {
|
||
return offlineState;
|
||
}
|
||
|
||
+(void) setReachabilityChangeBlock:(void(^)(int))changeBlock {
|
||
reachabilityChangeBlock = changeBlock;
|
||
}
|
||
|
||
- (void) configureCacheReachibility {
|
||
[self.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
|
||
reachabilityStatus = status;
|
||
{{classPrefix}}DebugLog(@"reachability changed to %@",AFStringFromNetworkReachabilityStatus(status));
|
||
[{{classPrefix}}ApiClient setOfflineState:status == AFNetworkReachabilityStatusUnknown || status == AFNetworkReachabilityStatusNotReachable];
|
||
|
||
// call the reachability block, if configured
|
||
if (reachabilityChangeBlock != nil) {
|
||
reachabilityChangeBlock(status);
|
||
}
|
||
}];
|
||
|
||
[self.reachabilityManager startMonitoring];
|
||
}
|
||
|
||
#pragma mark - Operation Methods
|
||
|
||
- (void) operationWithCompletionBlock: (NSURLRequest *)request
|
||
requestId: (NSNumber *) requestId
|
||
completionBlock: (void (^)(id, NSError *))completionBlock {
|
||
__weak __typeof(self)weakSelf = self;
|
||
NSURLSessionDataTask* op = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
|
||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||
if (![strongSelf executeRequestWithId:requestId]) {
|
||
return;
|
||
}
|
||
{{classPrefix}}DebugLogResponse(response, responseObject,request,error);
|
||
strongSelf.HTTPResponseHeaders = {{classPrefix}}__headerFieldsForResponse(response);
|
||
if(!error) {
|
||
completionBlock(responseObject, nil);
|
||
return;
|
||
}
|
||
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
|
||
if (responseObject) {
|
||
// Add in the (parsed) response body.
|
||
userInfo[{{classPrefix}}ResponseObjectErrorKey] = responseObject;
|
||
}
|
||
NSError *augmentedError = [error initWithDomain:error.domain code:error.code userInfo:userInfo];
|
||
completionBlock(nil, augmentedError);
|
||
}];
|
||
[op resume];
|
||
}
|
||
|
||
- (void) downloadOperationWithCompletionBlock: (NSURLRequest *)request
|
||
requestId: (NSNumber *) requestId
|
||
completionBlock: (void (^)(id, NSError *))completionBlock {
|
||
__weak __typeof(self)weakSelf = self;
|
||
NSURLSessionDataTask* op = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
|
||
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||
if (![strongSelf executeRequestWithId:requestId]) {
|
||
return;
|
||
}
|
||
strongSelf.HTTPResponseHeaders = {{classPrefix}}__headerFieldsForResponse(response);
|
||
{{classPrefix}}DebugLogResponse(response, responseObject,request,error);
|
||
if(error) {
|
||
NSMutableDictionary *userInfo = [error.userInfo mutableCopy];
|
||
if (responseObject) {
|
||
userInfo[{{classPrefix}}ResponseObjectErrorKey] = responseObject;
|
||
}
|
||
NSError *augmentedError = [error initWithDomain:error.domain code:error.code userInfo:userInfo];
|
||
completionBlock(nil, augmentedError);
|
||
}
|
||
NSString *directory = [self configuration].tempFolderPath ?: NSTemporaryDirectory();
|
||
NSString * filename = {{classPrefix}}__fileNameForResponse(response);
|
||
|
||
NSString *filepath = [directory stringByAppendingPathComponent:filename];
|
||
NSURL *file = [NSURL fileURLWithPath:filepath];
|
||
|
||
[responseObject writeToURL:file atomically:YES];
|
||
|
||
completionBlock(file, nil);
|
||
}];
|
||
[op resume];
|
||
}
|
||
|
||
#pragma mark - Perform Request Methods
|
||
|
||
-(NSNumber*) requestWithPath: (NSString*) path
|
||
method: (NSString*) method
|
||
pathParams: (NSDictionary *) pathParams
|
||
queryParams: (NSDictionary*) queryParams
|
||
formParams: (NSDictionary *) formParams
|
||
files: (NSDictionary *) files
|
||
body: (id) body
|
||
headerParams: (NSDictionary*) headerParams
|
||
authSettings: (NSArray *) authSettings
|
||
requestContentType: (NSString*) requestContentType
|
||
responseContentType: (NSString*) responseContentType
|
||
responseType: (NSString *) responseType
|
||
completionBlock: (void (^)(id, NSError *))completionBlock {
|
||
// setting request serializer
|
||
if ([requestContentType isEqualToString:@"application/json"]) {
|
||
self.requestSerializer = [{{classPrefix}}JSONRequestSerializer serializer];
|
||
}
|
||
else if ([requestContentType isEqualToString:@"application/x-www-form-urlencoded"]) {
|
||
self.requestSerializer = [AFHTTPRequestSerializer serializer];
|
||
}
|
||
else if ([requestContentType isEqualToString:@"multipart/form-data"]) {
|
||
self.requestSerializer = [AFHTTPRequestSerializer serializer];
|
||
}
|
||
else {
|
||
self.requestSerializer = [AFHTTPRequestSerializer serializer];
|
||
NSAssert(NO, @"Unsupported request type %@", requestContentType);
|
||
}
|
||
|
||
// setting response serializer
|
||
if ([responseContentType isEqualToString:@"application/json"]) {
|
||
self.responseSerializer = [{{classPrefix}}JSONResponseSerializer serializer];
|
||
} else {
|
||
self.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||
}
|
||
|
||
// sanitize parameters
|
||
pathParams = [self.sanitizer sanitizeForSerialization:pathParams];
|
||
queryParams = [self.sanitizer sanitizeForSerialization:queryParams];
|
||
headerParams = [self.sanitizer sanitizeForSerialization:headerParams];
|
||
formParams = [self.sanitizer sanitizeForSerialization:formParams];
|
||
if(![body isKindOfClass:[NSData class]]) {
|
||
body = [self.sanitizer sanitizeForSerialization:body];
|
||
}
|
||
|
||
// auth setting
|
||
[self updateHeaderParams:&headerParams queryParams:&queryParams WithAuthSettings:authSettings];
|
||
|
||
NSMutableString *resourcePath = [NSMutableString stringWithString:path];
|
||
[pathParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||
NSString * safeString = ([obj isKindOfClass:[NSString class]]) ? obj : [NSString stringWithFormat:@"%@", obj];
|
||
safeString = {{classPrefix}}PercentEscapedStringFromString(safeString);
|
||
[resourcePath replaceCharactersInRange:[resourcePath rangeOfString:[NSString stringWithFormat:@"{%@}", key]] withString:safeString];
|
||
}];
|
||
|
||
NSMutableURLRequest * request = nil;
|
||
|
||
NSString* pathWithQueryParams = [self pathWithQueryParamsToString:resourcePath queryParams:queryParams];
|
||
if ([pathWithQueryParams hasPrefix:@"/"]) {
|
||
pathWithQueryParams = [pathWithQueryParams substringFromIndex:1];
|
||
}
|
||
|
||
NSString* urlString = [[NSURL URLWithString:pathWithQueryParams relativeToURL:self.baseURL] absoluteString];
|
||
if (files.count > 0) {
|
||
__weak __typeof(self)weakSelf = self;
|
||
request = [self.requestSerializer multipartFormRequestWithMethod:@"POST"
|
||
URLString:urlString
|
||
parameters:nil
|
||
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
|
||
[formParams enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||
NSString *objString = [weakSelf.sanitizer parameterToString:obj];
|
||
NSData *data = [objString dataUsingEncoding:NSUTF8StringEncoding];
|
||
[formData appendPartWithFormData:data name:key];
|
||
}];
|
||
[files enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
|
||
NSURL *filePath = (NSURL *)obj;
|
||
[formData appendPartWithFileURL:filePath name:key error:nil];
|
||
}];
|
||
} error:nil];
|
||
}
|
||
else {
|
||
if (formParams) {
|
||
request = [self.requestSerializer requestWithMethod:method
|
||
URLString:urlString
|
||
parameters:formParams
|
||
error:nil];
|
||
}
|
||
if (body) {
|
||
request = [self.requestSerializer requestWithMethod:method
|
||
URLString:urlString
|
||
parameters:body
|
||
error:nil];
|
||
}
|
||
}
|
||
|
||
// request cache
|
||
BOOL hasHeaderParams = [headerParams count] > 0;
|
||
if (offlineState) {
|
||
{{classPrefix}}DebugLog(@"%@ cache forced", resourcePath);
|
||
[request setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
|
||
}
|
||
else if(!hasHeaderParams && [method isEqualToString:@"GET"] && cacheEnabled) {
|
||
{{classPrefix}}DebugLog(@"%@ cache enabled", resourcePath);
|
||
[request setCachePolicy:NSURLRequestUseProtocolCachePolicy];
|
||
}
|
||
else {
|
||
{{classPrefix}}DebugLog(@"%@ cache disabled", resourcePath);
|
||
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
|
||
}
|
||
|
||
if (hasHeaderParams){
|
||
for(NSString * key in [headerParams keyEnumerator]){
|
||
[request setValue:[headerParams valueForKey:key] forHTTPHeaderField:key];
|
||
}
|
||
}
|
||
[self.requestSerializer setValue:responseContentType forHTTPHeaderField:@"Accept"];
|
||
|
||
[self postProcessRequest:request];
|
||
|
||
NSNumber* requestId = [{{classPrefix}}ApiClient queueRequest];
|
||
if ([responseType isEqualToString:@"NSURL*"] || [responseType isEqualToString:@"NSURL"]) {
|
||
[self downloadOperationWithCompletionBlock:request requestId:requestId completionBlock:^(id data, NSError *error) {
|
||
completionBlock(data, error);
|
||
}];
|
||
}
|
||
else {
|
||
[self operationWithCompletionBlock:request requestId:requestId completionBlock:^(id data, NSError *error) {
|
||
NSError * serializationError;
|
||
id response = [self.responseDeserializer deserialize:data class:responseType error:&serializationError];
|
||
if(!response && !error){
|
||
error = serializationError;
|
||
}
|
||
completionBlock(response, error);
|
||
}];
|
||
}
|
||
return requestId;
|
||
}
|
||
|
||
//Added for easier override to modify request
|
||
-(void)postProcessRequest:(NSMutableURLRequest *)request {
|
||
// Always disable cookies!
|
||
[request setHTTPShouldHandleCookies:NO];
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
- (NSString*) pathWithQueryParamsToString:(NSString*) path
|
||
queryParams:(NSDictionary*) queryParams {
|
||
if(queryParams.count == 0) {
|
||
return path;
|
||
}
|
||
NSString * separator = nil;
|
||
NSUInteger counter = 0;
|
||
|
||
NSMutableString * requestUrl = [NSMutableString stringWithFormat:@"%@", path];
|
||
|
||
NSDictionary *separatorStyles = @{@"csv" : @",",
|
||
@"tsv" : @"\t",
|
||
@"pipes": @"|"
|
||
};
|
||
for(NSString * key in [queryParams keyEnumerator]){
|
||
if (counter == 0) {
|
||
separator = @"?";
|
||
} else {
|
||
separator = @"&";
|
||
}
|
||
id queryParam = [queryParams valueForKey:key];
|
||
if(!queryParam) {
|
||
continue;
|
||
}
|
||
NSString *safeKey = {{classPrefix}}PercentEscapedStringFromString(key);
|
||
if ([queryParam isKindOfClass:[NSString class]]){
|
||
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, safeKey, {{classPrefix}}PercentEscapedStringFromString(queryParam)]];
|
||
|
||
} else if ([queryParam isKindOfClass:[{{classPrefix}}QueryParamCollection class]]){
|
||
{{classPrefix}}QueryParamCollection * coll = ({{classPrefix}}QueryParamCollection*) queryParam;
|
||
NSArray* values = [coll values];
|
||
NSString* format = [coll format];
|
||
|
||
if([format isEqualToString:@"multi"]) {
|
||
for(id obj in values) {
|
||
if (counter > 0) {
|
||
separator = @"&";
|
||
}
|
||
NSString * safeValue = {{classPrefix}}PercentEscapedStringFromString([NSString stringWithFormat:@"%@",obj]);
|
||
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, safeKey, safeValue]];
|
||
counter += 1;
|
||
}
|
||
continue;
|
||
}
|
||
NSString * separatorStyle = separatorStyles[format];
|
||
NSString * safeValue = {{classPrefix}}PercentEscapedStringFromString([values componentsJoinedByString:separatorStyle]);
|
||
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, safeKey, safeValue]];
|
||
} else {
|
||
NSString * safeValue = {{classPrefix}}PercentEscapedStringFromString([NSString stringWithFormat:@"%@",queryParam]);
|
||
[requestUrl appendString:[NSString stringWithFormat:@"%@%@=%@", separator, safeKey, safeValue]];
|
||
}
|
||
counter += 1;
|
||
}
|
||
return requestUrl;
|
||
}
|
||
|
||
/**
|
||
* Update header and query params based on authentication settings
|
||
*/
|
||
- (void) updateHeaderParams:(NSDictionary *__autoreleasing *)headers
|
||
queryParams:(NSDictionary *__autoreleasing *)querys
|
||
WithAuthSettings:(NSArray *)authSettings {
|
||
|
||
if ([authSettings count] == 0) {
|
||
return;
|
||
}
|
||
|
||
NSMutableDictionary *headersWithAuth = [NSMutableDictionary dictionaryWithDictionary:*headers];
|
||
NSMutableDictionary *querysWithAuth = [NSMutableDictionary dictionaryWithDictionary:*querys];
|
||
|
||
NSDictionary* configurationAuthSettings = [[self configuration] authSettings];
|
||
for (NSString *auth in authSettings) {
|
||
NSDictionary *authSetting = configurationAuthSettings[auth];
|
||
if(!authSetting) { // auth setting is set only if the key is non-empty
|
||
continue;
|
||
}
|
||
NSString *type = authSetting[@"in"];
|
||
NSString *key = authSetting[@"key"];
|
||
NSString *value = authSetting[@"value"];
|
||
if ([type isEqualToString:@"header"] && [key length] > 0 ) {
|
||
headersWithAuth[key] = value;
|
||
} else if ([type isEqualToString:@"query"] && [key length] != 0) {
|
||
querysWithAuth[key] = value;
|
||
}
|
||
}
|
||
|
||
*headers = [NSDictionary dictionaryWithDictionary:headersWithAuth];
|
||
*querys = [NSDictionary dictionaryWithDictionary:querysWithAuth];
|
||
}
|
||
|
||
- (AFSecurityPolicy *) customSecurityPolicy {
|
||
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
|
||
|
||
{{classPrefix}}Configuration *config = [self configuration];
|
||
|
||
if (config.sslCaCert) {
|
||
NSData *certData = [NSData dataWithContentsOfFile:config.sslCaCert];
|
||
[securityPolicy setPinnedCertificates:@[certData]];
|
||
}
|
||
|
||
if (config.verifySSL) {
|
||
[securityPolicy setAllowInvalidCertificates:NO];
|
||
}
|
||
else {
|
||
[securityPolicy setAllowInvalidCertificates:YES];
|
||
[securityPolicy setValidatesDomainName:NO];
|
||
}
|
||
|
||
return securityPolicy;
|
||
}
|
||
|
||
- ({{classPrefix}}Configuration*) configuration {
|
||
return [{{classPrefix}}Configuration sharedConfig];
|
||
}
|
||
|
||
@end
|