124 lines
4.8 KiB
Objective-C
124 lines
4.8 KiB
Objective-C
#import "ARTHTTPPaginatedResponse+Private.h"
|
|
|
|
#import "ARTHttp.h"
|
|
#import "ARTAuth.h"
|
|
#import "ARTRest+Private.h"
|
|
#import "ARTPaginatedResult+Private.h"
|
|
#import "ARTNSMutableURLRequest+ARTPaginated.h"
|
|
#import "ARTNSHTTPURLResponse+ARTPaginated.h"
|
|
#import "ARTEncoder.h"
|
|
#import "ARTConstants.h"
|
|
|
|
@implementation ARTHTTPPaginatedResponse
|
|
|
|
- (instancetype)initWithResponse:(NSHTTPURLResponse *)response
|
|
items:(NSArray *)items
|
|
rest:(ARTRestInternal *)rest
|
|
relFirst:(NSMutableURLRequest *)relFirst
|
|
relCurrent:(NSMutableURLRequest *)relCurrent
|
|
relNext:(NSMutableURLRequest *)relNext
|
|
responseProcessor:(ARTPaginatedResultResponseProcessor)responseProcessor {
|
|
self = [super initWithItems:items rest:rest relFirst:relFirst relCurrent:relCurrent relNext:relNext responseProcessor:responseProcessor];
|
|
if (self) {
|
|
_response = response;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (NSInteger)statusCode {
|
|
return _response.statusCode;
|
|
}
|
|
|
|
- (BOOL)success {
|
|
return _response.statusCode >= 200 && _response.statusCode < 300;
|
|
}
|
|
|
|
- (NSInteger)errorCode {
|
|
NSString *code = [_response.allHeaderFields valueForKey:ARTHttpHeaderFieldErrorCodeKey];
|
|
return [code integerValue];
|
|
}
|
|
|
|
- (NSString *)errorMessage {
|
|
NSString *message = [_response.allHeaderFields valueForKey:ARTHttpHeaderFieldErrorMessageKey];
|
|
return message;
|
|
}
|
|
|
|
- (NSDictionary<NSString *,NSString *> *)headers {
|
|
return _response.allHeaderFields;
|
|
}
|
|
|
|
- (void)first:(ARTHTTPPaginatedCallback)callback {
|
|
if (callback) {
|
|
void (^userCallback)(ARTHTTPPaginatedResponse *_Nullable result, ARTErrorInfo *_Nullable error) = callback;
|
|
callback = ^(ARTHTTPPaginatedResponse *_Nullable result, ARTErrorInfo *_Nullable error) {
|
|
dispatch_async(self.userQueue, ^{
|
|
userCallback(result, error);
|
|
});
|
|
};
|
|
}
|
|
|
|
[self.class executePaginated:self.rest withRequest:self.relFirst callback:callback];
|
|
}
|
|
|
|
- (void)next:(ARTHTTPPaginatedCallback)callback {
|
|
if (callback) {
|
|
void (^userCallback)(ARTHTTPPaginatedResponse *_Nullable result, ARTErrorInfo *_Nullable error) = callback;
|
|
callback = ^(ARTHTTPPaginatedResponse *_Nullable result, ARTErrorInfo *_Nullable error) {
|
|
dispatch_async(self.userQueue, ^{
|
|
userCallback(result, error);
|
|
});
|
|
};
|
|
}
|
|
|
|
if (!self.relNext) {
|
|
// If there is no next page, we can't make a request, so we answer the callback
|
|
// with a nil PaginatedResult. That's why the callback has the result as nullable
|
|
// anyway. (That, and that it can fail.)
|
|
callback(nil, nil);
|
|
return;
|
|
}
|
|
|
|
[self.class executePaginated:self.rest withRequest:self.relNext callback:callback];
|
|
}
|
|
|
|
+ (void)executePaginated:(ARTRestInternal *)rest
|
|
withRequest:(NSMutableURLRequest *)request
|
|
callback:(ARTHTTPPaginatedCallback)callback {
|
|
[rest.logger debug:__FILE__ line:__LINE__ message:@"HTTP Paginated request: %@", request];
|
|
|
|
[rest executeRequest:request withAuthOption:ARTAuthenticationOn completion:^(NSHTTPURLResponse *response, NSData *data, NSError *error) {
|
|
if (error && ![error.domain isEqualToString:ARTAblyErrorDomain]) {
|
|
callback(nil, [ARTErrorInfo createFromNSError:error]);
|
|
return;
|
|
}
|
|
|
|
[[rest logger] debug:__FILE__ line:__LINE__ message:@"HTTP Paginated response: %@", response];
|
|
[[rest logger] debug:__FILE__ line:__LINE__ message:@"HTTP Paginated response data: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]];
|
|
|
|
NSError *decodeError = nil;
|
|
|
|
ARTPaginatedResultResponseProcessor responseProcessor = ^(NSHTTPURLResponse *response, NSData *data, NSError **errorPtr) {
|
|
id<ARTEncoder> encoder = [rest.encoders objectForKey:response.MIMEType];
|
|
return [encoder decodeToArray:data error:errorPtr];
|
|
};
|
|
NSArray *items = error ? @[] : responseProcessor(response, data, &decodeError);
|
|
|
|
if (decodeError) {
|
|
callback(nil, [ARTErrorInfo createFromNSError:decodeError]);
|
|
return;
|
|
}
|
|
|
|
NSDictionary *links = [response extractLinks];
|
|
|
|
NSMutableURLRequest *firstRel = [NSMutableURLRequest requestWithPath:links[@"first"] relativeTo:request];
|
|
NSMutableURLRequest *currentRel = [NSMutableURLRequest requestWithPath:links[@"current"] relativeTo:request];
|
|
NSMutableURLRequest *nextRel = [NSMutableURLRequest requestWithPath:links[@"next"] relativeTo:request];
|
|
|
|
ARTHTTPPaginatedResponse *result = [[ARTHTTPPaginatedResponse alloc] initWithResponse:response items:items rest:rest relFirst:firstRel relCurrent:currentRel relNext:nextRel responseProcessor:responseProcessor];
|
|
|
|
callback(result, nil);
|
|
}];
|
|
}
|
|
|
|
@end
|