From 192ab663b76dd8e640915c0670830c2de557804f Mon Sep 17 00:00:00 2001 From: Howard Yeh Date: Wed, 27 Apr 2016 14:39:10 -0700 Subject: [PATCH] Fix 302 ImageLoader caching problem on iOS Summary: + Fixes https://github.com/facebook/react-native/issues/5616 + Bug RNPlay Demo: https://rnplay.org/apps/Eg2goQ Test demo loads a Tumblr avatar image using a URL that 301 to a CDN. Try to edit and save the file to trigger image reloads. The 302 image request succeeds the first time: screen shot 2016-04-27 at 9 37 03 am But it fails for subsequent loads. You should see: screen shot 2016-04-27 at 9 37 22 am + The first image is a 302, only succeeds to load the first time. + The second image in the column adds a nonce as request parameter to render caching ineffective (but still a 302), and the problem doesn't occur. + The last image is the canonical url location (200). Although NSURLSession hand Closes https://github.com/facebook/react-native/pull/7262 Differential Revision: D3231702 Pulled By: javache fb-gh-sync-id: 364fcf9819188c63310768411d49e6431b2a01d3 fbshipit-source-id: 364fcf9819188c63310768411d49e6431b2a01d3 --- Libraries/Image/RCTImageLoader.m | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Libraries/Image/RCTImageLoader.m b/Libraries/Image/RCTImageLoader.m index fe83fdbb5..8349a2e2b 100644 --- a/Libraries/Image/RCTImageLoader.m +++ b/Libraries/Image/RCTImageLoader.m @@ -371,7 +371,24 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, // Check for cached response before reloading // TODO: move URL cache out of RCTImageLoader into its own module NSCachedURLResponse *cachedResponse = [_URLCache cachedResponseForRequest:request]; - if (cachedResponse) { + + while (cachedResponse) { + if ([cachedResponse.response isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)cachedResponse.response; + if (httpResponse.statusCode == 301 || httpResponse.statusCode == 302) { + NSString *location = httpResponse.allHeaderFields[@"Location"]; + if (location == nil) { + completionHandler(RCTErrorWithMessage(@"Image redirect without location"), nil); + return; + } + + NSURL *redirectURL = [NSURL URLWithString: location]; + request = [NSURLRequest requestWithURL: redirectURL]; + cachedResponse = [_URLCache cachedResponseForRequest:request]; + continue; + } + } + processResponse(cachedResponse.response, cachedResponse.data, nil); return; }