aboutsummaryrefslogtreecommitdiff
path: root/Foundation
diff options
context:
space:
mode:
authorGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2012-03-01 17:00:20 +0000
committerGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2012-03-01 17:00:20 +0000
commit32654998f055c85d9a70b6f415abf79dd81c601e (patch)
tree6d5ecf98880ccbd2c0ad55036f730eee4e6fa871 /Foundation
parent4f85e00accda833f7fd0ef1a40018818ae090495 (diff)
[Author: msenesi]
Flexible builder for URLs. R=altse,dmaclach,thomasvl APPROVED=dmaclach
Diffstat (limited to 'Foundation')
-rw-r--r--Foundation/GTMURLBuilder.h64
-rw-r--r--Foundation/GTMURLBuilder.m138
-rw-r--r--Foundation/GTMURLBuilderTest.m108
3 files changed, 310 insertions, 0 deletions
diff --git a/Foundation/GTMURLBuilder.h b/Foundation/GTMURLBuilder.h
new file mode 100644
index 0000000..e959fa7
--- /dev/null
+++ b/Foundation/GTMURLBuilder.h
@@ -0,0 +1,64 @@
+//
+// GTMURLBuilder.h
+//
+// Copyright 2012 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+
+//
+// Class for creating URLs. It handles URL encoding of parameters.
+//
+// Usage example:
+//
+// GTMURLBuilder *URLBuilder =
+// [GTMURLBuilder builderWithString:@"http://www.google.com"];
+// [URLBuilder setValue:@"abc" forParameter:@"q"];
+// NSURL *URL = [URLBuilder URL];
+//
+
+#import <Foundation/Foundation.h>
+#import "GTMDefines.h"
+
+@interface GTMURLBuilder : NSObject {
+ @private
+ NSMutableDictionary *params_;
+}
+
+@property(nonatomic, readonly) NSString *baseURLString;
+
+// Encodes URL by percent-encoding, except reserved characters:
+// ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
++ (NSURL *)URLWithString:(NSString *)URLString;
+// |URLString| is expected to be a valid URL with already escaped parameter
+// values.
++ (GTMURLBuilder *)builderWithString:(NSString *)URLString;
++ (GTMURLBuilder *)builderWithURL:(NSURL *)URL;
+
+// |URLString| The base URL to which parameters will be appended.
+// If the URL already contains parameters, they should already be encoded.
+- (id)initWithString:(NSString *)URLString;
+- (void)setValue:(NSString *)value forParameter:(NSString *)parameter;
+- (void)setIntegerValue:(NSInteger)value forParameter:(NSString *)parameter;
+- (NSString *)valueForParameter:(NSString *)parameter;
+- (void)removeParameter:(NSString *)parameter;
+- (void)setParameters:(NSDictionary *)parameters;
+- (NSDictionary *)parameters;
+- (NSURL *)URL;
+- (NSString *)URLString;
+
+// Case-sensitive comparison of the URL. Also protocol and host are compared
+// as case-sensitive strings. The order of URL parameters is ignored.
+- (BOOL)isEqual:(GTMURLBuilder *)URLBuilder;
+
+@end
diff --git a/Foundation/GTMURLBuilder.m b/Foundation/GTMURLBuilder.m
new file mode 100644
index 0000000..0cfce45
--- /dev/null
+++ b/Foundation/GTMURLBuilder.m
@@ -0,0 +1,138 @@
+//
+// GTMURLBuilder.m
+//
+// Copyright 2012 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+
+#import "GTMURLBuilder.h"
+
+#import "GTMDefines.h"
+#import "GTMLogger.h"
+#import "GTMNSDictionary+URLArguments.h"
+#import "GTMNSString+URLArguments.h"
+
+@implementation GTMURLBuilder
+
+@synthesize baseURLString = baseURLString_;
+
++ (GTMURLBuilder *)builderWithString:(NSString *)URLString {
+ GTMURLBuilder *URLBuilder =
+ [[[GTMURLBuilder alloc] initWithString:URLString] autorelease];
+ return URLBuilder;
+}
+
++ (GTMURLBuilder *)builderWithURL:(NSURL *)URL {
+ return [self builderWithString:[URL absoluteString]];
+}
+
+- (id)init {
+ self = [super init];
+ [self release];
+ _GTMDevAssert(NO, @"Invalid initialization.");
+ return nil;
+}
+
+- (id)initWithString:(NSString *)URLString {
+ self = [super init];
+ if (self) {
+ _GTMDevAssert(URLString, @"URL must not be nil");
+ NSURL *URL = [NSURL URLWithString:URLString];
+ _GTMDevAssert(URL, @"URL is invalid");
+
+ // NSURL does not work with ports.
+ baseURLString_ = [URL absoluteString];
+ if ([URL path]) {
+ NSRange pathRange =
+ [baseURLString_ rangeOfString:[URL path] options:NSBackwardsSearch];
+ if (pathRange.location != NSNotFound) {
+ baseURLString_ = [baseURLString_ substringToIndex:pathRange.location];
+ }
+
+ baseURLString_ =
+ [NSString stringWithFormat:@"%@%@", baseURLString_, [URL path]];
+ }
+ [baseURLString_ retain];
+ params_ = [[NSDictionary gtm_dictionaryWithHttpArgumentsString:[URL query]]
+ mutableCopy];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [baseURLString_ release];
+ [params_ release];
+ [super dealloc];
+}
+
+- (void)setValue:(NSString *)value forParameter:(NSString *)parameter {
+ [params_ setObject:value forKey:parameter];
+}
+
+- (void)setIntegerValue:(NSInteger)value forParameter:(NSString *)parameter {
+ [params_ setObject:[NSString stringWithFormat:@"%i", value] forKey:parameter];
+}
+
+- (NSString *)valueForParameter:(NSString *)parameter {
+ return [params_ objectForKey:parameter];
+}
+
+- (void)removeParameter:(NSString *)parameter {
+ [params_ removeObjectForKey:parameter];
+}
+
+- (void)setParameters:(NSDictionary *)parameters {
+ [params_ autorelease];
+ params_ = [[NSDictionary dictionaryWithDictionary:parameters] mutableCopy];
+}
+
+- (NSDictionary *)parameters {
+ return params_;
+}
+
+- (NSURL *)URL {
+ if (![params_ count]) {
+ return [NSURL URLWithString:baseURLString_];
+ } else {
+ return [NSURL URLWithString:[NSString stringWithFormat:@"%@?%@",
+ baseURLString_, [params_ gtm_httpArgumentsString]]];
+ }
+}
+
+- (NSString *)URLString {
+ return [[self URL] absoluteString];
+}
+
+- (BOOL)isEqual:(GTMURLBuilder *)URLBuilder {
+ if (!URLBuilder) {
+ return NO;
+ }
+
+ if (!([[self baseURLString] isEqualToString:[URLBuilder baseURLString]])) {
+ return NO;
+ }
+
+ if (![[self parameters] isEqualToDictionary:[URLBuilder parameters]]) {
+ return NO;
+ }
+
+ return YES;
+}
+
++ (NSURL *)URLWithString:(NSString *)URLString {
+ return [NSURL URLWithString:
+ [URLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+}
+
+@end
diff --git a/Foundation/GTMURLBuilderTest.m b/Foundation/GTMURLBuilderTest.m
new file mode 100644
index 0000000..096c09b
--- /dev/null
+++ b/Foundation/GTMURLBuilderTest.m
@@ -0,0 +1,108 @@
+//
+// GTMURLBuilderTest.m
+//
+// Copyright 2012 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+
+#import "GTMURLBuilder.h"
+
+#import "GTMSenTestCase.h"
+
+@interface GTMURLBuilderTest : GTMTestCase
+@end
+
+@implementation GTMURLBuilderTest
+
+- (void)testParseURL {
+ GTMURLBuilder *URLBuilder = [[[GTMURLBuilder alloc]
+ initWithString:@"http://google.com:8080/pathA/pathB?param=val"]
+ autorelease];
+ STAssertEqualStrings(@"http://google.com:8080/pathA/pathB?param=val",
+ [URLBuilder URLString], nil);
+ STAssertEqualStrings(@"val", [URLBuilder valueForParameter:@"param"], nil);
+ URLBuilder = [GTMURLBuilder builderWithString:
+ @"http://google.com:8080/pathA/pathB?param=val"];
+ STAssertEqualStrings(@"http://google.com:8080/pathA/pathB?param=val",
+ [URLBuilder URLString], nil);
+ STAssertEqualStrings(@"val", [URLBuilder valueForParameter:@"param"], nil);
+}
+
+- (void)testMailToHandling {
+ GTMURLBuilder *URLBuilder =
+ [GTMURLBuilder builderWithString:@"mailto:ytmapp-ios@google.com"];
+ [URLBuilder setValue:@"blah" forParameter:@"subject"];
+ STAssertEqualStrings(@"mailto:ytmapp-ios@google.com?subject=blah",
+ [URLBuilder URLString], nil);
+}
+
+- (void)testIsEqualTo {
+ GTMURLBuilder *URLBuilderA = [GTMURLBuilder
+ builderWithString:@"http://google.com/pathA/pathB?a=b&c=d"];
+ GTMURLBuilder *URLBuilderB =
+ [GTMURLBuilder builderWithString:@"http://google.com/pathA/pathB"];
+ [URLBuilderB setValue:@"d" forParameter:@"c"];
+ [URLBuilderB setValue:@"b" forParameter:@"a"];
+ STAssertTrue([URLBuilderA isEqual:URLBuilderB], nil);
+ [URLBuilderB setValue:@"c" forParameter:@"a"];
+ STAssertFalse([URLBuilderA isEqual:URLBuilderB], nil);
+ [URLBuilderB setValue:@"b" forParameter:@"a"];
+ [URLBuilderB setValue:@"f" forParameter:@"e"];
+ STAssertFalse([URLBuilderA isEqual:URLBuilderB], nil);
+}
+
+- (void)testURLWithString {
+ STAssertEqualStrings(@";/?:@&=+$,",
+ [[GTMURLBuilder URLWithString:@";/?:@&=+$,"]
+ absoluteString],
+ nil);
+ STAssertEqualStrings(@"a%20b%20&%20c%20-%20URL=http://test.com/",
+ [[GTMURLBuilder URLWithString:
+ @"a b & c - URL=http://test.com/"] absoluteString],
+ nil);
+}
+
+- (void)testSetParameters {
+ GTMURLBuilder *URLBuilderA =
+ [GTMURLBuilder builderWithString:@"http://google.com/"];
+ GTMURLBuilder *URLBuilderB =
+ [GTMURLBuilder builderWithString:@"http://google.com/?p1=x&p2=b"];
+ NSDictionary *params =
+ [NSDictionary dictionaryWithObjectsAndKeys:@"a", @"p1", @"b", @"p2", nil];
+ [URLBuilderA setParameters:params];
+ [URLBuilderA setValue:@"x" forParameter:@"p1"];
+ STAssertTrue([URLBuilderA isEqual:URLBuilderB], nil);
+}
+
+- (void)testReplaceParameters {
+ GTMURLBuilder *URLBuilderA =
+ [GTMURLBuilder builderWithString:@"http://google.com/?p1=y"];
+ GTMURLBuilder *URLBuilderB =
+ [GTMURLBuilder builderWithString:@"http://google.com/?p1=x&p2=b"];
+ NSDictionary *params =
+ [NSDictionary dictionaryWithObjectsAndKeys:@"a", @"p1", @"b", @"p2", nil];
+ [URLBuilderA setParameters:params];
+ [URLBuilderA setValue:@"x" forParameter:@"p1"];
+ STAssertTrue([URLBuilderA isEqual:URLBuilderB], nil);
+}
+
+- (void)testURLPathParsing {
+ GTMURLBuilder *URLBuilder =
+ [GTMURLBuilder builderWithString:@"http://google.com/"];
+ STAssertEqualStrings(@"http://google.com/", [URLBuilder URLString], nil);
+ URLBuilder = [GTMURLBuilder builderWithString:@"http://google.com/pA/pB"];
+ STAssertEqualStrings(@"http://google.com/pA/pB", [URLBuilder URLString], nil);
+}
+
+@end