HTTP Post - Time Out - Multiple Request getting initiated within timeout interval - ios

I am using HTTP Post method and initiating a synchronous request.
[NSURLConnection sendSynchronousRequest: ..]
For HTTP POST requests, the default time out is happening at 75 seconds as discussed in many threads.
But during that time out period of 75 seconds, Multiple web service requests are getting initiated for us for the same request raised with all the same parameters.
Please let us know What causes this multiple requests to get initiated? Is this due to HTTP POST in general or because of Synchronous request?
#iOS Sample Code
[body appendData:[[NSString stringWithFormat:#"\r\n--%#--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
[request addValue:[NSString stringWithFormat:#"%d", body.length] forHTTPHeaderField: #"Content-Length"];
[[NSURLCache sharedURLCache] setDiskCapacity:0];
[[NSURLCache sharedURLCache] setMemoryCapacity:0];
NSURLResponse *response;
response = nil;
urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(urlData)
{
NSString *responseString = [[NSString alloc] initWithData:urlData encoding:NSASCIIStringEncoding];
[self parseStringInformation:responseString infoDict:informationDictionary];
//NSLog(#"%#",responseString);
}

Without the server's request-response logs there are several possibilities.
Programmer Error: Have you already gone through all of "gotchya" type situations?
Have you put a logging message right before your "urlData = [NSURLConnection sendSynchronousRequest: ..." line to make sure your code is only calling it once?
Are you calling this function from within your main GUI thread, if you are that's not supported/recommended, which means it could be causing side-effects like what you're describing. https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html
Are you sure your Request is set up as a POST and has the proper headers like "Content-type: multipart/form-data, boundary=X"
Web Server Responses: Without the web servers logs (or the code for the service your POSTing to) it's hard to say...
Perhaps your server is sending cyclical redirects to the client. If you don't implement a "connection:willSendRequest" then the redirects could be followed for ?X? amount of times for one request. http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/urlloadingsystem/Articles/RequestChanges.html
API Error: You've found some corner case which is causing unwanted side effects. Maybe apple has an bug tracker or developer support forum?
If this is the case you'll have to work around the bug, until it's fixed. I suggest implementing the Asynchronous call chain. "Loading Data Asynchronously" https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html

Related

iOS sending a POST and GET in the same request

I am successfully posting data as follows:
NSMutableURLRequest *scriptrequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"myurl.com"]];
[scriptrequest setHTTPMethod:#"POST"];
NSString *sendData =[NSString stringWithFormat:#"ID=%#&action=List", ID, nil];
NSData *scriptdata = [sendData dataUsingEncoding:NSUTF8StringEncoding];
[scriptrequest setHTTPBody:scriptdata];
NSError *scripterr;
NSURLResponse *scriptresponse;
NSData *scriptResponseData = [NSURLConnection sendSynchronousRequest:scriptrequest returningResponse:&scriptresponse error:&scripterr];
My question is, is it possible to also attach GET data to the same call?
GET and POST are different types of HTTP Request.
GET Request is majorly used for fetching the web content while POST is for insert/update some content.
So eventually A single HTTP request can only be of one of the following.
Http types include:
GET
HEAD
POST
PUT
DELETE
TRACE
OPTIONS
CONNECT
PATCH
More technical details at Wikipedia:
http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
It looks to me like you are trying to retrieve data from your server, not update. A more typical way to form the request would be to GET http://myurl.com?ID=123&action=List. However, this really depends on how the server code is written.

Random latency between headers and body of POST

We're using NSUrlConnection sendAsynchronousRequest to send simple POST requests to our Node JS server. Through analyzing tcpdumps, we've noticed that sometimes the request headers and request body are split into 2 separate TCP packets.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:url]];
[request setTimeoutInterval:3];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[request setHTTPBody:postData];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler: ^(NSURLResponse *response, NSData *POSTReply, NSError *error) { }];
The problem is that occasionally the headers are sent to the server, which opens a connection to our API, and then multiple seconds later the body packet is sent. We're seeing a > 1 second delay between headers and body, randomly every hundred requests on the server side. It's the single largest source of latency on our API.
For the majority of requests, headers and body are about the same size (200 bytes each).
Has anyone seen this before?
I don't have concrete insights on the swift APIs (NSUrlConnection etc.) but in general, while the HTTP data is sent in chunks of large size (which can accommodate the 200 bytes in one packet), more granular decisions are taken at the underlying TCP level, which may decide to split these into chunks of lesser sizes.
I have observed this in node (sending side as well as receiving side) on specific platforms (such as AIX) where the packets are split at illogical boundaries by TCP. By TCP specification, applications should not rely on specific order or size of the low level data transport, it guarantees the data integrity at the final stage.
One suspect would be the presence of Nagile's algorithm in the TCP.
I would also recommend to change the client to another platform (such as Linux) and compare the behavior, if it is easy to port the code.
Hope this helps.

NSURLConnection Authorization Header not Working

I am trying to send an OAuth access token in an HTTP header via NSURLConnection but it doesn't seem to be sending the header because the API keeps giving me an error saying that "must provide authorization token".
This is the code that I am using:
NSURL *aUrl = [NSURL URLWithString: #"http://generericfakeapi.com/user/profile"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
[request addValue:[NSString stringWithFormat:#"OAuth %#", token] forHTTPHeaderField:#"Authorization"];
[request setHTTPMethod:#"GET"];
NSError *error = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error: &error];
NSDictionary *JSONDictionary = [NSJSONSerialization JSONObjectWithData:returnData options:kNilOptions error:&error];
NSLog(#"Response : %#", JSONDictionary);
And this is an example of the cURL command for the API:
curl 'http://generericfakeapi.com/user/profile' -H 'Authorization: OAuth YourAuthToken'
Is this not what I am essentially doing through NSURLConnection?
Any help would be appreciated.
Change this line:
NSURL *aUrl = [NSURL URLWithString: #"http://generericfakeapi.com/user/profile"];
To:
NSURL *aUrl = [NSURL URLWithString: #"http://generericfakeapi.com/user/profile/"];
Apparently iOS drops the Authorization header if there isn't a slash at the end of a URL. This problem literally cost me my sleep for two days.
#isair's answer is truly a lifesaver.
Just to add on the root cause if you're interested:
NSURLRequest defines a set of reserved HTTP headers. And surprisingly, Authrorization is part of it.
The URL Loading System handles various aspects of the HTTP protocol for you (HTTP 1.1 persistent connections, proxies, authentication, and so on). As part of this support, the URL Loading System takes responsibility for certain HTTP headers:
Content-Length
Authorization
Connection
Host
Proxy-Authenticate
Proxy-Authorization
WWW-Authenticate
If you set a value for one of these reserved headers, the system may ignore the value you set, or overwrite it with its own value, or simply not send it. Moreover, the exact behavior may change over time. To avoid confusing problems like this, do not set these headers directly.
In #isair's case, it's highly likely that URLs without a trailing slash had triggered such "filtering" behaviour. This maybe an inconsistency in the implementation but we don't have access to the source code to verify that.
In my case, I was writing a React webapp that uses Authorization header to authenticate with the backend Django server. The app behaved perfectly on desktop Chrome but always failed to access login-required APIs on the iPhone (both Safari and Chrome), due to the missing Authorization header.
The ideal solution is to avoid using Authorization at all. But if you're communicating with a backend framework that specifically requires it (e.g. Django Rest Framework's token authentication). #isair's answer can be a good workaround.
For me it look fine. Are you sure you gave a valid token?
Try catch the error like this
if (error) {
NSLog(#"error : %#", error.description);
}
My code work well :
NSURL *jsonURL = [NSURL URLWithString:[NSString stringWithFormat:#"http://....ID=%i", cellID]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:jsonURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:120.0];
[request setValue:#"Basic ...." forHTTPHeaderField:#"Authorization"];
NSURLResponse *response;
NSError * error = nil;
NSData *POSTReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
hope it helps
I had same problem. In my case I changed "http" to "https" and everything works fine

What is the easiest way to make an HTTP GET request with IOS 5?

I am trying to send a suggestion from my app to a php file on my web server, I have tested the php script in my browser which sends an email to the user and stores the suggestion in my database, which all works fine.. And when running the following script I get a successful connection via IOS however i do not receive the results in my database..
NSString *post = [NSString stringWithFormat:#"http://blahblah.com/suggest.php?s=%#&n=%#&e=%#", suggestion, name, email];
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:post]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
NSLog(#"Connection establisted successfully");
} else {
NSLog(#"Connection failed.");
}
I have checked all the strings and encoded all spaces with %20 etc.. Can anyone see any glaringly obvious reason why my script won't work?
What is the easiest way to make a HTTP request from my app without opening safari?
You problem is that you're creating the connection, but are not sending the actual "connect" request. Instead of
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
try using this piece of code:
NSURLResponse* response = nil;
NSData* data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:nil]
This is quick and dirty solution, but keep in mind that while this connection is in progress, your UI thread will appear to be frozen. The way around it is to use asynchronous connection method, which is a bit more complicated than the above. Search web for NSURLConnection send asynchronous request - the answer is there.

How to write data to the web server from iPhone application?

I am looking forward for posting some data and information on the web server through my iPhone application. I am not getting the way to post data to the web server from iPhone sdk.
It depends in what way you want to send data to the web server. If you want to just use the HTTP POST method, there are (at least) two options. You can use a synchronous or an asynchronous NSURLRequest. If you only want to post data and do not need to wait for a response from the server, I strongly recommend the asynchronous one, because it does not block the user interface. I.e. it runs "in the background" and the user can go on using (that is interacting with) your app. Asynchronous requests use delegation to tell the app that a request was sent, cancelled, completed, etc. You can also get the response via delegate methods if needed.
Here is an example for an asynchronous HTTP POST request:
// define your form fields here:
NSString *content = #"field1=42&field2=Hello";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.example.com/form.php"]];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:[content dataUsingEncoding:NSISOLatin1StringEncoding]];
// generates an autoreleased NSURLConnection
[NSURLConnection connectionWithRequest:request delegate:self];
Please refer to the NSURLConnection Class Reference for details on the delegate methods.
You can also send a synchronous request after generating the request:
[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
If you pass a NSURLResponse ** as returning response, you will find the server's response in the object that pointer points to. Keep in mind that the UI will block while the synchronous request is processed.

Resources