AFNetworking PUT and Delete with Rails - ruby-on-rails-3

In looking at the AFNetworking documentation, the Put and Delete methods take in a path and a dictionary of parameters. I am using Rails as my backend which expects these two types to take the form of Put /object/1.json and Delete /object/1.json. Should I build up a path string by adding in the Id or do I send a Put or Delete with the Id as one of the params in the Dictionary?

Typically when I do with PUT and similar type HTTP requests when using AFNetworking is something like this:
// Create an HTTP client with your site's base url
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"http://example.com"]];
// Setup the other parameters you need to pass
NSDictionary *parameters = #{#"username" : #"bob", #"password" : #"123456"};
// Create a NSURLRequest using the HTTP client and the path with your parameters
NSURLRequest *request = [client requestWithMethod:#"PUT" path:#"object/1.json" parameters:parameters];
// Create an operation to receive any response from the server
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// Do stuff
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
// Handle error
}];
// Begin the operation
[operation start];
If you look in AFHTTPClient.h there are examples for how to format your base url and your paths. There's more information on these methods in the AFNetworking documentation

Related

cached image Date in AFImageRequestOperation

I'm using AFImageRequestOperation to download hundreds of jpg from my server.
NSURLRequest *request = [NSURLRequest requestWithURL:theURL cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:20];
AFImageRequestOperation *operation;
operation = [AFImageRequestOperation imageRequestOperationWithRequest:request
imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {}
];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:[[paths objectAtIndex:0] stringByAppendingPathComponent:picture] append:NO];
[downloadQueue addOperation:operation];
If I delete them all (removing all images in Documents Folder) and start download again, the first X (depends on how far I got during last download process) operations are processed immediately. It seems like the images downloaded from the previous process are stored (cached) somewhere. I also checked the Documents Folder for the simulator and the images are downloaded correctly. So how can I make sure the download process really starts from the beginning?
When you're creating the NSURLRequest, use this instead:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:theURL];
request.cachePolicy = NSURLRequestReloadRevalidatingCacheData;
This policy is described in the docs the following way: Specifies that the existing cache data may be used provided the origin source confirms its validity, otherwise the URL is loaded from the origin source.
You can check the cache policies of NSURLRequest here.

Basic and OAuth Authentication headers at the same time

Is it possible to use Basic and OAuth authorization headers in the same request with AFNetworking (avoiding the overwriting) ?
I have this code:
NSURL *url = [NSURL URLWithString:#"https://www.infojobs.net/"];
AFOAuth2Client *OAuthClient = [[AFOAuth2Client alloc] initWithBaseURL:url clientID:kClientID secret:kClientSecret];
[OAuthClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[OAuthClient authenticateUsingOAuthWithPath:#"oauth/authorize" code:self.authorizationCode redirectURI:kInfoJobsRedirectURLString success:^(AFOAuthCredential *credential) {
NSLog(#"Credentials: %#", credential.accessToken);
if (![credential.accessToken isEqualToString:#""]) {
self.isAuthenticated = YES;
[AFOAuthCredential storeCredential:credential withIdentifier:#"kInfoJobsAccessToken"];
[[InfoJobsAPI sharedClient] setAuthorizationHeaderWithToken:credential.accessToken];
// (!) This overwrites the Authorization header set with the accessToken
[[InfoJobsAPI sharedClient] setAuthorizationHeaderWithUsername:kClientID password:kClientSecret];
success(credential);
}
} failure:^(NSError *error) {
NSLog(#"Error: %#", error.localizedDescription);
}];
And I need a request like this:
GET /api/1/application HTTP/1.1
Host: api.infojobs.net
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Authorization: OAuth 07d18fac-77ea-461f-9bfe-a5e9d98deb3d
....
But I can't set the "Basic" and "OAuth" Authorization headers in the same request because AFNetworking seems to overwrite this header as seen in documentation
It's possible to use "Basic" and "OAuth" in a same Authorization header, maybe splitting both with a "\n" ?
Thanks, and sorry for my poor english
Edit
Finally, I can use the "Basic" and "Oauth" authentications in the same header, this is the code:
[[InfoJobsAPI sharedClient] setAuthorizationHeaderWithUsername:kClientID password:kClientSecret];
AFOAuthCredential *credential = [AFOAuthCredential retrieveCredentialWithIdentifier:#"kInfoJobsAccessToken"];
NSMutableURLRequest *request = [self requestWithMethod:#"GET" path:#"/api/2/candidate" parameters:nil];
[request addValue:[NSString stringWithFormat:#"OAuth %#", credential.accessToken] forHTTPHeaderField:#"Authorization"];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
DLog(#"Response : %#",JSON);
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
DLog(#"Error : %#",error);
}];
[operation start];
According to the HTTP specification there can be only one Authorization header in a request. So the behavior the library is showing is correct according to that specification: the second call to setAuthorizationHeader... overwrites the previous one.
What you'll typically see in HTTP is that there is a handshaking phase, where the server tells the client what authorization protocols it can accept. The client can then choose from those protocols, which one it wants to use.

How would i create a GET method to a webserver with AFNetwork

I was wondering how i would get AFNetworking code to visit a link on my web server(PHP Script) and get the response data, and put it into a string?
Could anyone post an example of this?
Thanks alot!
here is the required code to get response from server using AFNETWorking.Just add AFNetworking Library and the Required frameWorks.After that use the below code.
NSURL *url = [[NSURL alloc] initWithString:#"http://itunes.apple.com/search?term=harry&country=us&entity=movie"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"JSON");
self.movies = [JSON objectForKey:#"results"];
[self.tbleView reloadData];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
self.movies is name of mutable Array you can use any name instead of this.
Also you can check here
https://github.com/AFNetworking/AFNetworking
AFHTTPRequests get passed default NSURLRequest objects. stock ones - no modification for AFNetwork
to build THAT see
How to add GET parameters to an ASIHttpRequest?

can't access self?

In this function I get xml through a kiss xml function called AFKissXMLRequestOperation. But since it is void, I can't access the XMLDocument unless I NSLog it, but that isn't useful when I need to access the XML. So, I try to set it as a variable of self in order to access it in other functions. If I NSLog self.xmlDocument inside of the block, it works. But, when I NSLog it outside the block in the call NSLog(#"self!%#", [self.xmlDocument XMLStringWithOptions:DDXMLNodePrettyPrint]); it is NULL. So how can I access self.XMLDocument?
-(id)xmlRequest:(NSString *)xmlurl
{
AFKissXMLRequestOperation* operation= [AFKissXMLRequestOperation XMLDocumentRequestOperationWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:xmlurl]] success:^(NSURLRequest *request, NSHTTPURLResponse *response, DDXMLDocument *XMLDocument) {
NSLog(#"kiss operation %#", [XMLDocument XMLStringWithOptions:DDXMLNodePrettyPrint]);
self.xmlDocument=XMLDocument;
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, DDXMLDocument *XMLDocument) {
NSLog(#"Failure!");
}];
[operation start];
NSLog(#"self!%#", [self.xmlDocument XMLStringWithOptions:DDXMLNodePrettyPrint]);
return self.xmlDocument;
}
NSURLRequest performs asynchroneously, so you will have to review either the way your code is organised, or using a synchroneous network operation.
The error in your above code is that since NSURLRequest performs asynchroneously, the
NSLog(#"self!%#", [self.xmlDocument XMLStringWithOptions:DDXMLNodePrettyPrint]);
return self.xmlDocument;
is performed before the operation has finished, thus returning nil.
Do you really need to return xmlDocument ? I don't think so, because you set it as a property. My guess is that in the success block, (where you set self.xmlDocument=XMLDocument; ) you could actually process the xmlDocument as you want to or call a method that do such.
Hope that helps
I believe AFKissXMLRequestOperation is an asynchronous operation, so you should do what you need to do with the response inside the success block. The success block can certainly call another function if you wish to keep the response handling separate. If you need to pass the response back to another class, you can do that by setting up your own delegate protocol / property or by using blocks yourself:
The delegate protocol:
#protocol XMLResponseHandlerDelegate <NSObject>
- (void)handleResponseXML:(XMLDocument *)xmlDoc;
#end
And then call it:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:xmlurl]];
AFKissXMLRequestOperation* operation= [AFKissXMLRequestOperation XMLDocumentRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, DDXMLDocument *xmlDocument)
{
NSLog(#"kiss operation %#", [XMLDocument XMLStringWithOptions:DDXMLNodePrettyPrint]);
[self.delegate handleResponseXML:xmlDocument];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, DDXMLDocument *XMLDocument)
{
NSLog(#"Failure!");
}];

How to pass JSON request

I am new to AFNetworking framework. I try to send JSON request to the server to get JSON response, so i tried something like this:
NSURL *url = [NSURL URLWithString:#"http://data.mycity.gov/api/views/INLINE/rows.json?method=index"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:[NSString stringWithFormat:#"application/json"] forHTTPHeaderField:#"Content-Type"];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Success");
} failure:^(NSURLRequest* req,NSHTTPURLResponse *req2, NSError *error,id mex) {
NSLog(#"Failed");
NSLog(#"%#",[error description]);
}];
[operation start];
So i always find my self into the failure block, with this error description:
Error Domain=com.alamofire.networking.error Code=-1011 "Expected status code in (200-299), got 400" UserInfo=0x7b58030 {NSErrorFailingURLKey=http://data.mycity.gov/api/views/INLINE/rows.json?method=index, NSLocalizedDescription=Expected status code in (200-299), got 400}
Any ideas? am i missing something?
Status Code of 400 means - Bad Request
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
When I try to go to that URL:
http://data.mycity.gov/api/views/INLINE/rows.json?method=index"
, I get a not found error
Make sure the API you are using is correct, if the web service returns JSON, you should be able to type that URL into your browser and get a JSON response.
It seems your server is returning 400, "Bad Request". Check that your URL is correct.
BTW your stringWithFormat is redundant. You can replace
[NSString stringWithFormat:#"application/json"]
with
#"application/json"