Skip to content
This repository was archived by the owner on Jul 22, 2020. It is now read-only.

Commit 0807239

Browse files
authored
[ITBL-4754] Fix an unhandled exception in response handling on network errors (#51)
1 parent e29a090 commit 0807239

File tree

2 files changed

+56
-9
lines changed

2 files changed

+56
-9
lines changed

Iterable-iOS-SDK/IterableAPI.m

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,24 @@ - (void)sendRequest:(NSURLRequest *)request onSuccess:(void (^)(NSDictionary *))
225225
{
226226
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
227227
NSInteger responseCode = httpResponse.statusCode;
228+
229+
// Handle network errors
230+
if (error != nil) {
231+
NSString *reason = [NSString stringWithFormat:@"%@", error];
232+
if (onFailure != nil) onFailure(reason, nil);
233+
return;
234+
}
228235

229236
NSError *jsonError = nil;
230-
id json = [NSJSONSerialization
231-
JSONObjectWithData:data
232-
options:0
233-
error:&jsonError];
237+
id json = nil;
238+
239+
// Only try to parse JSON if data exists, otherwise JSONObjectWithData throws an exception
240+
if ([data length] > 0) {
241+
json = [NSJSONSerialization
242+
JSONObjectWithData:data
243+
options:0
244+
error:&jsonError];
245+
}
234246

235247
if (responseCode == 401) {
236248
if (onFailure != nil) onFailure(@"Invalid API Key", data);
@@ -249,7 +261,7 @@ - (void)sendRequest:(NSURLRequest *)request onSuccess:(void (^)(NSDictionary *))
249261
onFailure(errorMessage, data);
250262
}
251263
} else if (responseCode == 200) {
252-
if ([data length] > 0 && error == nil) {
264+
if ([data length] > 0) {
253265
if (jsonError) {
254266
NSString *reason = [NSString stringWithFormat:@"Could not parse json: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]];
255267
if (onFailure != nil) onFailure(reason, data);
@@ -260,11 +272,8 @@ - (void)sendRequest:(NSURLRequest *)request onSuccess:(void (^)(NSDictionary *))
260272
} else {
261273
if (onFailure != nil) onFailure(@"Response is not a dictionary", data);
262274
}
263-
} else if ([data length] == 0 && error == nil) {
275+
} else {
264276
if (onFailure != nil) onFailure(@"No data received", data);
265-
} else if (error != nil) {
266-
NSString *reason = [NSString stringWithFormat:@"%@", error];
267-
if (onFailure != nil) onFailure(reason, nil);
268277
}
269278
} else {
270279
if (onFailure != nil) onFailure([NSString stringWithFormat:@"Received non-200 response: %ld", (long) responseCode], data);

Iterable-iOS-SDKTests/IterableAPIResponseTests.m

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,42 @@ - (void)testNon200ResponseCode {
159159
[self waitForExpectations:@[expectation] timeout:IterableResponseExpectationTimeout];
160160
}
161161

162+
- (void)testNoNetworkResponse {
163+
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
164+
return YES;
165+
} withStubResponse:^OHHTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
166+
NSError* notConnectedError = [NSError errorWithDomain:NSURLErrorDomain code:kCFURLErrorNotConnectedToInternet userInfo:nil];
167+
return [OHHTTPStubsResponse responseWithError:notConnectedError];
168+
}];
169+
170+
XCTestExpectation *expectation = [[XCTestExpectation alloc] initWithDescription:@"onFailure is called"];
171+
172+
NSURLRequest *request = [[IterableAPI sharedInstance] createRequestForAction:@"" withArgs:@{}];
173+
[[IterableAPI sharedInstance] sendRequest:request onSuccess:nil onFailure:^(NSString * _Nonnull reason, NSData * _Nullable data) {
174+
[expectation fulfill];
175+
XCTAssert([reason containsString:@"NSURLErrorDomain"]);
176+
}];
177+
[self waitForExpectations:@[expectation] timeout:IterableResponseExpectationTimeout];
178+
}
179+
180+
- (void)testNetworkTimeoutResponse {
181+
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
182+
return YES;
183+
} withStubResponse:^OHHTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
184+
NSError* notConnectedError = [NSError errorWithDomain:NSURLErrorDomain code:kCFURLErrorNotConnectedToInternet userInfo:nil];
185+
return [[OHHTTPStubsResponse responseWithData:nil statusCode:200 headers:nil] requestTime:0.0 responseTime:5.0];
186+
}];
187+
188+
XCTestExpectation *expectation = [[XCTestExpectation alloc] initWithDescription:@"onFailure is called"];
189+
190+
NSMutableURLRequest *request = (NSMutableURLRequest *) [[IterableAPI sharedInstance] createRequestForAction:@"" withArgs:@{}];
191+
request.timeoutInterval = 0.01;
192+
[[IterableAPI sharedInstance] sendRequest:request onSuccess:nil onFailure:^(NSString * _Nonnull reason, NSData * _Nullable data) {
193+
[expectation fulfill];
194+
XCTAssert([reason containsString:@"NSURLErrorDomain"]);
195+
XCTAssert([reason containsString:@"timed out"]);
196+
}];
197+
[self waitForExpectations:@[expectation] timeout:IterableResponseExpectationTimeout];
198+
}
199+
162200
@end

0 commit comments

Comments
 (0)