Search code examples
iosnsurlconnectionnsurlsessionnsurlrequestnsurlsessiondownloadtask

NSURLSessionDownloadTask results in 404 status when server issues a redirect


I am trying to download an image in Objective C from a CDN that serves images. This works fine if the image URL is the same as the URL that was requested. But some images will result in a redirect to a different URL (even a different domain). For example, this might be the request URL but then the CDN will redirect to the second URL.

If viewing this in a browser or other context, it works fine (the URL gets updated, but the image is shown correctly). But when trying to download it using an NSURLSessionDownloadTask, it results in a 404 status code.

Here is the code I am using to perform the download. The code does work if the image is not redirected (the URL of the image that is downloaded is the same as the image URL that was requested). But otherwise, if the server does perform any redirection, this results in a 404 status.

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
configuration.URLCache = nil;
configuration.timeoutIntervalForRequest = 5 * 60;
        
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:nil delegateQueue:nil];

NSURLRequest *request = [NSURLRequest requestWithURL:key.url];
            
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NSInteger statusCode = 0;
    NSHTTPURLResponse *httpResponse = nil;
    if ([response isKindOfClass:NSHTTPURLResponse.class]) {
        httpResponse = (NSHTTPURLResponse *)response;
        statusCode = httpResponse.statusCode;
    } else {
        statusCode = error.code;
    }

    // the status code is 404 when the server issues a redirect
}];

[task resume];

Does anyone know what I could do to get this to work? If I request an image from URL1 but it is served back at URL2, then I would just like to do the download anyway. It doesn't matter if the server redirects to a different URL or not, I would still like to get the image downloaded.


Solution

  • Your code here looks fine to me, other than me being a little confused about why you're using a download task for a thumbnail (which is presumably tiny, and probably doesn't need to be persisted to disk).

    NSURLSession automatically follows redirects unless you specifically create a delegate method on the session delegate that overrides that behavior.

    Besides, a redirect always involves a status code in the 3xx range, not a 404, regardless of any NSURLSession configuration. There's no plausible way to get a 404 unless the URL genuinely points to nothing.

    I can't tell you what's wrong on the server side, but either A. the URL you're sending is legitimately bad, B. it redirects to a URL for a resource that doesn't exist, or C. it redirects in a loop.

    To debug it, I would start by adding a delegate with a handler method for redirects, so that you can then log the redirects as they happen. That should make it way easier to figure out what's actually going on.

    See the documentation for the URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler: method for details:

    https://developer.apple.com/documentation/foundation/nsurlsessiontaskdelegate/1411626-urlsession

    but at a high level, log task.currentRequest.URL and newRequest.URL (or whatever you name that parameter), then call the completion handler with the new request.