Revision 45f2fce6 Classes/OpenStackRequest.m

b/Classes/OpenStackRequest.m
23 23
#import "GetFlavorsRequest.h"
24 24
#import "APICallback.h"
25 25
#import "APILogEntry.h"
26
#import "NSString+Conveniences.h"
26 27

  
27 28

  
28 29
static NSRecursiveLock *accessDetailsLock = nil;
......
44 45
- (void)notify {
45 46
    NSString *observeName = [NSString stringWithFormat:@"%@ %@ %@", [self isSuccess] ? @"SUCCESS" : @"FAILURE", self.requestMethod, [self.url description]];
46 47
    NSString *callbackName = [NSString stringWithFormat:@"%@ %@ %@ %@", [self isSuccess] ? @"SUCCESS" : @"FAILURE", self.requestMethod, [self.url description], self.callback.uuid];
47
    
48

  
48 49
    NSDictionary *callbackUserInfo = [NSDictionary dictionaryWithObject:self forKey:@"response"];
49 50

  
50 51
    NSNotification *observeNotification = [NSNotification notificationWithName:observeName object:nil userInfo:callbackUserInfo];
......
149 150
	[request addRequestHeader:@"X-Auth-Token" value:[account authToken]];
150 151
    [request addRequestHeader:@"Content-Type" value:@"application/json"];
151 152
    [request setTimeOutSeconds:60];
153
    [request setNumberOfTimesToRetryOnTimeout:5];
152 154
    request.retriedCount = 0;
153 155
	return request;
154 156
}
155 157

  
156 158
+ (id)getSharingAccountsRequest:(OpenStackAccount *)account {
157
    NSString *topLevelUrlString = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"GRNetStorageUrlPrefix"];
158
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@?format=json",topLevelUrlString]];
159
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@?format=json",account.provider.authEndpointURL]];
159 160
    return [OpenStackRequest request:account method:@"GET" url:url];
160 161
}
161 162

  
......
175 176
        filesUrl = [NSString stringWithFormat:@"%@%@",
176 177
                    [urlString substringToIndex:authUserRange.location],
177 178
                    account.sharingAccount];
178
    } else {
179
    } else
179 180
        filesUrl = urlString;
180
	}
181 181
    
182 182
	NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@?format=json%@&now=%@",
183 183
                                       filesUrl,
184 184
                                       path,
185 185
                                       account.shared ? @"&shared=" : @"",
186
                                       now]];   
186
                                       now]];  
187
    
187 188
    return [OpenStackRequest request:account method:method url:url];
188 189
}
189 190

  
......
193 194
    return [OpenStackRequest request:account method:method url:url];
194 195
}
195 196

  
197

  
196 198
#pragma mark -
197 199
#pragma mark Auth Retry
198 200

  
199 201
- (void)authRetrySucceded:(OpenStackRequest *)retryRequest {
200
    
201 202
    if ([self isKindOfClass:[GetFlavorsRequest class]]) {
202 203
        NSLog(@"flavor request");
203 204
    }
204
    
205
    self.account.authToken = [[retryRequest responseHeaders] objectForKey:@"X-Auth-Token"];    
205
    self.account.authToken = [[retryRequest responseHeaders] objectForKey:@"X-Auth-Token"]; 
206 206
    [self.account persist];
207 207
    
208 208
    // TODO: make this work for GetServersRequest, etc
......
210 210
    // try the original request again!
211 211
    retried = YES;
212 212
    retriedRequest = [self copy];
213

  
213 214
	[retriedRequest addRequestHeader:@"X-Auth-Token" value:self.account.authToken];    
214 215
    
215 216
    if (backupCompletionBlock) {
......
222 223
            backupFailureBlock();
223 224
        }];
224 225
    }
226

  
225 227
    [retriedRequest startSynchronous];     
226 228
}
227 229

  
228 230
- (void)authRetryFailed:(OpenStackRequest *)retryRequest {
229 231
    // if it fails due to bad connection, try again?
230
    NSLog(@"auth retry failed with status %i", retryRequest.responseStatusCode);
231 232
    NSNotification *notification = [NSNotification notificationWithName:[self.account.manager notificationName:@"authRetryFailed" identifier:0] object:nil userInfo:[NSDictionary dictionaryWithObject:retryRequest forKey:@"request"]];
232 233
    [[NSNotificationCenter defaultCenter] postNotification:notification];
233 234
}
......
248 249
}
249 250

  
250 251
- (void)failWithError:(NSError *)theError {
251

  
252 252
    if (responseStatusCode == 401 && ![url isEqual:account.provider.authEndpointURL]) {
253 253
        // auth is expired, so get a fresh token
254
        if (account) {
254
        if (account && ![account.provider isGRNet]) {
255 255
            OpenStackRequest *retryRequest = [OpenStackRequest authenticationRequest:account];
256 256
            retryRequest.delegate = self;
257 257
            retryRequest.didFinishSelector = @selector(authRetrySucceded:);
......
320 320
    }
321 321
}
322 322

  
323

  
324

  
323 325
+ (OpenStackRequest *)authenticationRequest:(OpenStackAccount *)account {
324 326

  
325 327
	OpenStackRequest *request = [[[OpenStackRequest alloc] initWithURL:account.provider.authEndpointURL] autorelease];
......
628 630
}
629 631

  
630 632
+ (OpenStackRequest *)createContainerRequest:(OpenStackAccount *)account container:(Container *)container {    
631
    return [OpenStackRequest filesRequest:account method:@"PUT" path:[[NSString stringWithFormat:@"/%@", container.name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
633
    return [OpenStackRequest filesRequest:account method:@"PUT" path:[NSString stringWithFormat:@"/%@", [NSString encodeToPercentEscape:container.name]]];
632 634
}
633 635

  
634 636
+ (OpenStackRequest *)deleteContainerRequest:(OpenStackAccount *)account container:(Container *)container {
635
    return [OpenStackRequest filesRequest:account method:@"DELETE" path:[[NSString stringWithFormat:@"/%@", container.name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
637
    return [OpenStackRequest filesRequest:account method:@"DELETE" path:[NSString stringWithFormat:@"/%@", [NSString encodeToPercentEscape:container.name]]];
636 638
}
637 639

  
638 640
+ (OpenStackRequest *)getObjectsRequest:(OpenStackAccount *)account container:(Container *)container {
639
    return [OpenStackRequest filesRequest:account method:@"GET" path:[[NSString stringWithFormat:@"/%@", container.name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];    
641
    return [OpenStackRequest filesRequest:account method:@"GET" path:[NSString stringWithFormat:@"/%@", [NSString encodeToPercentEscape:container.name]]];    
640 642
}
641 643

  
642 644
- (NSMutableDictionary *)objects {
643 645
    SBJSON *parser = [[SBJSON alloc] init];
644 646
    NSArray *jsonObjects = [parser objectWithString:[self responseString]];
647

  
645 648
    NSMutableDictionary *objects = [[[NSMutableDictionary alloc] initWithCapacity:[jsonObjects count]] autorelease];
646 649
    
647 650
    for (int i = 0; i < [jsonObjects count]; i++) {
......
655 658
}
656 659

  
657 660
+ (OpenStackRequest *)getObjectInfoRequest:(OpenStackAccount *)account container:(Container *)container object:(StorageObject *)object {
658
    return [OpenStackRequest filesRequest:account method:@"HEAD" path:[[NSString stringWithFormat:@"/%@/%@", container.name, object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];    
661
    return [OpenStackRequest filesRequest:account method:@"HEAD" path:[NSString stringWithFormat:@"/%@/%@",[NSString encodeToPercentEscape:container.name], [NSString encodeToPercentEscape:object.fullPath charactersToEncode:@"!*'();:@&=+$,?%#[]"]]];    
659 662
}
660 663

  
661 664
+ (OpenStackRequest *)getObjectRequest:(OpenStackAccount *)account container:(Container *)container object:(StorageObject *)object {
662
    return [OpenStackRequest filesRequest:account method:@"GET" path:[[NSString stringWithFormat:@"/%@/%@", container.name, object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];    
665
    return [OpenStackRequest filesRequest:account method:@"GET" path:[NSString stringWithFormat:@"/%@/%@",[NSString encodeToPercentEscape:container.name], [NSString encodeToPercentEscape:object.fullPath charactersToEncode:@"!*'();:@&=+$,?%#[]"]]];    
663 666
}
664 667

  
665 668
+ (OpenStackRequest *)writeObjectRequest:(OpenStackAccount *)account container:(Container *)container object:(StorageObject *)object {
......
667 670
    if ([fullPath characterAtIndex:0] == '/') {
668 671
        fullPath = [fullPath substringFromIndex:1];
669 672
    }
673
        
674
    OpenStackRequest *request = [OpenStackRequest filesRequest:account method:@"PUT" path:[NSString stringWithFormat:@"/%@/%@",[NSString encodeToPercentEscape:container.name], [NSString encodeToPercentEscape:fullPath charactersToEncode:@"!*'();:@&=+$,?%#[]"]]];    
670 675
    
671
    OpenStackRequest *request = [OpenStackRequest filesRequest:account method:@"PUT" path:[[NSString stringWithFormat:@"/%@/%@", container.name, fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];    
676
    if (object.sharing)
677
        [request.requestHeaders setObject:object.sharing forKey:@"X-Object-Sharing"];
678
    
679
    NSString *metadataKeyHeaderPrefix;
680
    if ([fullPath length] == 0)
681
        metadataKeyHeaderPrefix = @"X-Container-Meta-";
682
    else
683
        metadataKeyHeaderPrefix = @"X-Object-Meta-";
684
    
685
    for (NSString *metadataKey in object.metadata) {
686
        NSString *metadataKeyHeader = [NSString stringWithFormat:@"%@%@", metadataKeyHeaderPrefix, metadataKey]; 
687
        metadataKeyHeader = [NSString encodeToPercentEscape:metadataKeyHeader];
688
        NSString *metadataValue = [NSString encodeToPercentEscape:[object.metadata objectForKey:metadataKey]];
689
        [request.requestHeaders setObject:metadataValue forKey:metadataKeyHeader];
690
    }
691

  
672 692
	[request setPostBody:[NSMutableData dataWithData:object.data]];
673
    [request.requestHeaders setObject:object.contentType forKey:@"Content-Type"];
693
    [request.requestHeaders setObject:object.contentType forKey:@"Content-Type"];    
674 694
	return request;
675 695
}
676 696

  
677 697
+ (OpenStackRequest *)writeObjectMetadataRequest:(OpenStackAccount *)account container:(Container *)container object:(StorageObject *)object {
678
    NSString *fullPath = [NSString stringWithString:object.fullPath];
679
    if ([fullPath length] && ([fullPath characterAtIndex:0] == '/'))
698
    NSString *fullPath = object.fullPath;
699
    if ([fullPath length] != 0 && [fullPath characterAtIndex:0] == '/') {
680 700
        fullPath = [fullPath substringFromIndex:1];
701
    }
681 702

  
682 703
    NSString *metadataKeyHeaderPrefix;
683
    if (![fullPath length])
704
    if ([fullPath length] == 0)
684 705
        metadataKeyHeaderPrefix = @"X-Container-Meta-";
685 706
    else
686 707
        metadataKeyHeaderPrefix = @"X-Object-Meta-";
687 708
        
688
    OpenStackRequest *request = [OpenStackRequest filesRequest:account method:@"POST" path:[[NSString stringWithFormat:@"/%@/%@", container.name, fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 
689
    
709
    OpenStackRequest *request = [OpenStackRequest filesRequest:account method:@"POST" path:[NSString stringWithFormat:@"/%@/%@",[NSString encodeToPercentEscape:container.name], [NSString encodeToPercentEscape:fullPath charactersToEncode:@"!*'();:@&=+$,?%#[]"]]]; 
710

  
690 711
    for (NSString *metadataKey in object.metadata) {
691 712
        NSString *metadataKeyHeader = [NSString stringWithFormat:@"%@%@", metadataKeyHeaderPrefix, metadataKey]; 
692
        [request.requestHeaders setObject:[object.metadata objectForKey:metadataKey] forKey:metadataKeyHeader];
713
        metadataKeyHeader = [NSString encodeToPercentEscape:metadataKeyHeader];
714
        NSString *metadataValue = [NSString encodeToPercentEscape:[object.metadata objectForKey:metadataKey]];
715
        [request.requestHeaders setObject:metadataValue forKey:metadataKeyHeader];
693 716
    }
694 717
    if (!account.sharingAccount) {
695
        NSString *objectIsPublic = ([object.publicURI length]) ? @"true" : @"false";
718
        NSString *objectIsPublic = ([object.publicURI length] > 0) ? @"true" : @"false";
696 719
        [request.requestHeaders setObject:objectIsPublic forKey:@"X-Object-Public"];
697 720
    
698
        if (object.sharing)
699
            [request.requestHeaders setObject:object.sharing forKey:@"X-Object-Sharing"];
721
        if (object.sharing) {
722
            NSString *urlEncodedSharingString = [NSString encodeToPercentEscape:object.sharing];
723
            [request.requestHeaders setObject:urlEncodedSharingString forKey:@"X-Object-Sharing"];
724
        }
700 725
    }
701

  
702 726
    return request;
703 727
}
704 728

  
729

  
705 730
+ (OpenStackRequest *)deleteObjectRequest:(OpenStackAccount *)account container:(Container *)container object:(StorageObject *)object {
706 731
    if ([object.fullPath characterAtIndex:0] == '/') {
707
        return [OpenStackRequest filesRequest:account method:@"DELETE" path:[[NSString stringWithFormat:@"/%@%@", container.name, object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
732
        return [OpenStackRequest filesRequest:account method:@"DELETE" path:[NSString stringWithFormat:@"/%@%@",[NSString encodeToPercentEscape:container.name], [NSString encodeToPercentEscape:object.fullPath charactersToEncode:@"!*'();:@&=+$,?%#[]"]]];
708 733
    } else {
709
        return [OpenStackRequest filesRequest:account method:@"DELETE" path:[[NSString stringWithFormat:@"/%@/%@", container.name, object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
734
        return [OpenStackRequest filesRequest:account method:@"DELETE" path:[NSString stringWithFormat:@"/%@/%@",[NSString encodeToPercentEscape:container.name], [NSString encodeToPercentEscape:object.fullPath charactersToEncode:@"!*'();:@&=+$,?%#[]"]]];
710 735
    }
711 736
}
712 737

  
713 738
+ (OpenStackRequest *)writeContainerPolicyRequest:(OpenStackAccount *)account container:(Container *)container
714 739
{
715
    OpenStackRequest *request = [OpenStackRequest filesRequest:account method:@"PUT" path:[[NSString stringWithFormat:@"/%@", container.name] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 
740
    OpenStackRequest *request = [OpenStackRequest filesRequest:account method:@"PUT" path:[NSString stringWithFormat:@"/%@", [NSString encodeToPercentEscape:container.name]]]; 
716 741
    
717 742
    [request.requestHeaders setObject:container.versioning forKey:@"X-Container-Policy-Versioning"];
718
    [request.requestHeaders setObject:[NSString stringWithFormat:@"%lu", container.quota] forKey:@"X-Container-Policy-Quota"];
743
    [request.requestHeaders setObject:[NSString stringWithFormat:@"%u", container.quota] forKey:@"X-Container-Policy-Quota"];
719 744
    
720 745
    return request;
721 746
}
......
726 751
    
727 752
    NSMutableDictionary *groups = [accountInfo objectForKey:@"groups"];
728 753
    for (NSString *groupName in groups) {
729
        [request.requestHeaders setObject:[groups objectForKey:groupName] forKey:[NSString stringWithFormat:@"X-Account-Group-%@", groupName]];
754
        NSString *group = [NSString encodeToPercentEscape:[groups objectForKey:groupName]];
755
        groupName = [NSString encodeToPercentEscape:groupName];
756
        [request.requestHeaders setObject:group forKey:[NSString stringWithFormat:@"X-Account-Group-%@", groupName]];
730 757
    }
731 758
    if ([groups count] == 0)
732 759
        [request.requestHeaders setObject:@"" forKey:@"X-Account-Group-group"];
733 760
    
734 761
    NSMutableDictionary *accountMetadata = [accountInfo objectForKey:@"metadata"];
735 762
    for (NSString *metadataKey in accountMetadata) {
736
        [request.requestHeaders setObject:[accountMetadata objectForKey:metadataKey] forKey:[NSString stringWithFormat:@"X-Account-Meta-%@",metadataKey]];
763
        NSString *metadataValue = [NSString encodeToPercentEscape:[accountMetadata objectForKey:metadataKey]];
764
        metadataKey = [NSString encodeToPercentEscape:[accountMetadata objectForKey:metadataKey]];
765
        [request.requestHeaders setObject:metadataValue forKey:[NSString stringWithFormat:@"X-Account-Meta-%@",metadataKey]];
737 766
    }
738 767
    
739 768
    return request;
740 769
}
741 770

  
771

  
742 772
#pragma mark -
743 773
#pragma mark Memory Management
744 774

  

Also available in: Unified diff