Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IOS not encoding plus(+) sign in x-www-form-urlencoded POST request?

I am using the following code,

NSString *jsonD = [NSString stringWithFormat:@"rawJson=%@",[fbUserInfo jsonUTF8String]];
NSData *myRequestData = [jsonD dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                                           cachePolicy:policy timeoutInterval:20.0];

[ request setHTTPMethod: @"POST" ];
[request setValue:[NSString stringWithFormat:@"%d", [myRequestData length]] forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[ request setHTTPBody: myRequestData ];

In this code I have the date 2013-06-29T18:33:17+0000. The problem is that my server receiving date as 2013-06-29T18:33:17 0000. See the space. I don't know why this is happening.

like image 241
Imran Qadir Baksh - Baloch Avatar asked Jul 03 '13 09:07

Imran Qadir Baksh - Baloch


4 Answers

Just because you specify the encoding header does not mean the NSURLRequest will actually perform said encoding.

The CFURLCreateStringByAddingPercentEscapes function can URL-encode your strings for you.

If you don't care about the encoding and just want to send simple strings, I suggest you skip the encoding entirely and use the "text/plain" content type.

Another option would be to use JSON instead of form encoding ("application/json"). JSON is much easier to use, both on the server side and on the client side. Cocoa has builtin support for JSON.

EDIT: Now that I read your code again, I see that you name your variable suggesting that the data is already JSON. If so, the solution is to use the "application/json" content type and make sure the server understands and decodes this properly.

like image 196
Krumelur Avatar answered Oct 20 '22 00:10

Krumelur


If you need to have the ' ' -> '+' substitution, you need to do it on your own.

See: Objective-c iPhone percent encode a string? for the code to do the conversion.


Update

OK, based on your comment, here is some additional information. Based on old handling of query strings, '+' characters are turned into ' ' characters.

It was enshrined into old JavaScript, CGI, and PHP handing of URLs.

Microsoft even has a buggy example demonstrating it.

You can avoid the problem by always converting '+' to '%2B' and ' ' to '%20'.

like image 34
Jeffery Thomas Avatar answered Oct 20 '22 02:10

Jeffery Thomas


The AFNetworking library solves it thusly:

static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
    static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()~',*";
    static NSString * const kAFCharactersToLeaveUnescaped = @"[].";

    return (__bridge_transfer  NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding));
}
like image 23
FluffulousChimp Avatar answered Oct 20 '22 02:10

FluffulousChimp


As @Krumelur suggested,The CFURLCreateStringByAddingPercentEscapes function can URL-encode your strings for you. And Here is the code.

static NSString * CTPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
    return (__bridge_transfer  NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}

And Complete solution : To get encoded url from parameters use below code.

/**
 get parameterized url from url and query parameters.
 */
+(NSString *)getParameterizedUrl:(NSString *)url withParameters:(NSDictionary *)queryDictionary
{
    NSMutableArray *mutablePairs = [NSMutableArray array];
    for (NSString *key in queryDictionary) {
        [mutablePairs addObject:[NSString stringWithFormat:@"%@=%@", CTPercentEscapedQueryStringKeyFromStringWithEncoding(key, NSUTF8StringEncoding), CTPercentEscapedQueryStringValueFromStringWithEncoding(queryDictionary[key], NSUTF8StringEncoding)]];
    }

    return [[NSString alloc]initWithFormat:@"%@?%@",url,[mutablePairs componentsJoinedByString:@"&"]];
}

static NSString * const kCharactersToBeEscapedInQueryString = @":/?&=;+!@#$()',*";

static NSString * CTPercentEscapedQueryStringKeyFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
    static NSString * const kCharactersToLeaveUnescapedInQueryStringPairKey = @"[].";

    return (__bridge_transfer  NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kCharactersToLeaveUnescapedInQueryStringPairKey, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}

static NSString * CTPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
    return (__bridge_transfer  NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}

And use in your code as

NSString *url = [self getParameterizedUrl:@"http://www.example.com" withParameters:self.params];

Note : params here is dictionary.

like image 31
Giru Bhai Avatar answered Oct 20 '22 02:10

Giru Bhai