2828#import " RNCachingURLProtocol.h"
2929#import " Reachability.h"
3030
31+ @interface NSURLRequest (MutableCopyWorkaround)
32+
33+ - (id ) mutableCopyWorkaround ;
34+
35+ @end
36+
3137@interface RNCachedData : NSObject <NSCoding >
3238@property (nonatomic , readwrite , strong ) NSData *data;
3339@property (nonatomic , readwrite , strong ) NSURLResponse *response;
3440@property (nonatomic , readwrite , strong ) NSURLRequest *redirectRequest;
3541@end
3642
3743static NSString *RNCachingURLHeader = @" X-RNCache" ;
38- static NSString *RNCachingURLRedirectableHeader = @" X-RNCache-Redirectable" ;
39- static NSString *RNCachingURLRedirectedHeader = @" X-RNCache-Redirected" ;
4044
4145@interface RNCachingURLProtocol () // <NSURLConnectionDelegate, NSURLConnectionDataDelegate> iOS5-only
42- @property (nonatomic , readwrite , strong ) NSURLRequest *request;
4346@property (nonatomic , readwrite , strong ) NSURLConnection *connection;
4447@property (nonatomic , readwrite , strong ) NSMutableData *data;
4548@property (nonatomic , readwrite , strong ) NSURLResponse *response;
4649- (void )appendData : (NSData *)newData ;
4750@end
4851
4952@implementation RNCachingURLProtocol
50- @synthesize request = request_;
5153@synthesize connection = connection_;
5254@synthesize data = data_;
5355@synthesize response = response_;
5456
5557
5658+ (BOOL )canInitWithRequest : (NSURLRequest *)request
5759{
58- if (([[[request URL ] scheme ] isEqualToString: @" http" ] &&
59- [request valueForHTTPHeaderField: RNCachingURLHeader] == nil ) ||
60- ([request valueForHTTPHeaderField: RNCachingURLRedirectableHeader] &&
61- ([request valueForHTTPHeaderField: RNCachingURLRedirectedHeader] == nil ))) {
60+ if ([[[request URL ] scheme ] isEqualToString: @" http" ] &&
61+ ([request valueForHTTPHeaderField: RNCachingURLHeader] == nil )) {
6262 return YES ;
6363 }
6464 return NO ;
@@ -69,28 +69,6 @@ + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
6969 return request;
7070}
7171
72- - (id )initWithRequest : (NSURLRequest *)request
73- cachedResponse : (NSCachedURLResponse *)cachedResponse
74- client : (id <NSURLProtocolClient >)client
75- {
76- // Modify request so we don't loop
77- NSMutableURLRequest *myRequest = [request mutableCopy ];
78- [myRequest setValue: @" " forHTTPHeaderField: RNCachingURLHeader];
79-
80- if ([myRequest valueForHTTPHeaderField: RNCachingURLRedirectableHeader]) {
81- [myRequest setValue: @" " forHTTPHeaderField: RNCachingURLRedirectedHeader];
82- }
83-
84- self = [super initWithRequest: myRequest
85- cachedResponse: cachedResponse
86- client: client];
87-
88- if (self) {
89- [self setRequest: myRequest];
90- }
91- return self;
92- }
93-
9472- (NSString *)cachePathForRequest : (NSURLRequest *)aRequest
9573{
9674 // This stores in the Caches directory, which can be deleted when space is low, but we only use it for offline access
@@ -102,7 +80,9 @@ - (NSString *)cachePathForRequest:(NSURLRequest *)aRequest
10280- (void )startLoading
10381{
10482 if ([[Reachability reachabilityWithHostName: [[[self request ] URL ] host ]] currentReachabilityStatus ] != NotReachable) {
105- NSURLConnection *connection = [NSURLConnection connectionWithRequest: [self request ]
83+ NSMutableURLRequest *connectionRequest = [[self request ] mutableCopyWorkaround ];
84+ [connectionRequest setValue: @" " forHTTPHeaderField: RNCachingURLHeader];
85+ NSURLConnection *connection = [NSURLConnection connectionWithRequest: connectionRequest
10686 delegate: self ];
10787 [self setConnection: connection];
10888 }
@@ -135,20 +115,24 @@ - (void)stopLoading
135115
136116- (NSURLRequest *)connection : (NSURLConnection *)connection willSendRequest : (NSURLRequest *)request redirectResponse : (NSURLResponse *)response
137117{
138- NSMutableURLRequest *redirectableRequest = [request mutableCopy ];
139- // Thanks to Nick Dowell https://gist.github.com/1885821
118+ // Thanks to Nick Dowell https://gist.github.com/1885821
140119 if (response != nil ) {
141- [redirectableRequest setValue: @" "
142- forHTTPHeaderField: RNCachingURLRedirectableHeader];
120+ NSMutableURLRequest *redirectableRequest = [request mutableCopyWorkaround ];
121+ NSMutableDictionary *redirectableRequestAllHTTPHeaderFields = [[redirectableRequest allHTTPHeaderFields ] mutableCopy ];
122+ [redirectableRequestAllHTTPHeaderFields removeObjectForKey: RNCachingURLHeader];
123+ [redirectableRequest setAllHTTPHeaderFields: redirectableRequestAllHTTPHeaderFields];
124+
143125 NSString *cachePath = [self cachePathForRequest: [self request ]];
144126 RNCachedData *cache = [RNCachedData new ];
145127 [cache setResponse: response];
146128 [cache setData: [self data ]];
147129 [cache setRedirectRequest: redirectableRequest];
148130 [NSKeyedArchiver archiveRootObject: cache toFile: cachePath];
149131 [[self client ] URLProtocol: self wasRedirectedToRequest: redirectableRequest redirectResponse: response];
132+ return redirectableRequest;
133+ } else {
134+ return request;
150135 }
151- return redirectableRequest;
152136}
153137
154138- (void )connection : (NSURLConnection *)connection didReceiveData : (NSData *)data
@@ -162,6 +146,7 @@ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)err
162146 [[self client ] URLProtocol: self didFailWithError: error];
163147 [self setConnection: nil ];
164148 [self setData: nil ];
149+ [self setResponse: nil ];
165150}
166151
167152- (void )connection : (NSURLConnection *)connection didReceiveResponse : (NSURLResponse *)response
@@ -182,12 +167,13 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection
182167
183168 [self setConnection: nil ];
184169 [self setData: nil ];
170+ [self setResponse: nil ];
185171}
186172
187173- (void )appendData : (NSData *)newData
188174{
189175 if ([self data ] == nil ) {
190- [self setData: [[ NSMutableData alloc ] initWithData: newData]];
176+ [self setData: [newData mutableCopy ]];
191177 }
192178 else {
193179 [[self data ] appendData: newData];
@@ -224,4 +210,16 @@ - (id)initWithCoder:(NSCoder *)aDecoder
224210 return self;
225211}
226212
213+ @end
214+
215+ @implementation NSURLRequest (MutableCopyWorkaround)
216+
217+ - (id ) mutableCopyWorkaround {
218+ NSMutableURLRequest *mutableURLRequest = [[NSMutableURLRequest alloc ] initWithURL: [self URL ]
219+ cachePolicy: [self cachePolicy ]
220+ timeoutInterval: [self timeoutInterval ]];
221+ [mutableURLRequest setAllHTTPHeaderFields: [self allHTTPHeaderFields ]];
222+ return mutableURLRequest;
223+ }
224+
227225@end
0 commit comments