Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't handle successful 204 response and correctly map failing response using RestKit

Tags:

ios

restkit

I am writing an iOS app that interacts with a service to update a user's profile. In order to update a user's name, the iOS app PUTs a request with a body of the following format:

 {"name" : {"first" : "FIRSTNAMEGOESHERE", "lastName":"LASTNAMEGOESHERE"}}

In the case where the request body is valid (i.e. both a first and last name are provided), the service returns a 204 (No Content) status code and an empty response body.

In the case where the request body is invalid (e.g. first name is missing, etc.), the service will return a status code of 400 and a response body in the following format:

{"code":"ERRORCODEHERE"}

The iOS app is using RestKit and I have been unable to figure out how to get it to both properly handle the success and failure case. If I use this:

- (void)updateUserName
{
    RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[[NSURL alloc] initWithString:@"http://someqaserver:8080"]];
    [objectManager setRequestSerializationMIMEType:RKMIMETypeJSON];

    RKObjectMapping *userMapping = [RKObjectMapping requestMapping];
    [userMapping addAttributeMappingsFromDictionary:@{@"firstName" : @"first", @"lastName" : @"last"}];

    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userMapping objectClass:[OurUser class]                                       rootKeyPath:@"name"];

    [objectManager addRequestDescriptor:requestDescriptor];

    [objectManager putObject:[OurUser getCurrentUser]
                   path:@"/mobile/profile/name"
                   parameters:nil
                   success:^(RKObjectRequestOperation *operation, RKMappingResult *result)
                   {
                     NSLog(@"Success!");
                   }
                   failure:^(RKObjectRequestOperation *operation, NSError *error)
                   {
                     NSLog(@"Fail!");
                   }];
}

This obviously does not work for the error case, but it does successfully execute the success block in the case where a 204 is returned from the server.

If I add the following code before calling putObject, the error handling works, but now the valid 204 case is deemed a failure:

    RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[ServiceError class]];
    [errorMapping addAttributeMappingsFromDictionary:@{@"code" : @"errorCode"}];
    RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
    [objectManager addResponseDescriptor:errorDescriptor];

This seems to happen since the accepted HTTP status codes are now set to those of the response descriptors provided and 204 is not one of them (or maybe it's something else?)

How can I get it so that: 1.) if a 204 is returned, it's seen as a success 2.) if a 4XX is returned, it's seen as a failure and the error code is properly mapped to my ServiceError object?

Thanks in advance for any help you can provide.

like image 575
Kathleen Avatar asked Oct 21 '22 15:10

Kathleen


2 Answers

The problem was solved by also adding a response descriptor to handle the 204:

RKResponseDescriptor *successResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[RKObjectMapping mappingForClass:nil]
                                                                                               method:RKRequestMethodPUT
                                                                                          pathPattern:nil
                                                                                              keyPath:nil
                                                                                          statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[manager addResponseDescriptor:successResponseDescriptor];
like image 98
Kathleen Avatar answered Oct 30 '22 03:10

Kathleen


code 204 is not an error, any 2xx status is deemed a success. 204 means 'no content', which is a perfectly valid response. If you expect restkit to treat it as an error, make sure you throw a 3xx, 4xx or a 5xx error. In your case you are using a RKStatusCodeClassClientErrorm which would suggest you should throw a 4xx error.

See wikipedia for a complete list of error codes

like image 25
Kevin R Avatar answered Oct 30 '22 02:10

Kevin R