Ignore query params with SDWebImage
Asked Answered
W

5

9

I'm using SDWebImage to cache images in my app, however I recently ran into a problem where images that should be cached keep refreshing. Looking into it I found that the full image url from AWS is actually changing due to parameters tacked onto the end of the url. Every time I fetch the object that contains the image url, the image url returns with a dynamic "signature" and "expires" parameter (for security purposes). A different url so far as the image cache is concerned, but notice the same path to the image.

First fetch:

https://myapp.s3.amazonaws.com/path/image123.jpeg?AWSAccessKeyId=SOMEKEY&Signature=vrUFlMFEQ9fqQ%3D&Expires=1441702633

Fetch again 1 second later:

https://myapp.s3.amazonaws.com/path/image123.jpeg?AWSAccessKeyId=SOMEKEY&Signature=2mcMxUJLyJd7E%3D&Expires=1441703105

What's the best way to handle this situation? Sure would be awesome if SDWebImage had an option to ignore query params beyond the path to the file.

Washer answered 8/9, 2014 at 9:26 Comment(0)
H
12

SDWebImage has a method that allows for using a custom key, which helps in this case as AWS changes the query every time it's called.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary    *)launchOptions
{
    SDWebImageManager.sharedManager.cacheKeyFilter = ^(NSURL *url) {
        url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path];
        return [url absoluteString];
    };

    // Your app init code...
    return YES;
}

For more reading: SDWebImage | Using the cache key filter

Hamburger answered 9/9, 2014 at 3:44 Comment(0)
W
6

@John 's answer is very good, but I met sometimes crashed.

below is more stable version.

SDWebImageManager.sharedManager.cacheKeyFilter = ^(NSURL *url) {
    if( [[url absoluteString] isEqualToString:@""] ){
        return @"";
    }
    url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path];
    return [url absoluteString];
};

This additional code checks if url is valid. [[NSURL alloc] initWithString:@""] or something like this makes crashes.

Weekday answered 29/5, 2015 at 15:25 Comment(3)
Could you please explain your answer, even if it's going to explain similar stuff to the other answer it's useful for your answer to explain the code you've posted.Unmuzzle
@Unmuzzle [[NSURL alloc] initWithString:@""] or something like that crashed @Hamburger 's code.Weekday
Nice catch @SatoshiSuzuki.Hamburger
C
6

The answer for Swift language:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    ...............

    SDWebImageManager.sharedManager().cacheKeyFilter = { url in
        if url.absoluteString == "" {
            return ""
        }

        let newUrl = NSURL(scheme: url.scheme, host: url.host, path: url.path!)!
        return newUrl.absoluteString
    }

    return true
}
Cicala answered 23/11, 2015 at 7:11 Comment(0)
H
2

[NSURL initWithScheme: host: path:] is deprecated in iOS10. should use NSURLComponents instead.

my updated solution:

SDWebImageManager.sharedManager.cacheKeyFilter = ^NSString *(NSURL *url) {
     if([[url absoluteString] isEqualToString:@""]){
        return @"";
    }
    NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO];
    urlComponents.query = nil;
    return [[urlComponents URL] absoluteString];
};
Handsome answered 27/2, 2018 at 3:45 Comment(0)
S
2

iOS 14 || Swift 5

SDWebImageManager.shared.cacheKeyFilter = SDWebImageCacheKeyFilter { url in
    var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
    components?.query = nil

    print("SDWebImage Cache Key:", components?.url)

    return components?.url?.absoluteString ?? ""
}

So configure SDWebImageManager at launch & then whenever a url is supplied, it will be stripped of all it's query parameters to generate a common cache key identifier for SDWebImage cache logic to work properly again.

So something like:

https://bucket.s3.us-east-1.amazonaws.com/public/someAsset.ext?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=TILT&X-Amz-Date=20210602T113954Z&X-Amz-Expires=17999&X-Amz-SignedHeaders=host&X-Amz-Security-Token=TILT&X-Amz-Signature=TILT

will have the cache key:

https://bucket.s3.us-east-1.amazonaws.com/public/someAsset.ext


NOTE: Pay attention to the final url. If the url is dependent on its query parameters for a dynamic output then obviously you will need to modify the logic in SDWebImageCacheKeyFilter to fit your requirement.

Salsify answered 2/6, 2021 at 11:49 Comment(1)
Succinct, well written, and complete with detailed description and caveats. If I could upvote you a thousand times I would.Lefevre

© 2022 - 2025 — McMap. All rights reserved.