snod
snod

Reputation: 2443

Getting the reponse body of a 302 HTTP redirect with NSURLConnection

I'm sending a HTTP GET request to an URL using NSURLConnection with the delegate. The request gets redirected with a HTTP 302 and the new request is performed and the data retrieved.

The problem is that I don't want the body of the redirected HTTP request but the content of the original redirect response.

I've implemented - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response which is called with the redirectRepsonse but connection:didReceiveData is not called until the new redirected request returns.

I've found no solution so far except of using a CFNetwork based approach.

Update: I've created a sample project with the problem for you to play with: https://github.com/snod/302RedirectTest

Any ideas?

Upvotes: 1

Views: 3154

Answers (2)

F.A. Botic
F.A. Botic

Reputation: 101

From the test project you created it looks like it should run fine ViewController.m has all methods required, let me elaborate further with clear examples which are already partially implemented in your test project.

    //This method can be used to intercept the redirect
- (NSURLRequest *)connection:(NSURLConnection *)connection
            willSendRequest:(NSURLRequest *)request
            redirectResponse:(NSURLResponse *)redirectResponse {
    if(redirectResponse != nil && redirectResponse) {
        //Cast NSURLResponse to NSHTTPURLResponse
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) redirectResponse;
        //Verify if statusCode == MOVED_TEMPORARILY (302)
        if((long)[httpResponse statusCode] == 302){
            NSDictionary* headers = [(NSHTTPURLResponse *)httpResponse allHeaderFields];
            NSString *redirectLocation;
            //Find redirect URL
            for (NSString *header in headers) {
                if([header isEqualToString:@"Location"]){
                    redirectLocation = headers[header];
                    break;
                }
            }
            //return nil without following the redirect URL automatically 
            return nil;
            
        } else {
            //return without modifiying request
            return request;
        }
    } else {
        //return without modifiying request
        return request;
    }
    //returnd without modifiying request
    return request;
}

- (void)connection:(NSURLConnection *)aConnection
    didReceiveResponse:(NSHTTPURLResponse *)aResponse
{
    if ([aResponse statusCode] == 302) {
        //do whatever you need to do with the response, the redirectURL is in the header "Location"
        //for example show an UIAlertController to the user with a button which can then redirect to the URL
    }
}

Upvotes: 0

Ken Thomases
Ken Thomases

Reputation: 90521

From the docs of -connection:willSendRequest:redirectResponse::

To receive the body of the redirect response itself, return nil to cancel the redirect. The connection continues to process, eventually sending your delegate a connectionDidFinishLoading or connection:didFailLoadingWithError: message, as appropriate.

Upvotes: 2

Related Questions