0

I need to use NSURLSession send a post request to server.and one of the params need to be a url encode string.I found in Charles it is not I expected format. Here is the code.

NSMutableDictionary *md = [self defaultParams].mutableCopy;
[md setObject:@"track" forKey:@"$event_type"];
[md setObject:@"page" forKey:@"$event_name"];
NSDictionary *tempMd = @{@"message_id":@"776", @"msgid":@"MG-0703_111_857"};
NSString *extraString = nil;
if (tempMd.allKeys.count != 0) {
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:tempMd options:NSJSONWritingPrettyPrinted error:&error];
    if (jsonData) {
        extraString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
}
//A
if (extraString.length != 0) {
    extraString = [extraString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//B
    [md setObject:extraString forKey:@"$extra"];
}

id params = md.copy;
NSError * error = nil;
NSString *paramsString;
NSData *jsonData;
if ([params isKindOfClass:[NSDictionary class]]||[params isKindOfClass:[NSArray class]]) {
    @try {
        jsonData = [NSJSONSerialization dataWithJSONObject:params options:kNilOptions error:&error];
        if (jsonData) {
            paramsString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        }
    }
    @catch (NSException *exception) {
        return;
    }
    @finally {
    }
}
if (paramsString.length > 0) {
    NSString *bid = @"18.1.1";
    NSDictionary *requestParams = @{@"data" : paramsString, @"bid" : bid};
    NSURL *url = [NSURL URLWithString:@"https://ec.log.mgtv.com/s.gif?"];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    request.HTTPMethod = @"POST";
    request.timeoutInterval = 20.;
    NSString *bodyString = [self parseParams:requestParams];
    //C
    request.HTTPBody = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"big data complete");
        completeBlock();
    }] resume];
}

+ (NSString *)parseParams:(NSDictionary *)params {
    NSString *keyValueFormat;
    NSMutableString *result = [NSMutableString new];
    NSMutableArray *array = [NSMutableArray new];
    NSEnumerator *keyEnum = [params keyEnumerator];
    id key;
    while (key = [keyEnum nextObject]) {
        keyValueFormat = [NSString stringWithFormat:@"%@=%@&", key, [params valueForKey:key]];
        [result appendString:keyValueFormat];
        [array addObject:keyValueFormat];
    }
    return result;
}

At A, extraString is enter image description here At B, extraString is enter image description here At C, bodyString is enter image description here

and I found it in Charles: enter image description here

{"$os":"iOS","$is_vip":0,"biz_id":"MG-0703_111_859","$screen_width":390,"$app_version":"xm-iphone-1.0","$extra":"{
  "messageid" : "859",
  "msgid" : "MG-0703_111_859"
}","$event_name":"page","$model":"iPhone13_2","$network_type":"WIFI","$time":1625295930198,"device_id":"01f23f0160839dada3e3d214982df41bcf0220cc","$carrier":"中国电信","page_name":"push","$user_type":0,"$channel":"apple","$project":"mgtv-ec","$ua":"XMNotificationService\/1.0 (iPhone; iOS 14.6; Scale\/3.00)","biz_type":"push","$screen_height":844,"$is_login":0,"$event_type":"track","$lib_version":"1.0","$os_version":"14.6","$manufacturer":"Apple","$lib":"iOS","$is_ecom_vip":0}

But what I expect is like below:

{"$os":"iOS","$is_vip":0,"biz_id":"MG-0703_111_859","$screen_width":390,"$app_version":"xm-iphone-1.0","$extra":"%7B%0A%20%20%22messageid%22%20:%20%22860%22,%0A%20%20%22msgid%22%20:%20%22MG-0703_111_860%22%0A%7D","$event_name":"page","$model":"iPhone13_2","$network_type":"WIFI","$time":1625295930198,"device_id":"01f23f0160839dada3e3d214982df41bcf0220cc","$carrier":"中国电信","page_name":"push","$user_type":0,"$channel":"apple","$project":"mgtv-ec","$ua":"XMNotificationService\/1.0 (iPhone; iOS 14.6; Scale\/3.00)","biz_type":"push","$screen_height":844,"$is_login":0,"$event_type":"track","$lib_version":"1.0","$os_version":"14.6","$manufacturer":"Apple","$lib":"iOS","$is_ecom_vip":0}

And my question is why the Charles show different with the C, I expect to see "$extra":"%7B%0A%20%20%22messageid%22%20:%20%22860%22,%0A%20%20%22msgid%22%20:%20%22MG-0703_111_860%22%0A%7D"

childrenOurFuture
  • 1,889
  • 2
  • 14
  • 23

1 Answers1

0

It looks to me like the charles proxy is interpreting the encoded data in the $extra item when showing the information inside the HTTP.Body. The body itself looks fine when you get ready to send it. but it seems to have taken the

%7B%0A%20%20%22me...

Which is embedded inside the body and decoded it to ascii.

The question really is if it is actually decoded at the end point or simply the Charles presentation mode. When you look on the server is it coming through decoded, or as the % encoded characters?

I'd suggest viewing the packet in hex and making sure it is not just presentation information you are seeing... the Charles docs suggest this is possible

"You can always see the HTTP request and response headers and the request and response bodies, either as plain text or binary (hexadecimal & ascii)."

I would inspect in hex and make sure you are seeing a real problem.

Jim
  • 229
  • 3
  • 9