Delete Object in Restkit .20 did not take JSON Values - iphone

I have an API which is used to delete a record in server DB. I used to construct the API with the request ID .It was working with CURL, but in Restkit it seems to give an error.
The Curl is:
curl -d '{eve:{mod_policy:"current"}}' -X DELETE -H Content-Type:application/json https://myurl.com/eve/eve_id?token=my_aut_token\&apikey=myapi_key.
I checked with POST & PATCH. It takes the JSON as a correct form.
My RestKit Code Sample:
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromDictionary:#{ #"modPolicy" : #"mod_policy"}];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[Event class] rootKeyPath:#"eve"];
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[Events class]];
[responseMapping addAttributeMappingsFromDictionary:#{
#"data" : #"data",
#"status":#"status"
}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping pathPattern:nil keyPath:#"" statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addRequestDescriptor:requestDescriptor];
[objectManager addResponseDescriptor:responseDescriptor];
NSString * urlPath = [NSString stringWithFormat:#"/eve/%#?token=%#&apikey=%#",eventID,loginToken,apiKey];
[objectManager deleteObject:hubEve path:urlPath parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *result)
{
DLog(#" response code is %d",operation.HTTPRequestOperation.response.statusCode);
Events * _event = [result firstObject];
DLog(#"status %#",_event.status);
if([_eventt.status isEqualToString:#"success"])
{
DLog("Move Next");
}
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
DLog("error %#",error);
}];
Some log details, if I send As DeleteObject in request:
request.body=(null) //Restkit Log
Or if I send as post Object/Patch Object
request.body={"eve":{"mod_policy":"all"}} //Restkit Log

Request mapping is explicitly not performed for DELETE requests. RestKit expects that when deleting you will be using the system to add parameters into the URL. You will need to plan some other method by which to delete. This could be using the RestKit mapping operation to create the payload data and then using the methods to create the URL request and setting the body data explicitly.

RESTKit does not support DELETE request with request.body parameter
natively because HTTP 1.1 doesn't support DELETE request with
request.body. There is a work around to set request.body explicitly but
its complex.
The request works well with cURL but not with HTTP, maybe because cURL
does not send DELETE request with request.body as DELETE but upgrades it
to PUT, we are not sure though.

Related

Xmpp gtalk authentication with google access token

I am using xmpp framework to integrate gtalk in my application. I have successfully authenticated user using OAuth 2.0. Now i want to use the access token and user email to authenticate xmpp stream. I know that the authentication call get sent xmppStreamDidConnect method using this method authenticateWithPassword. This requires a password, i want to get it done using the google access token. Any help?
Yes you can do it please follow the steps:
Register your app on google developer console.
Generate access token with following scope:
https://www.googleapis.com/auth/googletalk
start authentication as following:
(BOOL)start:(NSError **)errPtr
{
XMPPLogTrace();
// From RFC 4616 - PLAIN SASL Mechanism:
// [authzid] UTF8NUL authcid UTF8NUL passwd
//
// authzid: authorization identity
// authcid: authentication identity (username)
// passwd : password for authcid
NSString *accessToken = #"ACCESS-TOKEN-STRING-FROM Google";//TODO: assign your generated access token
NSLog(#"stream supports: %#",xmppStream.supportedAuthenticationMechanisms);
NSString *payload = [NSString stringWithFormat:#"\0%#\0%#", xmppStream.hostName, accessToken];
NSLog(#"payload = %#",payload);
NSString *base64 = [[payload dataUsingEncoding:NSUTF8StringEncoding] xmpp_base64Encoded];
NSXMLElement *auth = [NSXMLElement elementWithName:#"auth" xmlns:#"urn:ietf:params:xml:ns:xmpp-sasl"];
[auth addAttributeWithName:#"mechanism" stringValue:#"X-OAUTH2"];
[auth addAttributeWithName:#"auth:service" stringValue:#"oauth2"];
[auth addAttributeWithName:#"xmlns:auth" stringValue:#"https://www.google.com/talk/protocol/auth"];
[auth setStringValue:base64];
[xmppStream sendAuthElement:auth];
return YES;
}
Everything should work as expected, please comment.

Updating MGTwitterEngine to New Twitter API v1.1

I am currently updating my app to .json from xml for Twitters new API v1.1. I currently have .json working and can log on, get me timelines, mentions, but when trying to get direct messages, lists, or user info it seems its looking for "cookies" but it is not stored.
This is the error message received by twitter when trying to make a simple GET user/show call:
Twitter request failed: 08AD12D3-0044-49AB-8D3D-4E61D8398550 with error:Error Domain=HTTP
Code=400 "The operation couldn’t be completed. (HTTP error 400.)" UserInfo=0xce90540
{response=<NSHTTPURLResponse: 0xce94bd0> { URL:
https://api.twitter.com/1.1/users/show.json?screen_name=FreeAppl3 } { status code: 400,
headers {
"Content-Encoding" = gzip;
"Content-Type" = "application/json; charset=utf-8";
Date = "Fri, 14 Jun 2013 09:25:40 UTC";
Server = tfe;
"Set-Cookie" = "guest_id=v1%3A137120194019582695; Domain=.twitter.com; Path=/;
Expires=Sun, 14-Jun-2015 09:25:40 UTC";
"Strict-Transport-Security" = "max-age=631138519";
"Transfer-Encoding" = Identity;
} }, body={"errors":[{"message":"Bad Authentication data","code":215}]}hjD4nzoeOUaTQ1Q%3D}
When I call [twitterEngine isAuthorized]; is returns YES and if I check for my access token string, I receive what was stored on initial login. I have searched and searched as to what is happening or how to fix the issues, but am simply stuck and any help would be greatly appreciated.
Twitter API - https://dev.twitter.com/docs/api/1.1/get/users/show
Twitter Error Codes - https://dev.twitter.com/docs/error-codes-responses
refer FHSTwitterEngine you can use newly FHSTwitterEngine and if you request this method without autenticating, the users status is removed... you need to send consumer key and token along with screen_name..
In FHSTwitterEngine
//get username pass to method. In Dictionary you can get all info
NSString *username = [[FHSTwitterEngine sharedEngine]loggedInUsername];
NSDictionary *data=[[FHSTwitterEngine sharedEngine]getUserProfile:username];
// method to get all user info
-(id)getUserProfile:(NSString *)username
{
if (username.length == 0) {
return getBadRequestError();
}
NSURL *baseURL = [NSURL URLWithString:url_users_show];
OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
OARequestParameter *usernameP = [OARequestParameter requestParameterWithName:#"screen_name" value:username];
NSArray *params = [NSArray arrayWithObjects:usernameP, nil];
id userShowReturn = [self sendGETRequest:request withParameters:params];
return userShowReturn;
}

Send HTTPBody data with restkit

I'm using a firefox tool call "Poster" to check that my web service is working. When I POST the request I send a JSON object in the content to send (also call HTTP body data).
When I press the POST button the result is fine.
Now I want to do exactly the same with RestKit in objective-c:
NSString *squery = #"{\"Sort\":\"Relevance\",\"DaysToSearch\":0,\"WorkType\":\"\",\"PageSize\":20,\"LastRunCount\":0,\"IndustryCodes\":[\"\"],\"AccountId\":27,\"Experience\":\"\",\"GetResultCount\":0,\"Keywords\":\"iOS\",\"PageIndex\":0,\"DistanceFromLocation\":\"250\",\"SalaryType\":\"\",\"JobQueryId\":\"\",\"JobTitleCodes\":[\"\"]}";
RKObjectLoader *objectLoader = [[RKObjectManager sharedManager] objectLoaderWithResourcePath:url delegate:performJobQueryHandler];
objectLoader.method = RKRequestMethodPOST;
objectLoader.objectMapping = s.jobQueryDataMapper;
objectLoader.HTTPBody = [squery dataUsingEncoding:NSUTF8StringEncoding];
objectLoader.serializationMIMEType = RKMIMETypeJSON;
[objectLoader send];
As a result I get: "An non-fault exception is occured."
In the FireFox extension "Poster" if I use a different mine-type than "application/json", let say "application/x-www-form-urlencoded" I get the same error: "An non-fault exception is occured."
Is something wrong with objectLoader.serializationMIMEType = RKMIMETypeJSON; ???
Martin Magakian
Ok I think I find out.
I activated RestKit debug with
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
And I get:
2012-02-14 11:55:48 [4048:207] T restkit.network:RKRequest.m:318 Prepared POST URLRequest '<NSMutableURLRequest http://servicestest.foo.com/jobservice/jobservice.svc/json/jobquery>'. HTTP Headers: {
Accept = "application/json";
"Content-Type" = "application/x-www-form-urlencoded";
}. HTTP Body: Sort=Relevance&DaysToSearch=0&WorkType=&SalaryType=&LastRunCount=0&IndustryCodes[]=&Experience=&AccountId=0&GetResultCount=0&PageIndex=0&DistanceFromLocation=250&PageSize=20&JobQueryId=&JobTitleCodes[]=.
So I think using RKObjectLoader object don't care about objectLoader.serializationMIMEType = RKMIMETypeJSON; because the Content-Type remain "Content-Type" = "application/x-www-form-urlencoded"; instead of "Content-Type" = "application/json";
Do you think it's a bug or the normal behavior ?

Upload file from iPhone to Django

Sorry, a beginner's question: I have a very simple function in my Django application with which I can upload a file from a web browser to my server (works perfectly!). Now, instead of the web browser, I would like to use an iPhone.
I got a bit stuck as I don't really know how to provide Django with a valid form, i.e. we need a file name and enctype="multipart/form-data" as far as I understand.
Here is my upload function in Django:
class UploadFileForm(forms.Form):
file = forms.FileField()
def handle_uploaded_file(f):
destination = open('uploads/example.txt', 'wb+')
for chunk in f.chunks():
destination.write(chunk)
destination.close()
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
print form
print request.FILES
return HttpResponse('Upload Successful')
else:
form = UploadFileForm()
return render_to_response('upload.html', {'form': form})
My template looks like this (upload.html):
<form action="" method="post" enctype="multipart/form-data">
{{ form.file }}
{{ form.non_field_errors }}
<input type="submit" value="Upload" />
</form>
Now, let's suppose that I want to send a simple txt file from my iPhone app to the sever.
I don't really know how to:
provide the file name
specify the enctype and
make sure that it's in a format Django can read
This is how far I got:
NSString *fileContents = [self loadTXTFromDisk:#"example.txt"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:[NSURL
URLWithString:#"http://127.0.0.1:8000/uploadfile/"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/xml" forHTTPHeaderField:#"Content-type"];
[request setValue:[NSString stringWithFormat:#"%d", [fileContents length]]
forHTTPHeaderField:#"Content-length"];
[request setHTTPBody:[fileContents dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *theConnection = [[NSURLConnection alloc]
initWithRequest:request
delegate:self];
However, Django will not except this as the form it expects is not valid. Cf. above:
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid(): #this will not be true ...
The enctype from the HTML form should be the Content-Type of the HTTP request. You are currently setting the content type to 'text/xml' instead.
You will also have to build up the body as a multipart mime object. The answers to this question seem to have some code for that: File Upload to HTTP server in iphone programming
Your other option, since you have complete control of the client, is to do an HTTP PUT request. That actually looks closer to what you were doing with your original code. Change the method to 'PUT', and don't use a Django form on the other end; just access request.raw_post_data to get the complete file data.

ASIHTTPRequest Returning HTML instead of JSON

I am using ASIHTTPRequest to contact an API the problem is that it is returning html instead of JSON and i have no idea why. Everything has been working great for weeks and i can't seem to figure out what has broken..
What's strange is doing exactly the same request with a browser or postie returns the correct JSON response, but when i do the request via ASIHTTPRequest these are the response headers i get:
"Cache-Control" = "private, max-age=0, must-revalidate";
Connection = "keep-alive";
"Content-Encoding" = gzip;
"Content-Type" = "text/html; charset=utf-8";
Date = "Tue, 05 Jul 2011 21:11:10 GMT";
Etag = "\"e467792713ac4124f055c1719f4ea6c2\"";
Server = "nginx/0.7.65";
Status = "200 OK";
"Transfer-Encoding" = Identity;
"X-Runtime" = 1;
And the html (which should be json)..
<div id="universal_meta" logged_in_user_id="removed" style="display:none"></div>
<div id="meta" screen="projects" logged_in_as="removed"></div>
<h1>9 projects with 50 open issues</h1>
<ul class="biglinks progressbars">
etc...
Here is the code used to do the request..
NSURL *url = [NSURL URLWithString:path];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
if(secure){
[request setUsername:self.username];
[request setPassword:self.password];
}
[request setDelegate:self];
[request setDidFinishSelector:#selector(requestDone:)];
[request setDidFailSelector:#selector(requestWentWrong:)];
[request setDownloadDestinationPath:destination];
[[self queue] addOperation:request]; //queue is an NSOperationQueue
I have triple checked all of the login details/url, everything is correct, i would really appreciate any help with this one as i am completely lost.
--
Update:
Lighthouse have acknowledged a bug regarding headers on their side. Waiting on a solution from them.
Did you check that the headers sent using your browser are also the same as when you send the request by code?
Especially did you try to add the "Accept" header to your request to define that you accept the json Content-Type?
[request addRequestHeader:#"Accept" value:#"application/json"];
Try using a tool like wireshark or charlesproxy to compare the working requests from your browser/postie, and compare them to the non-working requests from ASIHTTPRequest - once you spot what's different it should be easy to fix.
AliSoftware's suggestion is one of the most likely differences you'll see, but it's possible there are other things too.