mirror of
https://github.com/danog/Telegram.git
synced 2024-12-02 09:27:55 +01:00
230 lines
8.1 KiB
Objective-C
Executable File
230 lines
8.1 KiB
Objective-C
Executable File
//
|
|
// GDClient.m
|
|
// GDFileManagerExample
|
|
//
|
|
// Created by Graham Dennis on 26/01/13.
|
|
// Copyright (c) 2013 Graham Dennis. All rights reserved.
|
|
//
|
|
|
|
#import "GDHTTPClient.h"
|
|
#import "GDClientManager.h"
|
|
#import "GDClientCredential.h"
|
|
#import "GDAccessTokenClientCredential.h"
|
|
|
|
#import "GDHTTPOperation.h"
|
|
|
|
@interface GDHTTPClient ()
|
|
|
|
@property (nonatomic, readwrite) dispatch_queue_t isolationQueue;
|
|
@property (nonatomic, readwrite) dispatch_queue_t workQueue;
|
|
|
|
@end
|
|
|
|
NSString *const GDHTTPClientErrorDetailsKey = @"GDHTTPClientErrorDetails";
|
|
|
|
BOOL GDIsErrorPermanentlyFatal(NSError *error)
|
|
{
|
|
// Code based on GTMHTTPFetcher, which is under the Apache license
|
|
|
|
static dispatch_once_t onceToken;
|
|
static NSArray *retryErrors = nil;
|
|
dispatch_once(&onceToken, ^{
|
|
retryErrors = @[
|
|
[NSError errorWithDomain:GDHTTPStatusErrorDomain code:408 userInfo:nil], // Request timeout
|
|
[NSError errorWithDomain:GDHTTPStatusErrorDomain code:503 userInfo:nil], // Service unavailable
|
|
[NSError errorWithDomain:GDHTTPStatusErrorDomain code:504 userInfo:nil], // Request timeout
|
|
[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorTimedOut userInfo:nil],
|
|
[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorNetworkConnectionLost userInfo:nil],
|
|
[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCannotFindHost userInfo:nil]
|
|
];
|
|
});
|
|
|
|
for (NSError *retryError in retryErrors) {
|
|
if ([retryError.domain isEqualToString:error.domain]
|
|
&& retryError.code == error.code)
|
|
return NO;
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
|
|
@implementation GDHTTPClient
|
|
|
|
@synthesize available;
|
|
|
|
#if !OS_OBJECT_USE_OBJC
|
|
- (void)dealloc
|
|
{
|
|
if (self.isolationQueue) {
|
|
dispatch_release(self.isolationQueue);
|
|
self.isolationQueue = NULL;
|
|
}
|
|
if (self.workQueue) {
|
|
dispatch_release(self.workQueue);
|
|
self.workQueue = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
- (id)initWithBaseURL:(NSURL *)url
|
|
{
|
|
return [self initWithClientManager:nil credential:nil baseURL:url];
|
|
}
|
|
|
|
- (id)initWithClientManager:(GDClientManager *)clientManager
|
|
{
|
|
return [self initWithClientManager:clientManager userID:nil];
|
|
}
|
|
|
|
- (id)initWithClientManager:(GDClientManager *)clientManager userID:(NSString *)userID
|
|
{
|
|
GDClientCredential *credential = [clientManager credentialForUserID:userID];
|
|
|
|
return [self initWithClientManager:clientManager credential:credential];
|
|
}
|
|
|
|
- (id)initWithClientManager:(GDClientManager *)clientManager credential:(GDClientCredential *)credential
|
|
{
|
|
return [self initWithClientManager:clientManager credential:credential baseURL:nil];
|
|
}
|
|
|
|
- (id)initWithClientManager:(GDClientManager *)clientManager credential:(GDClientCredential *)credential baseURL:(NSURL *)baseURL
|
|
{
|
|
if (!baseURL) return nil;
|
|
|
|
if ((self = [super initWithBaseURL:baseURL])){
|
|
_clientManager = clientManager;
|
|
self.credential = credential;
|
|
self.requestsIgnoreCacheByDefault = YES;
|
|
|
|
NSString *label = [NSString stringWithFormat:@"%@.isolation.%p", [self class], self];
|
|
self.isolationQueue = dispatch_queue_create([label UTF8String], DISPATCH_QUEUE_SERIAL);
|
|
|
|
label = [NSString stringWithFormat:@"%@.work.%p", [self class], self];
|
|
self.workQueue = dispatch_queue_create([label UTF8String], DISPATCH_QUEUE_CONCURRENT);
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (NSString *)userID
|
|
{
|
|
return self.credential.userID;
|
|
}
|
|
|
|
- (void)enqueueHTTPRequestOperation:(AFHTTPRequestOperation *)operation
|
|
{
|
|
if (!operation) return;
|
|
|
|
// NSLog(@"Request: %@; %@", [operation request], [[operation request] allHTTPHeaderFields]);
|
|
|
|
[super enqueueHTTPRequestOperation:operation];
|
|
}
|
|
|
|
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters
|
|
{
|
|
NSMutableURLRequest *request = [super requestWithMethod:method path:path parameters:parameters];
|
|
|
|
if (self.requestsIgnoreCacheByDefault)
|
|
request.cachePolicy = NSURLRequestReloadIgnoringCacheData;
|
|
|
|
return request;
|
|
}
|
|
|
|
// FIXME: I need something equivalent to a bookmark to be able to handle files being renamed.
|
|
// FIXME: I also need to be able to handle JSON responses as errors to download operations when an AFJSONRequestOperation would otherwise be inappropriate.
|
|
// This is not needed by Google Drive, but might be needed by Dropbox.
|
|
// This is needed by Dropbox and Google Drive.
|
|
|
|
- (NSOperation *)enqueueOperationWithURLRequest:(NSMutableURLRequest *)urlRequest
|
|
requiresAuthentication:(BOOL)requiresAuthentication
|
|
success:(void (^)(AFHTTPRequestOperation *, id))success
|
|
failure:(void (^)(AFHTTPRequestOperation *, NSError *))failure
|
|
{
|
|
return [self enqueueOperationWithURLRequest:urlRequest requiresAuthentication:requiresAuthentication
|
|
shouldRetryBlock:NULL
|
|
success:success failure:failure
|
|
configureOperationBlock:NULL];
|
|
}
|
|
|
|
- (NSOperation *)enqueueOperationWithURLRequest:(NSMutableURLRequest *)urlRequest
|
|
requiresAuthentication:(BOOL)requiresAuthentication
|
|
shouldRetryBlock:(BOOL (^)(NSError *error))shouldRetryBlock
|
|
success:(void (^)(AFHTTPRequestOperation *, id))success failure:(void (^)(AFHTTPRequestOperation *, NSError *))failure
|
|
configureOperationBlock:(void (^)(AFHTTPRequestOperation *))configureOperationBlock
|
|
{
|
|
GDHTTPOperation *parentOperation = [[GDHTTPOperation alloc] initWithClient:self urlRequest:urlRequest success:success failure:failure];
|
|
parentOperation.shouldRetryAfterError = shouldRetryBlock;
|
|
parentOperation.requiresAuthentication = requiresAuthentication;
|
|
|
|
if (self.requestsIgnoreCacheByDefault) {
|
|
parentOperation.configureOperationBlock = ^(AFHTTPRequestOperation *requestOperation) {
|
|
[requestOperation setCacheResponseBlock:^NSCachedURLResponse *(__unused NSURLConnection *connection, __unused NSCachedURLResponse *cachedResponse) {
|
|
return nil;
|
|
}];
|
|
if (configureOperationBlock)
|
|
configureOperationBlock(requestOperation);
|
|
};
|
|
} else {
|
|
parentOperation.configureOperationBlock = configureOperationBlock;
|
|
}
|
|
|
|
[parentOperation start];
|
|
|
|
return parentOperation;
|
|
}
|
|
|
|
- (void)getAccessTokenWithSuccess:(void (^)(GDAccessTokenClientCredential *credential))__unused success failure:(void (^)(NSError *error))__unused failure
|
|
{
|
|
[self doesNotRecognizeSelector:_cmd];
|
|
}
|
|
|
|
- (BOOL)authorizeRequest:(NSMutableURLRequest *)__unused urlRequest
|
|
{
|
|
return YES;
|
|
}
|
|
|
|
- (BOOL)isAuthenticationFailureError:(NSError *)__unused error
|
|
{
|
|
return NO;
|
|
}
|
|
|
|
- (NSError *)httpErrorWithErrorDomain:(NSString *)domain fromAFNetworkingError:(NSError *)error
|
|
{
|
|
return [self httpErrorWithErrorDomain:domain fromAFNetworkingError:error errorDetails:nil];
|
|
}
|
|
|
|
|
|
- (NSError *)httpErrorWithErrorDomain:(NSString *)domain fromAFNetworkingError:(NSError *)error errorDetails:(id)errorDetails
|
|
{
|
|
NSError *httpError = nil;
|
|
if ([[error domain] isEqualToString:AFNetworkingErrorDomain] && [error code] == NSURLErrorBadServerResponse) {
|
|
NSURLResponse *response = [[error userInfo] objectForKey:@"AFNetworkingOperationFailingURLResponseErrorKey"];
|
|
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
|
NSMutableDictionary *userInfo = [NSMutableDictionary new];
|
|
userInfo[NSUnderlyingErrorKey] = error;
|
|
userInfo[NSURLErrorFailingURLErrorKey] = [response URL];
|
|
if (errorDetails) {
|
|
userInfo[GDHTTPClientErrorDetailsKey] = errorDetails;
|
|
}
|
|
|
|
httpError = [NSError errorWithDomain:domain
|
|
code:[(NSHTTPURLResponse *)response statusCode]
|
|
userInfo:errorDetails];
|
|
}
|
|
}
|
|
return httpError;
|
|
}
|
|
|
|
|
|
- (GDAPIToken *)apiToken
|
|
{
|
|
return self.credential.apiToken;
|
|
}
|
|
|
|
|
|
@end
|