Reputation: 26007
What I want to do:
When I make a GET
request to a URL, the response is a 302 HTTP response
, which means its a redirect. I know that there are multiple redirects(3 to 4) after my initial GET
request. I want to get the very last URL after multiple redirects happen. I am only able to receive the first redirect URL.
What I've tried, is answers on:
My code sniplet taken from the answers:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *URLString = @"URL";
NSDictionary *parameters = @{@"k1": @"v1", @"k2": @"v2"};
NSMutableURLRequest *request_orig = [manager.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:manager.baseURL] absoluteString] parameters:parameters error:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request_orig];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
//This is the first Redirect URL that I receive
NSLog(@"New redirect URL: %@",[[[operation response] URL] absoluteString]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(@"Failure: err: %@", error);
}];
[operation setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {
if (redirectResponse) {
NSMutableURLRequest *r = [request_orig mutableCopy]; // original request
[r setURL: [request URL]];
return r;
} else {
NSLog(@"redirecting to : %@", [request URL]);
return request;
}
}];
[manager.operationQueue addOperation:operation];
I am able to receive the first redirected URL but there is no 2nd or 3rd redirect after that. What should I do in order to let the redirects continue and only receive the URL for the last redirect that is made. I am novice in iOS dev. I'll appreciate your help. Thanks.
Upvotes: 0
Views: 1057
Reputation: 744
If you just want to follow all redirects, it is sufficient to keep returning the provided request and abort when data is starting to come through the connection.
I wrote this some time ago for OSX, but it should work on iOS (w/ ARC) without changes:
- (NSURL *)resolvedURLRedirectionsForURL:(NSURL *)aURL {
NSLog(@"Started w/ initial URL: '%@'", aURL);
NSURL *originalURL = aURL;
NSURL __block *resolvedURL = nil;
if (aURL) {
dispatch_semaphore_t __communicationLock = dispatch_semaphore_create(0);
NSURLRequest *resolveRequest = [NSURLRequest requestWithURL:originalURL
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:5. ];
AFHTTPRequestOperation *request = [[AFHTTPRequestOperation alloc] initWithRequest:resolveRequest];
[request setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {
NSLog(@"..request encountered redirection to: '%@'",request.URL);
if (redirectResponse)
resolvedURL = [request.URL copy];
return request;
}];
AFHTTPRequestOperation __weak *weakRequest = request;
[request setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
[weakRequest cancel];
}];
[request setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"..request successful! (result: %@)",responseObject);
dispatch_semaphore_signal(__communicationLock);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (operation.response.statusCode == 200)
NSLog(@"..request successful! (aborted)");
else
NSLog(@"..request failed! (error: %@)",error);
dispatch_semaphore_signal(__communicationLock);
}];
[request start];
dispatch_semaphore_wait(__communicationLock, DISPATCH_TIME_FOREVER);
}
NSLog(@"Resolved URL '%@' to '%@'",originalURL,resolvedURL);
return resolvedURL;
}
Note: Because of the semaphore it's not a good idea to run it on the main thread unaltered as it'll block the main runloop (and NSURLConnections hate that). Therefore it is better to dispatch the method call to a global queue.
Upvotes: 1