【问题标题】:Restkit POST operation server timeoutRestkit POST 操作服务器超时
【发布时间】:2014-03-15 21:12:43
【问题描述】:

我正在尝试使用 Restkit 0.22.0 向 Web 服务发送 POST 请求。我已经设置了请求描述符和响应描述符,并且正在发送请求,但是服务器永远不会获取有效负载(或者不“知道”有效负载的结束位置),因此不会返回到我的应用程序。结果是 60 秒后服务器超时。

在设置请求描述符或请求时,我缺少一些东西。看起来,服务器要么根本没有得到任何有效载荷,要么不知道有效载荷何时结束,要么是由于 http 标头中缺少 content-length 属性,要么是由于缺少“流结束”标志。

如果我对邮递员进行同样的尝试,它会起作用。

我在 Xcode 日志中看到的是:

   2014-03-15 20:43:14.819 testIOS[52095:60b] T restkit.network:RKObjectRequestOperation.m:148 POST 'http://api.test.com:3000/0.1/user/':
   request.headers={
    Accept = "application/json";
    "Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
    "Content-Type" = "application/json; charset=utf-8";
    "User-Agent" = "testIOS/1 (iPhone Simulator; iOS 7.1; Scale/2.00)";
    "X-NewRelic-ID" = "UAEBVFNWGwAEV1ZQBgM=";
   }
   request.body={"name":"alex"}

到目前为止看起来它是正确的,虽然我不知道这个 request.body 是否像这样正确格式化。 然后需要 60 秒,直到我在日志窗口中得到下一个输出并出现以下错误:

2014-03-15 20:44:14.948 testIOS[52095:3707] E restkit.network:RKObjectRequestOperation.m:547 Object request failed: Underlying HTTP request operation failed with error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0xd342700 {NSErrorFailingURLStringKey=http://api.test.com:3000/0.1/user/, NSErrorFailingURLKey=http://api.test.com:3000/0.1/user/, NSLocalizedDescription=The request timed out., NSUnderlyingError=0xd656c20 "The request timed out."}
2014-03-15 20:44:14.949 testIOS[52095:3707] E restkit.network:RKObjectRequestOperation.m:208 POST 'http://api.test.com:3000/0.1/user/' (0 / 0 objects) [request=60.1298s mapping=0.0000s total=60.1320s]:
error=Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0xd342700 {NSErrorFailingURLStringKey=http://api.test.com:3000/0.1/user/, NSErrorFailingURLKey=http://api.test.com:3000/0.1/user/, NSLocalizedDescription=The request timed out., NSUnderlyingError=0xd656c20 "The request timed out."}
response.body=(null)
2014-03-15 20:44:14.950 testIOS[52095:60b] error is: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0xd342700 {NSErrorFailingURLStringKey=http://api.test.com:3000/0.1/user/, NSErrorFailingURLKey=http://api.test.com:3000/0.1/user/, NSLocalizedDescription=The request timed out., NSUnderlyingError=0xd656c20 "The request timed out."}

这里是代码(我认为这一定是错误的地方或遗漏了重要的部分):

+ (void)setupRK
{
    RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];

    objectManager.requestSerializationMIMEType = RKMIMETypeJSON;

    [objectManager.HTTPClient setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        if (status == AFNetworkReachabilityStatusNotReachable) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No network connection"
                                                            message:@"You must be connected to the internet to use this app."
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
            [alert show];
        }
    }];

    [RKObjectManager setSharedManager:objectManager];

    // Log all HTTP traffic with request and response bodies
    RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
}

+ (RKObjectRequestOperation *)loginRKOperationForUser:(STF_RKObj_User *)user
{
    RKObjectManager *objectManager = [RKObjectManager sharedManager];

    RKObjectMapping *userMapping = [STF_RKObj_User objectMapping];
    NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:statusCodes];
    [objectManager addResponseDescriptor:responseDescriptor];

    RKObjectMapping *objMapping = [STF_RKObj_User objectMapping];
    RKRequestDescriptor *reqDescr = [RKRequestDescriptor requestDescriptorWithMapping:[objMapping inverseMapping] objectClass:[STF_RKObj_User class] rootKeyPath:nil method:RKRequestMethodPOST];
    [objectManager addRequestDescriptor:reqDescr];

    NSMutableURLRequest *request = [objectManager requestWithObject:user method:RKRequestMethodPOST path:@"user/" parameters:nil];

    RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];

    return operation;
}

然后像这样从另一个类调用它:

- (void)loginWithUserObject:(STF_RKObj_User *)userObj
{
    RKObjectRequestOperation *operation = [STF_REST_Operations loginRKOperationForUser:userObj];
    [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        NSLog(@"mappingResult: %@", mappingResult);
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {

        [self logoutUser];

        self.loginCallback(NO, error);
        [self setLoginCallback:nil];

    }];

    [operation start];
}

我一生都无法弄清楚我错过了什么。整天在谷歌上搜索...帮助...

TIA

更新:

唷,我现在不需要后端程序员的帮助,只需将 requestSerializationMIMEType 设置为 @"text/plain" 就可以工作了。

[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"text/plain"];
sharedManager.requestSerializationMIMEType = @"text/plain";

这显然不是一个正确的服务器设置,因为在 Restkit 框架中没有用于“文本/纯文本”的 mime 类型的常量。如果我只是将 requestSerializationMIMEType 设置为“text/plain”的“任意值”,这给我留下了一个问题,是否“坏事会发生在我身上”。现在它可以工作,但我以后会遇到新问题吗?

(非常感谢 Wain 为我指明了正确的方向并建议使用 Charles!)

【问题讨论】:

  • 哦,还有一件事很重要:Web 服务托管在 Amazon AWS 服务器上
  • 网络服务日志说?
  • Web 服务日志中没有错误。如果我打开服务器上的日志,我可以看到对路径“用户”的请求,没有别的。它只是看起来,因为它坐在那里并等待有效负载流入(或停止流入)
  • 代替行:RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:[self responseDescriptors]];我现在使用 RKObjectRequestOperation *operation = [objectManager objectRequestOperationWithRequest: success: failure: .. 但仍然得到相同的服务器超时。如何更改 POST 有效负载的格式。显然服务器需要另一种格式
  • 那是requestSerializationMIMEType

标签: ios objective-c restkit restkit-0.20


【解决方案1】:

所以要回答我自己的问题,后端服务器设置要求我将 requestSerializationMIMEType 设置为 @"text/plain"。

[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"text/plain"];
sharedManager.requestSerializationMIMEType = @"text/plain";

我不确定更好的解决方案是否是更改后端服务器设置,因为它似乎并不常见,它只适用于 @"text/plain"。当@"text/plain" 甚至没有常量时。我将为此打开另一个单独的问题。

【讨论】:

  • 好吧,你的服务器坏了。应该立即返回 406 错误。如果它不喜欢您的请求,可能会出现另一个错误。但不要只是保持沉默。这是一个严重的服务器错误。
  • 好的,会告诉后端开发者修复它。我也希望网络服务至少会以错误响应,如果它如此挑剔的话:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多