File Cache between AFNetworking 2.0 and Nginx - ios

iOS client:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"host/json/demo.json"
parameters:parameters
success:^(AFHTTPRequestOperation *operation, id responseObject) {
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
Nginx conf on server:
location /json {
alias /var/www/json;
expires 30s;
}
First time I run the app and get json data from server correctly, then I modify the demo.json on server, restart the app, I still get old json data(even 30 second later), but using CURL commend in terminal I can get new json data.I delete the app and reinstall it then I get new json data.
Any problem with my conf or code?

Your server's response to your GET request contains cache-control HTTP headers, causing the foundation URL loading system to cache your request. See the NSURLCache Class Reference (and this NSHipster article about it) to learn more.
During debug, you could temporarily disable the cache:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0
diskCapacity:0
diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
But this is absolutely not recommended for use in most production apps, since caching is very important to network performance on mobile devices.
If there are specific resources that should not be cached, the server should indicate these using the cache-control headers.

The method GET:parameters:success:failure is always using cache by default, so I changed to use custom AFHTTPRequestOperation without cache, like this:
NSURL *URL = [NSURL URLWithString:filePath];
NSMutableURLRequest *request = [[NSURLRequest requestWithURL:URL] mutableCopy];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
[[NSOperationQueue mainQueue] addOperation:op];

Related

AFNetwoking POST call returns 500 internal server error but server got request parameter

I'm trying to upload my payment success message to my server. Below are my code
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] init];
[manager.requestSerializer setValue:[NSString stringWithFormat:#"Bearer %#",myTokenString] forHTTPHeaderField: #"Authorization"];
AFHTTPRequestOperation *operation = [manager POST:#"MYAPI" parameters:paramsDict success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#",error.localizedDescription);
}];
[operation start];
But I'm getting error code 500 (internal server error). But my server has all the information and API call is success. Can anyone please help me understand why it's entering the error block?
In new AFNetworking version, you don't need a initialize for AFHTTPRequestOperation class to handle request so you just adjust your code as following:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:[NSString stringWithFormat:#"Bearer %#",myTokenString] forHTTPHeaderField: #"Authorization"];
[manager POST:#"MYAPI" parameters:paramsDict success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#",error.localizedDescription);
}];
By default requestSerializer is set to an instance of AFHTTPRequestSerializer, which means that Content-Type of your request will be application/x-www-form-urlencoded.
But if your server requires application/json content type for that api, then you must set to an instance of AFJSONResponseSerializer
E.G.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
Encode your url.
NSString *unescaped = #"http://www";
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
Try with formData
[manager POST:#"API" parameters:paramsDict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
} progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
it's AFNetworking 3.0 Method, but you can used same (formData) in AFNetworking 2.x
I had been encountering the same issue with AFNetworking POST as well as sometimes on GET calls but... Sometimes i would get a 500 internal server error although the server received request parameters!! Finally after some research with my web services backend developers, i came to know that its caused due to a DLL misconfiguration on the server side, particularly the System.reflection DLL file. Deleting the file from the server side (if it exists) removes the issue, otherwise copy pasting it back from the Bin (if it doesn't exist already) removes the issue. This is pretty baffling but apparently it fixes it!!
AND YES. IT HAS NOTHING TO DO WITH AFNETWORKING!
The answer assumes Microsoft azure server
Try to see what the detail accept/content type is for android. Do you know if they are using retrofit? Most likely it will have to do with your request or response serializer not matching what server is expecting.
Add the below coding to AFURLResponseSerialization.m file and remove the existing code.
#implementation AFJSONResponseSerializer
self.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript",#"application/xml",#"text/html", nil];
return self;

AFNetworking issue with UStream API request for channel's video list

This is probably something simple that I am just overlooking. I am trying to make an AFHTTPRequest from uStream's API using AFNetworking. I should be getting a JSON payload response back that lists all the videos on a uStream Channel. Here is my code:
NSURL *url = [NSURL URLWithString:#"https://api.ustream.tv/channels/12321320/videos.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"failed");
}];
[operation start];
Everything works fine when testing in a browser but when trying to use AFNetworking I get a NSURLErrorDomain failure. Anyone have any suggestions?
My code was fine but there was an issue with my iphone simulator. Reset Content and Settings did the trick. Thanks to k6sandeep for the help.

Batch GET requests in AFNetworking 2.0

I'm running AFNetworking GET requests in a loop. The "codeArray" has 8000 odd elements. However, AFNetworking makes only about ~1000 requests and stops abruptly. Anyone know what the problem could be? Is there a way I can make sure AFNetworking makes all the server calls without being interrupted?
for(NSString *station in codeArray)
{
[self getLocationForStation:station
success:^(NSDictionary *response) {
} fail:^{
}];
}
The function that makes the GET calls using AFNEtworking looks like
- (void)getLocationForStation:(NSString *)stationCode
success:(void (^)(NSDictionary *response))success fail: (void (^)())fail
{
NSString *urlString = [NSString stringWithFormat:#"http://myurl.in/station-details/%#.json", stationCode];
NSURL *url = [NSURL URLWithString:urlString];
url = [url URLByAppendingQueryString:[NSString stringWithFormat:#"_=%f", [[NSDate date] timeIntervalSince1970]]];
IRCTCHTTPRequestOperationManager *manager = [IRCTCHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:#"application/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager GET:[url absoluteString] parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
success(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// NSLog(#"Failure!!");
}];
}
Yikes! 8000 is a lot of simultaneous requests! That's almost over 9000!!!! I would throttle your requesting instead of figuring out why you can't do 8000 at the same time.
Luckily, NSOperationQueue makes that relatively easy to do for asynchronous operations. Here is a page that has a nice summary of how to do this: Concurrent Operations Demystified

AFNetworking and id reponseObject NOT working and not able to recover the content

After few days of job I am not able to solve this issue, I really need your help because I am completely locked, I start to be crazy!!!!!!. I have a project in Objective c for iOS where I get data from my server to put in my application. I have some trouble to recover and save data from JSON.
I would like to use "id responseObject", and save and use the content in another area in my project. Each time I try to use the following method and use "id responseObject" outside of "setCompletionBlockWithSucess" the "id responseObject" is (null), how can I do ?
NSURL *URL = [NSURL URLWithString:#"…."];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[[NSOperationQueue mainQueue] addOperation:op]
It sounds like you don't quite understand what scope is for variables. This project may be too advanced for you if that's the case. I urge you to read into scope + blocks to get a better understanding of what's going on.
What is happening is the setCompletionBlockWithSuccess is actually a block of code that gets executed if the URL request is a success. This means that responseObject is not immediately executed! It's being passed back some time after and you get access to it within setCompletionBlockWithSuccess. So that's why it's nil outside of the block.
To do what you're wanting is very simple. You need to read responseObject within the setCompletionBlockWithSuccess and set it to another variable that you have access to. Or you can immediately send it to another class to parse/save.
I haven't tested it, but I believe this should work with a simple JSON response. If not, use operation.responseString instead
NSString *jsonResponse;
NSURL *URL = [NSURL URLWithString:#"…."];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
jsonResponse = responseObject;
}
...

Requirements on connecting to https

I'm trying to connect using AFNetworking to API that is under https address. I keep getting 404 since the old app, based on ASIHTTPRequest is able to connect.
Do I have to implement certificate file into app somehow? What else should be provided?
Basically you have to add nothing, you only need to add http basic auth credentials if needed. This is how i usually connect to a https api with http basic auth.
//Base URL
NSURL *requestPasswordURL = [NSURL URLWithString:BASEURL];
//Http client with server credentials
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:requestURL];
[httpClient setAuthorizationHeaderWithUsername:#"user" password:#"password"];
//Set request parameters for example email
NSDictionary *params = #{#"email": email};
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:API_REQUEST parameters:params];
request.cachePolicy = NSURLRequestReloadIgnoringCacheData;
//Prepare request
AFHTTPRequestOperation *request = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[requestPasswordOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//Your code
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//Your Code
}];
//call start on your request operation
[request start];

Resources