I'm using tastypie for a REST interface in django, from Xcode I can call the server and get data successfully using RestKit however I cannot POST data. I know it's hitting the right area as I had a 401 then turned on authentication() in django and that problem was solved, now I'm receiving a 501 Not Implemented Error. I've also manually added the detail and list_allowed_methods to allow all forms POST/GET/ETC. I've Googled and overflowed to no avail! Help!
Here's the code I'm using for POSTING (I'm new to RestKit so be gentle)
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"http://127.0.0.1:8000/api/v1/"]];
RKObjectMapping *lotRequestMapping = [RKObjectMapping requestMapping];
[lotRequestMapping addAttributeMappingsFromDictionary:#{#"status" : #"parking_availability"}];
RKResponseDescriptor *lotResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:lotRequestMapping
pathPattern:#"parkinglot/:primaryKey/"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
Screenshot -
Here's the Error
See Screenshot
Text from Screenshot
2012-12-19 13:23:26.145 Parkable[36586:4b07] I
restkit.network:RKHTTPRequestOperation.m:143 POST
'http://127.0.0.1:8000/api/v1/parkinglot/22/?format=json' 2012-12-19
13:23:26.158 Parkable[36586:3807] E
restkit.network:RKHTTPRequestOperation.m:156 POST
'http://127.0.0.1:8000/api/v1/parkinglot/22/?format=json' (501 Not
Implemented): Error Domain=AFNetworkingErrorDomain Code=-1011
"Expected status code in (200-299,400-499), got 501"
UserInfo=0x9170260
{AFNetworkingOperationFailingURLRequestErrorKey=http://127.0.0.1:8000/api/v1/parkinglot/22/?format=json>,
NSErrorFailingURLKey=http://127.0.0.1:8000/api/v1/parkinglot/22/?format=json,
NSLocalizedDescription=Expected status code in (200-299,400-499), got
501,
AFNetworkingOperationFailingURLResponseErrorKey=} 2012-12-19 13:23:26.158 Parkable[36586:4b07] E
restkit.network:RKObjectRequestOperation.m:271 Object request failed:
Underlying HTTP request operation failed with error: Error
Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code in
(200-299,400-499), got 501" UserInfo=0x9470f10
{AFNetworkingOperationFailingURLRequestErrorKey=http://127.0.0.1:8000/api/v1/parkinglot/22/?format=json>,
NSErrorFailingURLKey=http://127.0.0.1:8000/api/v1/parkinglot/22/?format=json,
NSLocalizedDescription=Expected status code in (200-299,400-499), got
501,
AFNetworkingOperationFailingURLResponseErrorKey=} 2012-12-19 13:23:26.159 Parkable[36586:c07] failure -
Error Domain=AFNetworkingErrorDomain Code=-1011 "Expected status code
in (200-299,400-499), got 501" UserInfo=0x9470f10
{AFNetworkingOperationFailingURLRequestErrorKey=http://127.0.0.1:8000/api/v1/parkinglot/22/?format=json>,
NSErrorFailingURLKey=http://127.0.0.1:8000/api/v1/parkinglot/22/?format=json,
NSLocalizedDescription=Expected status code in (200-299,400-499), got
501,
AFNetworkingOperationFailingURLResponseErrorKey=}
To answer my own question the 501 error went away after adding in the
class UserResource(ModelResource):
to the resources.py file and registering it with urls.py
v1_api.register(UserResource())
Related
In the RestKit app I'm making the requests and responses are working happily, but now I'm trying to add error handling. I'm following the example in the RestKit readme and similar examples from the net, but run into some strange behaviour.
The error mapping is added with
// Error JSON looks like {"errors": "Some Error Has Occurred"}
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
// The entire value at the source key path containing the errors maps to the message
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:#"errorMessage"]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError);
// Any response in the 4xx status code range with an "errors" key path uses this mapping
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:#"errors" statusCodes:statusCodes];
[objectManager addResponseDescriptor:errorDescriptor];
When I make my service simulate an error instead of returning data, the following happens. The response of my service is
HTTP/1.1 401 Unauthorized
Server: ASP.NET Development Server/10.0.0.0
Date: Tue, 26 May 2015 19:01:21 GMT
X-AspNet-Version: 4.0.30319
Cache-Control: private
Content-Type: application/json; charset=utf-8
Connection: Close
{"errors":"This is a test exception"}
after which the connection is closed. On the client side, however, the failure block of getObjectsAtPath: isn't executed immediately. Instead the function waits for a timeout and doesn't return an error object. The error is [Updated. Replaced with log including trace logging]:
2015-05-27 14:08:25.968 Olive Oil[37455:37884261] I restkit:RKLog.m:49 RestKit logging initialized...
2015-05-27 14:08:26.275 Olive Oil[37455:37884261] 320.000000
2015-05-27 14:08:26.415 Olive Oil[37455:37884261] T restkit.network:RKObjectRequestOperation.m:148 GET 'http://192.168.69.88/OliveOil.svc/recipies':
request.headers={
"Accept-Language" = "en;q=1";
Authorization = "Basic XXXXXXXXXXXXX==";
"User-Agent" = "Olive Oil/1 (iPad Simulator; iOS 8.3; Scale/2.00)";
}
request.body=(null)
2015-05-27 14:09:33.559 Olive Oil[37455:37885022] E restkit.network:RKObjectRequestOperation.m:544 Object request failed: Underlying HTTP request operation failed with error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x7f91f36ad440 {NSUnderlyingError=0x7f91f37271e0 "The request timed out.", NSErrorFailingURLStringKey=http://192.168.69.88/OliveOil.svc/recipies, NSErrorFailingURLKey=http://192.168.69.88/OliveOil.svc/recipies, NSLocalizedDescription=The request timed out.}
2015-05-27 14:09:33.559 Olive Oil[37455:37885022] E restkit.network:RKObjectRequestOperation.m:209 GET 'http://192.168.69.88/OliveOil.svc/recipies' (401 Unauthorized / 0 objects) [request=67.1418s mapping=0.0000s total=67.2429s]:error=Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x7f91f36ad440 {NSUnderlyingError=0x7f91f37271e0 "The request timed out.", NSErrorFailingURLStringKey=http://192.168.69.88/OliveOil.svc/recipies, NSErrorFailingURLKey=http://192.168.69.88/OliveOil.svc/recipies, NSLocalizedDescription=The request timed out.}
2015-05-27 14:09:33.560 Olive Oil[37455:37885022] D restkit.network:RKObjectRequestOperation.m:210 response.body=(null)
So apparently the status 401 gets communicated (2nd error), but something makes the RestKit wait for more data. What could be the cause of this behaviour? Some misconfiguration? Is the service response malformed? Is there something wrong with the error mapping?
On the service side, the connection wasn't closed after the data was sent.
After making the appropriate changes, the app processes the error information as expected. Thanks, Wain, for pointing me in the right direction.
I am getting an ntewtork error from their server on application launch reading
2014-03-27 16:46:05.356 C21[4222:60b] Failed to initialize gimbal Error Domain=QLRestTemplateErrorDomain Code=-1011 "Expected status code in (200-299), got 400" UserInfo=0x1700f3480 {NSLocalizedDescription=Expected status code in (200-299), got 400, QL_HTTP_STATUS_CODE=400, NSErrorFailingURLKey=https://ios.api.gimbal.com/service/rest/v4/user/28414345/application, NSLocalizedFailureReason={"statusCode":10000,"errorMessage":"Application verification failed. Invalid com.iBeek.C21 for application with package com.iBeek.C21"}}
2014-03-27 16:46:05:359 C21[4222:60b] Error Occoured:Expected status code in (200-299), got 400
2014-03-27 16:46:05:501 C21[4222:60b] Error Occoured:Expected status code in (200-299), got 400
2014-03-27 16:46:06.018 C21[4222:9403] QLDDLogFileInfo: creationDate(log-03272014-164606.txt): getattrlist result = -1
It looks like the verification failed but checked all the API keys and they were right. Not sure whats causing this.
I am writing an iOS app that requests data from Yelp.
I currently have code that manages Yelp requests/responses and parses the JSON data returned internally. The current code builds the OAuth parameters for its requests using OAuthConsumer by Jon Crosby.
I came upon RestKit yesterday, and found it very appealing. It would probably eliminate much of the request submission and response parsing I am doing.
But I hit a roadblock, because I have not been able to figure out how to generate the OAuth parameters that Yelp requires with RestKit. I worked through the Ray Wenderlich RestKit tutorial at http://www.raywenderlich.com/13097/intro-to-restkit-tutorial, but it uses a client ID and client secret (as required by Foursquare).
Yelp requests need to have a consumer key, token, signature method, signature, timestamp and nonce. I have been unable to find an add-on for RestKit that can generate this particular set of OAuth parameters.
I am now generating my RestKit GET requests using an AFOAuth1Client developed by Matt Thompson. Now the Yelp API is returning an Invalid Signature error when I send a request.
I am puzzled because I have checked the fields in the HTTP Authorization header, and they look correct. The error seems to indicate that Yelp wants the oauth parameters in the URL, but the API documentation says that it is acceptable to send them in the authorization header.
Here is the Invalid Signature error I'm getting:
2013-08-26 15:34:54.806 RestKitYelpGroupon[2157:400b] E restkit.network:RKObjectRequestOperation.m:575 Object request failed: Underlying HTTP request operation failed with error: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200-299), got 400" UserInfo=0xa876190 {NSLocalizedRecoverySuggestion={"error": {"text": "Signature was invalid", "id": "INVALID_SIGNATURE", "description": "Invalid signature. Expected signature base string: GET\u0026http%3A%2F%2Fapi.yelp.com%2Fv2%2Fsearch\u0026ll%3D32.893282%252C-117.195083%26oauth_consumer_key%3D(MY CONSUMER KEY)%26oauth_nonce%3DC0F25D91-B473-4059-B5F6-2D850A144A1D%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1377556409%26oauth_token%3D(MY OAUTH TOKEN)%26oauth_version%3D1.0%26term%3Dsushi"}}, AFNetworkingOperationFailingURLRequestErrorKey=http://api.yelp.com/v2/search?ll=32.893282%2C-117.195083&term=sushi>, NSErrorFailingURLKey=http://api.yelp.com/v2/search?ll=32.893282%2C-117.195083&term=sushi, NSLocalizedDescription=Expected status code in (200-299), got 400, AFNetworkingOperationFailingURLResponseErrorKey=}
Here is the code I am using to generate the requests:
NSURL *baseURL = [NSURL URLWithString:#"http://api.yelp.com/v2"];
AFOAuth1Client *oauth1Client = [[AFOAuth1Client alloc] initWithBaseURL:baseURL key:consumerKey secret:consumerSecret];
oauth1Client.accessToken = [[AFOAuth1Token alloc] initWithKey:tokenKey
secret:tokenSecret
session:nil
expiration:[NSDate distantFuture]
renewable:NO];
[oauth1Client registerHTTPOperationClass:[AFJSONRequestOperation class]];
// Accept HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
[oauth1Client setDefaultHeader:#"Accept" value:#"application/json"];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:oauth1Client];
RKObjectMapping *couponMapping = [RKObjectMapping mappingForClass:[Coupon class]];
[couponMapping addAttributeMappingsFromDictionary:#{#"id" : #"id"}];
RKObjectMapping *businessMapping = [RKObjectMapping mappingForClass:[Business class]];
[businessMapping addAttributeMappingsFromDictionary:#{#"name" : #"name"}];
[businessMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"deals" toKeyPath:#"location" withMapping:couponMapping]];
RKResponseDescriptor * responseDescriptor = [RKResponseDescriptor
responseDescriptorWithMapping:businessMapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:#"response.venues"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager getObjectsAtPath:#"http://api.yelp.com/v2/search"
parameters:queryParams
success:^(RKObjectRequestOperation * operaton, RKMappingResult *mappingResult)
Any further assistance is greatly appreciated!
Take a look at using AFOAuth2Client and setting it as the client when you init your RKObjectManager.
I am using RestKit 0.2, and I am getting the following error.
E restkit.network:RKObjectRequestOperation.m:237 GET 'http://some.url.com/o/3134' (200 OK / 0 objects) [request=3.2563s mapping=0.0000s total=3.2955s]: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (400-499), got 200" UserInfo=0x87712e0 {NSLocalizedRecoverySuggestion={"d":"2013-07-15T02:30:00.000Z","t":16.1,"at":13.8}, AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest http://some.url.com/o/3134>, NSErrorFailingURLKey=http://some.url.com/o/3134, NSLocalizedDescription=Expected status code in (400-499), got 200, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x9647260>}
I use nodejs and restify as the server end. And I can get the json data by using Google Chrome, and I can see the Content-Type of response is application/json in Chrome.
But when I used RestKit, I got this error about 'Expected status code in (400-499), got 200', I think 200 is fine, why the RestKit is expecting 400 - 499 rather than 200? And I can see the json object in the error message too. which is {"d":"2013-07-15T02:30:00.000Z","t":16.1,"at":13.8}.
Thanks.
When you define the response descriptor for a request, you need to set the status code to RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful) if you expect a response with http status code 2xx
Example:
[RKResponseDescriptor responseDescriptorWithMapping:yourMapping method:RKRequestMethodAny pathPattern:yourPattern keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
UPDATE:
Make sure that the pathPattern of the response descriptor matches the request path. Otherwise RestKit will use the error response descriptor (if you define it), and expect a response with a different status code.
I'm getting a weird behavior where using sendSynchronousRequest or sendAsynchronousRequest with invalid credential will make the nsurlresponse nil. But the old way with the [[NSURLConnection alloc] initWithRequest:request delegate:self]; I get the 401 response code.
The error value using the sendSynchronousRequest or sendAsynchronousRequest is
Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be
completed. (NSURLErrorDomain error -1012.)" UserInfo=0x756ecb0
{NSErrorFailingURLKey=myurl,
NSErrorFailingURLStringKey=myurl,
NSUnderlyingError=0x75704d0 "The operation couldn’t be completed.
(kCFErrorDomainCFNetwork error -1012.)"
Does someone have a clue as to why it is like that? Any information on this is appreciated. I was expecting to get a 401 response from sendSynchronousRequest or sendAsynchronousRequest
Thanks,
This error is caused when a WWW-Authenticate: HTTP header is returned with the 401 response, asking for user-interaction to enter valid credentials. The NSURLConnection processes the HTTP headers and the response body, returning the response data correctly as an NSData object, but leaving the returningResponse object as nil.
According to Apple's Foundation Constants Reference, the error -1012 is:
NSURLErrorUserCancelledAuthentication
Returned when an asynchronous request for authentication is cancelled by the user.
This is typically incurred by clicking a “Cancel” button in a username/password dialog, rather than the user making an attempt to
authenticate.
I am speculating that it automatically treats the WWW-Authenticate: header as a request for credentials that was cancelled by the user (since it is headless) and generates the error. Then some other part of the code-path that should set the response is not executed because there was an error. Personally I think this is either a bug or bad design. It should be ok to get a valid HTTP response and an error at the same time, either way, you get a valid HTTP response so the returningResponse should be set. Bad Apple!