Skip to content

Commit 7e1f0a0

Browse files
author
hborders
committed
Simplified the request state machine, fixed the leak.
I suspected that swapping the request object in init was a no-no, so I thought I'd rework the logic to modify the request before creating the connection instead. That proved to work. I still had to workaround a leak associated with -[NSMutableURLRequest mutableCopy], but that was very easy.
1 parent 3208ddf commit 7e1f0a0

File tree

1 file changed

+35
-37
lines changed

1 file changed

+35
-37
lines changed

RNCachingURLProtocol.m

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,37 +28,37 @@
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

3743
static 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

Comments
 (0)