Created
February 28, 2017 14:26
-
-
Save sclark39/6b03820eba8a26ace6bb97fbccd121a9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. | |
Licensed under the Apache License, Version 2.0 (the "License"). | |
You may not use this file except in compliance with the License. | |
A copy of the License is located at | |
http://aws.amazon.com/apache2.0 | |
or in the "license" file accompanying this file. This file is distributed | |
on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | |
express or implied. See the License for the specific language governing | |
permissions and limitations under the License. | |
*/ | |
#import "WOMAPIGatewayClient.h" | |
#import <AWSCore/AWSCore.h> | |
#import <AWSCore/AWSSignature.h> | |
#import <AWSCore/AWSSynchronizedMutableDictionary.h> | |
NSString *const AWSAPIGatewayErrorDomain = @"com.amazonaws.AWSAPIGatewayErrorDomain"; | |
NSString *const AWSAPIGatewayErrorHTTPBodyKey = @"HTTPBody"; | |
NSString *const AWSAPIGatewayErrorHTTPHeaderFieldsKey = @"HTTPHeaderFields"; | |
static NSString *const AWSAPIGatewayAPIKeyHeader = @"x-api-key"; | |
static NSString *const AWSAPIGatewaySDKVersion = @"2.5.1"; | |
static NSString *const AWSAPIGatewayEndpoint = @"https://........................"; | |
static int defaultChunkSize = 1024; | |
@interface AWSAPIGatewayClient() | |
// Networking | |
@property (nonatomic, strong) NSURLSession *session; | |
// For requests | |
@property (nonatomic, strong) NSURL *baseURL; | |
// For responses | |
@property (nonatomic, strong) NSDictionary *HTTPHeaderFields; | |
@property (nonatomic, assign) NSInteger HTTPStatusCode; | |
- (NSURL *)requestURL:(NSString *)URLString query:(NSDictionary *)query URLPathComponentsDictionary:(NSDictionary * _Nullable)URLPathComponentsDictionary; | |
@end | |
@interface WOMAPIGatewayClient() | |
@property (nonatomic, strong) AWSServiceConfiguration *configuration; | |
@end | |
@interface AWSServiceConfiguration() | |
@property (nonatomic, strong) AWSEndpoint *endpoint; | |
@end | |
@implementation WOMAPIGatewayClient | |
static NSString *const AWSInfoClientKey = @"WOMAPIGatewayClient"; | |
@synthesize configuration = _configuration; | |
static AWSSynchronizedMutableDictionary *_serviceClients = nil; | |
+ (instancetype)defaultClient { | |
AWSServiceConfiguration *serviceConfiguration = nil; | |
AWSServiceInfo *serviceInfo = [[AWSInfo defaultAWSInfo] defaultServiceInfo:AWSInfoClientKey]; | |
if (serviceInfo) { | |
serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:serviceInfo.region | |
credentialsProvider:serviceInfo.cognitoCredentialsProvider]; | |
} else if ([AWSServiceManager defaultServiceManager].defaultServiceConfiguration) { | |
serviceConfiguration = AWSServiceManager.defaultServiceManager.defaultServiceConfiguration; | |
} else { | |
serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUnknown | |
credentialsProvider:nil]; | |
} | |
static WOMAPIGatewayClient *_defaultClient = nil; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
_defaultClient = [[WOMAPIGatewayClient alloc] initWithConfiguration:serviceConfiguration]; | |
}); | |
return _defaultClient; | |
} | |
+ (void)registerClientWithConfiguration:(AWSServiceConfiguration *)configuration forKey:(NSString *)key { | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
_serviceClients = [AWSSynchronizedMutableDictionary new]; | |
}); | |
[_serviceClients setObject:[[WOMAPIGatewayClient alloc] initWithConfiguration:configuration] | |
forKey:key]; | |
} | |
+ (instancetype)clientForKey:(NSString *)key { | |
@synchronized(self) { | |
WOMAPIGatewayClient *serviceClient = [_serviceClients objectForKey:key]; | |
if (serviceClient) { | |
return serviceClient; | |
} | |
AWSServiceInfo *serviceInfo = [[AWSInfo defaultAWSInfo] serviceInfo:AWSInfoClientKey | |
forKey:key]; | |
if (serviceInfo) { | |
AWSServiceConfiguration *serviceConfiguration = [[AWSServiceConfiguration alloc] initWithRegion:serviceInfo.region | |
credentialsProvider:serviceInfo.cognitoCredentialsProvider]; | |
[WOMAPIGatewayClient registerClientWithConfiguration:serviceConfiguration | |
forKey:key]; | |
} | |
return [_serviceClients objectForKey:key]; | |
} | |
} | |
+ (void)removeClientForKey:(NSString *)key { | |
[_serviceClients removeObjectForKey:key]; | |
} | |
- (instancetype)init { | |
@throw [NSException exceptionWithName:NSInternalInconsistencyException | |
reason:@"`- init` is not a valid initializer. Use `+ defaultClient` or `+ clientForKey:` instead." | |
userInfo:nil]; | |
return nil; | |
} | |
- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)configuration { | |
if (self = [super init]) { | |
_configuration = [configuration copy]; | |
NSString *URLString = AWSAPIGatewayEndpoint | |
if ([URLString hasSuffix:@"/"]) { | |
URLString = [URLString substringToIndex:[URLString length] - 1]; | |
} | |
_configuration.endpoint = [[AWSEndpoint alloc] initWithRegion:_configuration.regionType | |
service:AWSServiceAPIGateway | |
URL:[NSURL URLWithString:URLString]]; | |
AWSSignatureV4Signer *signer = [[AWSSignatureV4Signer alloc] initWithCredentialsProvider:_configuration.credentialsProvider | |
endpoint:_configuration.endpoint]; | |
_configuration.baseURL = _configuration.endpoint.URL; | |
_configuration.requestInterceptors = @[[AWSNetworkingRequestInterceptor new], signer]; | |
} | |
return self; | |
} | |
- (AWSTask *)invokeHTTPRequest:(NSString *)HTTPMethod | |
URLString:(NSString *)URLString | |
pathParameters:(NSDictionary * _Nullable)pathParameters | |
queryParameters:(NSDictionary *)queryParameters | |
headerParameters:(NSDictionary *)headerParameters | |
body:(NSDictionary * _Nullable)body | |
{ | |
NSURL *URL = [self requestURL:URLString query:queryParameters URLPathComponentsDictionary:pathParameters]; | |
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; | |
request.HTTPMethod = HTTPMethod; | |
request.allHTTPHeaderFields = headerParameters; | |
if (self.APIKey) { | |
[request addValue:self.APIKey forHTTPHeaderField:AWSAPIGatewayAPIKeyHeader]; | |
} | |
NSError *error = nil; | |
if (body != nil) { | |
request.HTTPBody = [NSJSONSerialization dataWithJSONObject:body | |
options:0 | |
error:&error]; | |
if (!request.HTTPBody) { | |
AWSLogError(@"Failed to serialize a request body. %@", error); | |
} | |
} | |
// Refreshes credentials if necessary | |
AWSTask *task = [AWSTask taskWithResult:nil]; | |
task = [task continueWithSuccessBlock:^id(AWSTask *task) { | |
id signer = [self.configuration.requestInterceptors lastObject]; | |
if (signer) { | |
if ([signer respondsToSelector:@selector(credentialsProvider)]) { | |
id<AWSCredentialsProvider> credentialsProvider = [signer performSelector:@selector(credentialsProvider)]; | |
return [credentialsProvider credentials]; | |
} | |
} | |
return nil; | |
}]; | |
// Signs the request | |
for (id<AWSNetworkingRequestInterceptor> interceptor in self.configuration.requestInterceptors) { | |
task = [task continueWithSuccessBlock:^id(AWSTask *task) { | |
return [interceptor interceptRequest:request]; | |
}]; | |
} | |
return [task continueWithSuccessBlock:^id(AWSTask *task) { | |
AWSTaskCompletionSource *completionSource = [AWSTaskCompletionSource new]; | |
void (^completionHandler)(NSData *data, NSURLResponse *response, NSError *error) = ^(NSData *data, NSURLResponse *response, NSError *error) { | |
// Networking errors | |
if (error) { | |
[completionSource setError:error]; | |
return; | |
} | |
// Serializes the HTTP body | |
id JSONObject = nil; | |
if (data && [data length] > 0) { | |
JSONObject = [NSJSONSerialization JSONObjectWithData:data | |
options:NSJSONReadingAllowFragments | |
error:&error]; | |
if (!JSONObject) { | |
NSString *bodyString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; | |
if ([bodyString length] > 0) { | |
AWSLogError(@"The body is not in JSON format. Body: %@\nError: %@", bodyString, error); | |
} | |
[completionSource setError:error]; | |
return; | |
} | |
} | |
// Handles developer defined errors | |
NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)response; | |
NSDictionary *HTTPHeaderFields = HTTPResponse.allHeaderFields; | |
NSInteger HTTPStatusCode = HTTPResponse.statusCode; | |
if (HTTPStatusCode/100 == 4 || HTTPStatusCode/100 == 5) { | |
NSMutableDictionary *userInfo = [NSMutableDictionary new]; | |
if (JSONObject) { | |
userInfo[AWSAPIGatewayErrorHTTPBodyKey] = JSONObject; | |
} | |
if (HTTPHeaderFields) { | |
userInfo[AWSAPIGatewayErrorHTTPHeaderFieldsKey] = HTTPHeaderFields; | |
} | |
if (HTTPStatusCode/100 == 4) { | |
NSError *clientError = [NSError errorWithDomain:AWSAPIGatewayErrorDomain | |
code:AWSAPIGatewayErrorTypeClient | |
userInfo:userInfo]; | |
[completionSource setError:clientError]; | |
} | |
if (HTTPStatusCode/100 == 5) { | |
NSError *clientError = [NSError errorWithDomain:AWSAPIGatewayErrorDomain | |
code:AWSAPIGatewayErrorTypeService | |
userInfo:userInfo]; | |
[completionSource setError:clientError]; | |
} | |
return; | |
} | |
// Maps a serialized JSON object to an Objective-C object | |
if (JSONObject) | |
{ | |
[completionSource setResult:JSONObject]; | |
} else { | |
[completionSource setResult:nil]; | |
} | |
}; | |
NSURLSessionDataTask *sessionTask = [self.session dataTaskWithRequest:request | |
completionHandler:completionHandler]; | |
[sessionTask resume]; | |
return completionSource.task; | |
}]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment