NSURLSession 发布一个带有 url 编码字符串的参数

问题描述

我需要使用 NSURLSession 向服务器发送一个 post 请求。其中一个参数需要是一个 url 编码字符串。我在 Charles 中发现它不是我期望的格式。 这是代码

DecimalFormat format = new DecimalFormat("#.####");
format.format(yourDoubleObject);

在 A 处,extraString 是

enter image description here

在 B 处,extraString 为

enter image description here

在 C 中,bodyString 是

enter image description here

我在查尔斯找到了它:

enter image description here

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;
}

但我的期望如下:

{"$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}

我的问题是为什么 Charles 显示与 C 不同,我希望看到 {"$os":"iOS","$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","$is_ecom_vip":0}

解决方法

在我看来,当显示 HTTP.Body 中的信息时,charles 代理正在解释 $extra 项目中的编码数据。当您准备好发送时,身体本身看起来很好。但它似乎已经采取了

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

嵌入在正文中并将其解码为ascii。

问题实际上是它是在终点实际解码还是简单地在 Charles 演示模式下进行解码。当您查看服务器时,它是通过解码来的,还是作为 % 编码字符来的?

我建议以十六进制查看数据包并确保它不仅仅是您看到的演示信息......查尔斯文档表明这是可能的

“您始终可以看到 HTTP 请求和响应标头以及请求和响应正文,无论是纯文本还是二进制(十六进制和 ascii)。”

我会以十六进制进行检查,确保您看到的是真正的问题。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...