3

我刚刚开始使用新的AFNetworking 2.0API,之前的版本已经使用了一段时间。我正在尝试做一个沼泽标准http POST request,但遗憾的是我做得不太好。这是我当前的代码:

AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];

NSDictionary *parameters = @{@"username" : self.usernameField.text,
                             @"password" : self.passwordField.text};

[operationManager POST:@"https:URL GOES HERE" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", [responseObject description]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

现在这会返回一个JSONof(NULL)并且不会给我一个状态代码之类的404东西(顺便说一句,我们在使用 AFN 2.0 时如何获得状态代码?)。但是,当我使用像apikitchen.com这样为我测试的网络应用程序尝试这些信息HTTP Post request时,当我将用户名和密码输入该param字段时它就可以工作。所以真的我的问题是,为什么不parameters以与网络应用程序AFN 2.0 parameter property相同的方式行事?parameters更一般地说,为什么不post request parameters为我工作AFN 2.0

提前感谢您的帮助,
迈克

编辑:我正在努力实施建议的修复程序。我的 Post 方法现在看起来像这样,但现在对我来说没有意义。

AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"username" : self.usernameField.text,
                             @"password" : self.passwordField.text};

operationManager.requestSerializer.queryStringSerializationWithBlock =
^NSString*(NSURLRequest *request,
           NSDictionary *parameters,
           NSError *__autoreleasing *error) {
    NSString* encodedParams = form_urlencode_HTTP5_Parameters(parameters);
    return encodedParams;
};

[operationManager POST:@"URL HERE" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", [responseObject description]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];
4

2 回答 2

2

现在这会返回一个 (NULL) 的 JSON,并且不会给我一个像 404 之类的状态代码(顺便说一句,我们在使用 AFN 2.0 时如何获得状态代码?)。

它至少应该给出一个错误。故障处理程序打印出什么?

所以我的问题是,为什么 AFN 2.0 参数属性中的参数的行为方式与 Web 应用程序中的参数不同?更一般地说,为什么在 AFN 2.0 中发布请求参数对我不起作用?

在检查了 AFN(版本 2.0.1)如何对参数进行编码后,在我看来,这些参数没有按应有的方式编码: application/x-www-form-urlencoded encoding algorithm

在解决此问题之前,您可以尝试以下解决方法。以下算法严格按照 w3c 对 HTTP 5 的建议对参数进行编码,至少对于我测试过的 Mac OS X 10.8:

static NSString* form_urlencode_HTTP5_String(NSString* s) {
    CFStringRef charactersToLeaveUnescaped = CFSTR(" ");
    CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@~");

    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
                         kCFAllocatorDefault,
                         (__bridge CFStringRef)s,
                         charactersToLeaveUnescaped,
                         legalURLCharactersToBeEscaped,
                         kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

(注意:上面的代码取决于 function 的实现细节CFURLCreateStringByAddingPercentEscapes。完全有可能在没有任何依赖关系的情况下轻松实现建议的算法,我会推荐 - 它变得不那么短。)

static NSString* form_urlencode_HTTP5_Parameters(NSDictionary* parameters) 
{
    NSMutableString* result = [[NSMutableString alloc] init];
    BOOL isFirst = YES;
    for (NSString* name in parameters) {
        if (!isFirst) {
            [result appendString:@"&"];
        }
        isFirst = NO;
        assert([name isKindOfClass:[NSString class]]);
        NSString* value = parameters[name];
        assert([value isKindOfClass:[NSString class]]);

        NSString* encodedName = form_urlencode_HTTP5_String(name);
        NSString* encodedValue = form_urlencode_HTTP5_String(value);

        [result appendString:encodedName];
        [result appendString:@"="];
        [result appendString:encodedValue];
    }

    return [result copy];
}

然后,在使用 AFN 时,您可以自定义序列化算法,如下所示:

    AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];

    operationManager.requestSerializer.queryStringSerializationWithBlock = 
       ^NSString*(NSURLRequest *request,
                  NSDictionary *parameters,
                  NSError *__autoreleasing *error) {
        NSString* encodedParams = form_urlencode_HTTP5_Parameters(parameters);
        return encodedParams;
    };
于 2013-10-15T14:33:43.667 回答
0

放在/网址后面。我已经错过了几个小时。

于 2014-01-23T13:12:42.033 回答