Skip to content

Commit

Permalink
Enables user to access response from original request when the reques…
Browse files Browse the repository at this point in the history
…t is redirect by using a 302
  • Loading branch information
simonmitchell committed Nov 12, 2015
1 parent b899b95 commit 6409c2d
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 2 deletions.
2 changes: 2 additions & 0 deletions ThunderRequest.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
B1177EFD1BBAF24100372D4D /* TSCErrorRecoveryOption.h in Headers */ = {isa = PBXBuildFile; fileRef = 49B77E081B36A7BF001475CE /* TSCErrorRecoveryOption.h */; settings = {ATTRIBUTES = (Public, ); }; };
B1177EFE1BBAF24500372D4D /* TSCRequestDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 49B77E0A1B36A7BF001475CE /* TSCRequestDefines.h */; settings = {ATTRIBUTES = (Public, ); }; };
B16743E81BA6C4E000352C68 /* TSCOAuth2Manager.h in Headers */ = {isa = PBXBuildFile; fileRef = B16743E61BA6C4E000352C68 /* TSCOAuth2Manager.h */; settings = {ATTRIBUTES = (Public, ); }; };
B17F34601BF4A59000F3586C /* NSDictionary+URLEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = B1FC231C1BC6A6EA00E67C8D /* NSDictionary+URLEncoding.m */; };
B19894891BEA3B7C00E96DA3 /* NSURLSession+Synchronous.h in Headers */ = {isa = PBXBuildFile; fileRef = B19894871BEA3B7C00E96DA3 /* NSURLSession+Synchronous.h */; };
B198948A1BEA3B7C00E96DA3 /* NSURLSession+Synchronous.h in Headers */ = {isa = PBXBuildFile; fileRef = B19894871BEA3B7C00E96DA3 /* NSURLSession+Synchronous.h */; };
B198948B1BEA3B7C00E96DA3 /* NSURLSession+Synchronous.m in Sources */ = {isa = PBXBuildFile; fileRef = B19894881BEA3B7C00E96DA3 /* NSURLSession+Synchronous.m */; };
Expand Down Expand Up @@ -468,6 +469,7 @@
B1177EF41BBAF21F00372D4D /* TSCRequestResponse.m in Sources */,
B1177EF51BBAF21F00372D4D /* TSCErrorRecoveryAttempter.m in Sources */,
B198948C1BEA3B7C00E96DA3 /* NSURLSession+Synchronous.m in Sources */,
B17F34601BF4A59000F3586C /* NSDictionary+URLEncoding.m in Sources */,
B1177EF61BBAF21F00372D4D /* TSCErrorRecoveryOption.m in Sources */,
B1177EF71BBAF21F00372D4D /* TSCRequestDefines.m in Sources */,
);
Expand Down
2 changes: 2 additions & 0 deletions ThunderRequest/NSDictionary+URLEncoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@

- (NSString *)urlEncodedFormString;

+ (instancetype)dictionaryWithURLEncodedString:(NSString *)string;

@end
22 changes: 22 additions & 0 deletions ThunderRequest/NSDictionary+URLEncoding.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,28 @@ @implementation NSDictionary (URLEncoding)
return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
}

+ (instancetype)dictionaryWithURLEncodedString:(NSString *)string
{
NSString *queryString = [[NSURL URLWithString:string] query];

NSMutableDictionary *result = [[[self alloc] init] mutableCopy];

NSArray *parameters = [queryString componentsSeparatedByString:@"&"];

for (NSString *parameter in parameters)
{
NSArray *parts = [parameter componentsSeparatedByString:@"="];
NSString *key = [[parts objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([parts count] > 1)
{
id value = [[parts objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[result setObject:value forKey:key];
}
}

return result;
}

- (NSString *)urlEncodedFormString
{
if (self.allKeys.count == 0) {
Expand Down
51 changes: 49 additions & 2 deletions ThunderRequest/TSCRequestController.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,36 @@
#import "NSURLSession+Synchronous.h"
#import "NSThread+Blocks.h"
#import "TSCOAuth2Credential.h"
#import <objc/runtime.h>

static NSString * const TSCQueuedRequestKey = @"TSC_REQUEST";
static NSString * const TSCQueuedCompletionKey = @"TSC_REQUEST_COMPLETION";

@interface TSCRequest (TaskIdentifier)

/**
@abstract Can be used to get the task back for the request
*/
@property (nonatomic, assign) NSUInteger taskIdentifier;

@end

@implementation TSCRequest (TaskIdentifier)

static char taskIdentifierKey;

- (NSUInteger)taskIdentifier
{
return [objc_getAssociatedObject(self, &taskIdentifierKey) integerValue];
}

- (void)setTaskIdentifier:(NSUInteger)taskIdentifier
{
objc_setAssociatedObject(self, &taskIdentifierKey, @(taskIdentifier), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

typedef void (^TSCOAuth2CheckCompletion) (BOOL authenticated, NSError *authError, BOOL needsQueueing);

@interface TSCRequestController () <NSURLSessionDownloadDelegate, NSURLSessionTaskDelegate>
Expand Down Expand Up @@ -70,6 +96,12 @@ @interface TSCRequestController () <NSURLSessionDownloadDelegate, NSURLSessionTa
*/
@property (nonatomic, strong) NSMutableArray *authQueuedRequests;

/**
@abstract A dictionary representing any re-direct responses provided with a redirect request
@discussion These will be added onto the TSCRequestResponse object of the re-directed request, they are stored in this request under the request object itself
*/
@property (nonatomic, strong) NSMutableDictionary *redirectResponses;

@end

@implementation TSCRequestController
Expand Down Expand Up @@ -98,6 +130,7 @@ - (instancetype)init
self.sharedRequestHeaders = [NSMutableDictionary dictionary];

self.authQueuedRequests = [NSMutableArray new];
self.redirectResponses = [NSMutableDictionary new];
}
return self;
}
Expand Down Expand Up @@ -307,6 +340,12 @@ - (void)uploadBodyParams:(nullable NSDictionary *)bodyParams toPath:(nonnull NSS
- (void)TSC_fireRequestCompletionWithData:(NSData *)data response:(NSURLResponse *)response error:(NSError *)error request:(TSCRequest *)request completion:(TSCRequestCompletionHandler)completion onThread:(NSThread *)scheduleThread
{
TSCRequestResponse *requestResponse = [[TSCRequestResponse alloc] initWithResponse:response data:data];

if (request.taskIdentifier && self.redirectResponses[@(request.taskIdentifier)]) {
requestResponse.redirectResponse = self.redirectResponses[@(request.taskIdentifier)];
[self.redirectResponses removeObjectForKey:@(request.taskIdentifier)];
}

//Notify of response
[[NSNotificationCenter defaultCenter] postNotificationName:@"TSCRequestDidReceiveResponse" object:requestResponse];

Expand Down Expand Up @@ -558,12 +597,14 @@ - (void)scheduleRequest:(TSCRequest *)request completion:(TSCRequestCompletionHa
} else {

NSThread *currentThread = [NSThread currentThread];
[[welf.defaultSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSURLSessionDataTask *dataTask = [welf.defaultSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

[welf TSC_fireRequestCompletionWithData:data response:response error:error request:request completion:completion onThread:currentThread];

}] resume];
}];

request.taskIdentifier = dataTask.taskIdentifier;
[dataTask resume];
}
}];
}
Expand All @@ -580,6 +621,12 @@ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didRece
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}

- (void)URLSession:(NSURLSession *)session task:(nonnull NSURLSessionTask *)task willPerformHTTPRedirection:(nonnull NSHTTPURLResponse *)response newRequest:(nonnull NSURLRequest *)request completionHandler:(nonnull void (^)(NSURLRequest * _Nullable))completionHandler
{
self.redirectResponses[@(task.taskIdentifier)] = response;
completionHandler(request);
}

#pragma mark - NSURLSessionDownloadDelegate

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
Expand Down
6 changes: 6 additions & 0 deletions ThunderRequest/TSCRequestResponse.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
*/
@property (nonatomic, strong, nullable) NSObject *object;

/**
@abstract The redirect response
@discussion If the request was redirected, this represents the NSHTTPURLResponse object for the original request
*/
@property (nonatomic, strong, nullable) NSHTTPURLResponse *redirectResponse;

/**
Initialises a new response object using the response given by NSURLSession
*/
Expand Down

0 comments on commit 6409c2d

Please sign in to comment.