nst / STHTTPRequest

Obj-C / Cocoa HTTP requests for humans
BSD 3-Clause "New" or "Revised" License
826 stars 75 forks source link

URL encoding GET requests #24

Closed jasperblues closed 10 years ago

jasperblues commented 10 years ago

Thankfully RESTful style parameter passing is popular now, but every now and then we need to hit a legacy service, where we append traditional query parameters to a GET request.

This is actually fairly complicated.

It would be nice if we could create a request something like this:

STHTTPRequest *request = [STHTTPRequest requestWithURL:_endpointUrl 
    appendedWithQueryParameters:@{
        @"q" : city,
        @"format" : @"json",
        @"num_of_days" : [NSString stringWithFormat:@"%i", _daysToRetrieve],
        @"key"         : _apiKey
    }];
];

The code that I currently use for encoding URLs looks like this:

Utility class:

+ (NSURL *)URL:(NSURL *)url appendedWithQueryParameters:(NSDictionary *)parameters
{
    NSMutableString *urlString = [[NSMutableString alloc] initWithString:[url absoluteString]];

    for (id key in parameters) {
        NSString *keyString = [key description];
        NSString *valueString = [[parameters objectForKey:key] description];

        if ([urlString rangeOfString:@"?"].location == NSNotFound) {
            [urlString appendFormat:@"?%@=%@", [self URLEscapeString:keyString], [self URLEscapeString:valueString]];
        }
        else {
            [urlString appendFormat:@"&%@=%@", [self URLEscapeString:keyString], [self URLEscapeString:valueString]];
        }
    }
    return [NSURL URLWithString:urlString];
}

//Fall all the way down to foundation, as it handles '/' character properly
+ (NSString *)URLEscapeString:(NSString *)rawString
{
    CFStringRef originalStringRef = (__bridge_retained CFStringRef) rawString;
    NSString *encoded =
        (__bridge_transfer NSString *) CFURLCreateStringByAddingPercentEscapes(NULL, originalStringRef, NULL, NULL, kCFStringEncodingUTF8);
    CFRelease(originalStringRef);
    return encoded;
}
jasperblues commented 10 years ago

Alternatively we could use: [request addQueryParameterWithName:value]

I love that this library is simple and not bloated, however I think this would be a useful addition. If you like I could send a pull request.

gavinwilliams commented 10 years ago

+1

nst commented 10 years ago

Thank you for the proposal, I'll review it in the upcoming days.

nst commented 10 years ago

Sorry for the delay, I've been quite busy lately, I haven't forgotten you proposal.

nst commented 10 years ago

I eventually chose to use a GETDictionary property.

I hope you'll find it useful.