iOS和RestKit:如何获得正确的text / html响应?

时间:2014-02-17 13:17:49

标签: ios objective-c rest restkit

我已经尝试了几个StackOverflow问题,并且我在这个问题上找到了正确的答案。我正在使用Chrome的POSTMAN插件检查我的REST调用,我无法弄清楚为什么我无法读取响应。在评论中,您将看到我为获得响应而做出的所有不同尝试。

NSDictionary* session_params = @{SESSION_USERNAME_KEY:SESSION_USERNAME_VALUE, SESSION_PASSWORD_KEY:SESSION_PASSWORD_VALUE};
NSURL* url = [NSURL URLWithString:SESSION_URL];
RKObjectManager* objectManager = [RKObjectManager managerWithBaseURL:url];
//GET THE **** THING TO INTERPRET A TEXT response

//[RKMIMETypeSerialization registerClass:[RKXMLReaderSerialization class] forMIMEType:RKMIMETypeTextXML];
//[objectManager setAcceptHeaderWithMIMEType:@"text/html"];
//[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeTextXML];
//[RKMIMETypeSerialization registerClass:[RKXMLReaderSerialization class] forMIMEType:@"text/html"];
//[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"text/html"];
//[objectManager setRequestSerializationMIMEType:@"text/html"];

//END
NSMutableURLRequest* request = [objectManager requestWithObject:nil method:RKRequestMethodPOST path:SESSION_URL parameters:session_params];


RKObjectRequestOperation* operation = [objectManager
                                       objectRequestOperationWithRequest:request success:^(RKObjectRequestOperation* operation, RKMappingResult* result)
                                       {
                                           NSLog(@"RESULT [%@]", result);
                                       }
                                       failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                           NSLog(@"ERROR [%@]", error);
                                       }];

    [operation start];

我认为最令人恼火的是我需要的东西包含在NSLocalizedRecoverySuggestion值中。这是我需要的会话密钥。

输出:

  

E restkit.network:RKObjectRequestOperation.m:547对象请求失败:基础HTTP请求操作失败,错误:错误Domain = org.restkit.RestKit.ErrorDomain Code = -1016“预期内容类型{(       “应用程序/ x WWW的形式进行了urlencoded”,       “应用程序/ JSON”   )},得到的text / html”的UserInfo = {0x1c52aed0 = NSLocalizedRecoverySuggestion eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJCbG8uUmVnQWxlcnQuQnJva2VyIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdC9CbG8uUmVnQWxlcnQuQVBJL2FwaSIsIm5iZiI6MTM5MjY0MTY2MSwiZXhwIjoxMzkyNjQ1MjYxLCJ1bmlxdWVfbmFtZSI6IkJ1dHRvbnMiLCJyb2xlIjoiUmVnQWxlcnRDb25zdW1lciJ9.JCTMGJRKlOxEtNrcGodpce-tqsRS4zlApNisKQW6iSw,AFNetworkingOperationFailingURLRequestErrorKey =,= NSErrorFailingURLKey HTTP:// ...,NSLocalizedDescription =预期的内容类型{(       “应用程序/ x WWW的形式进行了urlencoded”,       “应用程序/ JSON”   ),得到text / html,AFNetworkingOperationFailingURLResponseErrorKey =}   2014-02-17 14:54:20.808 AppName [5600:6403] E restkit.network:RKObjectRequestOperation.m:213 POST'http:// ...'(200 OK / 0个对象)[request = 0.0000s mapping = 0.0000s total = 0.1925s]:Error Domain = org.restkit.RestKit.ErrorDomain Code = -1016“预期内容类型{(       “应用程序/ x WWW的形式进行了urlencoded”,       “应用程序/ JSON”   )},得到的text / html”的UserInfo = {0x1c52aed0 = NSLocalizedRecoverySuggestion eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJCbG8uUmVnQWxlcnQuQnJva2VyIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdC9CbG8uUmVnQWxlcnQuQVBJL2FwaSIsIm5iZiI6MTM5MjY0MTY2MSwiZXhwIjoxMzkyNjQ1MjYxLCJ1bmlxdWVfbmFtZSI6IkJ1dHRvbnMiLCJyb2xlIjoiUmVnQWxlcnRDb25zdW1lciJ9.JCTMGJRKlOxEtNrcGodpce-tqsRS4zlApNisKQW6iSw,AFNetworkingOperationFailingURLRequestErrorKey =,= NSErrorFailingURLKey HTTP:// ...,NSLocalizedDescription =预期的内容类型{(       “应用程序/ x WWW的形式进行了urlencoded”,       “应用程序/ JSON”   ),得到text / html,AFNetworkingOperationFailingURLResponseErrorKey =}

工作的代码 感谢Wain指出我在那里的正确道路。我有点失望,RestKit无法处理这么简单的请求,我需要RestKit,因为这只是一个调用其他方法的会话令牌,但无论如何,我想:

NSDictionary* session_params = @{SESSION_USERNAME_KEY:SESSION_USERNAME_VALUE, SESSION_PASSWORD_KEY:SESSION_PASSWORD_VALUE};

NSURL* url = [NSURL URLWithString:SESSION_URL];

AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:SESSION_URL parameters:session_params];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSString* response = [operation responseString];
    NSLog(@"response: %@",response);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"error: %@", [operation error]);
}];
[operation start];

2 个答案:

答案 0 :(得分:3)

这一位:

  

“预期内容类型{(”application / x-www-form-urlencoded“,”application / json“)},得到text / html”

告诉你,你告诉RestKit期待form-urlencodedjson,但是服务器正在返回html。

可能希望使用带有JSON mime类型的setAcceptHeaderWithMIMEType来告诉服务器您想要回复的内容。但是,在这种情况下,您可能不应该使用RestKit。

RestKit用于将任意JSON / XML数据映射到您的数据模型中。你只需要一把钥匙回来。不需要映射。因此,不要使用RestKit,而是使用AFNetworking(您可以完全访问它,因为RestKit在内部使用它。

答案 1 :(得分:1)

感谢Wain和Quintin,这对我来说非常有用:)

我认为更新版本的RestkitAFNetworking中的某些名称已更改。我使用了AFNetworking,如其他答案所述,因为服务器没有返回json而是返回空plain/text。这只是在我在响应标题中寻找令牌的特定端点上。

在这里分享我的代码:

-(void) find_some_token_with_success:(void (^)(AFRKHTTPRequestOperation *operation, id responseObject))success failure:(void (^)(AFRKHTTPRequestOperation *operation, NSError *error))failure {

    NSURL *baseURL = [NSURL URLWithString:@"https://example.com"];

    AFRKHTTPClient *client = [AFRKHTTPClient clientWithBaseURL:baseURL];
    [client setDefaultHeader:@"Accept" value:RKMIMETypeJSON];
    [client setDefaultHeader:@"some_custom_header" value:@"some_custom_value"];

    NSMutableURLRequest *request = [client requestWithMethod:@"GET" path:@"/api/v1/some_non_json_endpoint" parameters:nil];

    AFRKHTTPRequestOperation *operation = [[AFRKHTTPRequestOperation alloc] initWithRequest:request];

    [operation setCompletionBlockWithSuccess:success failure:failure];
    [operation start];
}

然后我使用这样的东西来获得我正在寻找的标题:

-(void) get_the_token:(void (^)(NSString *token))withTokenCallback failure:(void (^)(AFRKHTTPRequestOperation *operation, NSError *error))failure {
    [self xsrftoken_with_success:^(AFRKHTTPRequestOperation *operation, id responseObject) {
        NSString *token = [self get_the_token_from_response:[operation response]];
        withTokenCallback(token);
    } failure:failure];
}

-(NSString *) get_the_token_from_response: (NSHTTPURLResponse *) response;
{
    NSDictionary *headerDictionary = response.allHeaderFields;
    NSString *token = [headerDictionary objectForKey:@"SOME-TOKEN-KEY"];
    return token;
}

所以这一切都可以像这样使用:

- (void)testGetSometokenInARequest
{
    XCTestExpectation *expectation = [self expectationWithDescription:@"Query timed out."];

    [[SomeRequestWithoutJsonResponse alloc]
     get_the_token:^(NSString *token) {
         [expectation fulfill];
         NSLog(@"token: %@", token);
         // this token should be 100 characters long
         XCTAssertTrue([token length] == 100);
     }
     failure:^(AFRKHTTPRequestOperation *operation, NSError *error) {
         NSLog(@"error: %@", [operation error]);
     }];

    [self waitForExpectationsWithTimeout:10.0 handler:nil];
}

换句话说,get_the_token使用所需的令牌和失败回调进行回调。

请确保您仍然包含<RestKit/RestKit>,以便您可以访问Restkit的AFNetowkring:)

使用restkit的替代工作解决方案:

RestKit: How to handle empty response.body?

你为这种Mimetype注册一个序列化器,如下所示:

[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"text/plain"];