I'm creating an iPhone app that consumes a json webservice. I have an NSURLRequest and NSURLConnection object that are used to load JSON data from that webservice:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
initWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:30];
[request setHTTPMethod: #"POST"];
//[request setHTTPShouldHandleCookies:YES];
//create connection
NSURLConnection *connection = [[NSURLConnection alloc]
initWithRequest:request delegate:self];
[connection start];
First time I executed the above code, using as the url "admin.mydomain.com/param1/value1/param2/value2", the response came through correctly (a JSON string: {"Wrong API Key"}).
I then changed the url to my staging server: "admin.stg.mydomain.com/param1/value1/param2/value2". This server provides me with some completely different output (when I try that new url in a browser, the correct output is shown, a json object completely different from what the first url gives me), but in my iphone app I still get the exact same response I got from the other server. If I try non existent urls I do get a correct error message.
It just seems to have cached the result from the original server and returns the same value for my stg subdomain, somehow matching the two urls (is this possible?), but I have cleared all caching data I could find. I have tried to clean the build and build directory, restarted xcode, the computer and everything, the cache policy is set to ignore the cache (see code). Important: I get the same behavior on my actual iPhone, not just the simulator.
Does anyone have any idea what could cause this kind of behavior? Am I forgetting something obvious?
I have been looking at this for hours on end now, any help is greatly appreciated!
I have changed the request method to 'GET', now I get the expected results! When checking the url in the browser a get request is used, when posting it I get a different response, which happens to be exactly the same as what I get on the dev server. Problem solved, just have to make some adjustments to the backend to allow a post request!
Related
I want to stream audio file from a source that needs OAuth2 authentication, this is my code, but it is not working.
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[req setValue:[NSString stringWithFormat:#"Bearer %#", accessToken] forHTTPHeaderField:#"Authorization"];
player = [AVPlayer playerWithURL:req.URL];
[player play];
Can you please help?
The issue is that you're adding your authentication token as an HTTP header, but then making a request using only the URL (and headers are not included in the URL).
I need to do a similar thing in my app, but it doesn't look like it's possible to interfere with AVPlayer's network request (at least, not with a public API). So now I'm looking at either requesting the file myself using NSURLSession (which means no streaming - gotta wait for the whole file, or else do some complicated processing to hand it off to an audio player in chunks), or else fudge the web service to accept my parameter as a query parameter instead of as an HTTP header.
This question also has some potential work-arounds: Send headers with AVPlayer request in iOS
As soon as, I send request to the server (via NSURLConnection sendSynchronousRequest method), the server receives it in about 2 seconds, it processes and sends back response in another 3-5 seconds. However, I only get back the response in 30-35 seconds. This delay makes our communication very slow.
Even the async APIs are getting a delayed response.
Earlier, everything was working fine, with client getting the response back within 10 seconds.
Anyone else having this issue? What could be the reason?
EDIT
here is a screenshot of Wireshark analysis:
Link to a better image
How should I see what packet is saying what?..and why is it getting delayed?
EDIT2
Here is the code:
NSHTTPURLResponse *response=nil;
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:nsURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:180.0];
[theRequest setHTTPMethod:#"POST"];
[theRequest setTimeoutInterval:180.0];
[theRequest setHTTPBody:[[NSString stringWithFormat:#"%#",sdata] dataUsingEncoding:NSASCIIStringEncoding]];
NSError *error= nil;
NSData *result = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
if (error ) {
NSLog(#"error sending synchronous request: %#", error);
}
NSLog(#"request completed with code:%d",response.statusCode);
I'd avoid calling sendSynchronousRequest. Use the asynchronous version instead if you're not doing the call already on a background thread (you don't want to block the UI thread).
How do you know when the iOS response is received? An NSLog? A UI state change?
See also these questions:
NSURLConnection sendSynchronousRequest - background to foreground
NSURLConnection sendSynchronousRequest taking too much time to respond
Update
If you're a bit stuck, one strategy might be to rule out the use of NSURLConnection as the problem.
Strategy 1: try using NSURL's asychronous connection call instead of synchronous
Strategy 2: try using a different HTTP lib, such as AFNetworking
If you want to take a closer look at what is going on with the HTTP connection, you can use tools such as Charles, Fiddler or Wireshark to debug what data is being sent and received. To get the most benefit from this sort of analysis, you need to have some knowledge of the HTTP protocol(s). This is probably more time consuming than the previously mentioned strategies.
See also questions such as How to monitor network calls made from iOS Simulator.
Update
Are you accessing a webserver of your own, or is it someone else's?
Have you had a close look at the headers being sent to your webserver (and the ones being returned)? Pay attention to the content length, for example. Wrong content length can cause a delay, as explained here.
To see the request and returned headers, you could use Firebug, or something like wget or curl on the command line.
Also, double check that there's not a newline on the end of your URL, as described here.
Solution that worked for me:
In the request headers, iOS sets "gzip" for "Accept-Encoding" by default. The gzip compression was taking a lot of time, and hence the delayed response. I did the following to solve the problem:
[theRequest setValue:#"" forHTTPHeaderField:#"Accept-Encoding"];
NOTE: Check your headers, for any response delay.
Thanks to #occulus for directing me to the request headers!
You do this over wifi or celluar?
Speaking from my experience, when my data useage is exeeded my phone-provider slows down my downloads. Sometimes this happen to me at the end of the month after I did use a lot of mobile data.
I am not sure to say but it may be network problem first check it. it proper or down ?? okay Maybe I will be wrong.. but first check it...
Following describe code it might solve your problem :)
NSString *url = #"Your URL ";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
NSMutableData *body = [NSMutableData data];
.
.
/// Add Here Your NSMutableData Valuew
.
.
[request setHTTPBody:body];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (theConnection)
{
self.responseData = [[NSMutableData alloc] init];
}
else
NSLog(#"Connection Failed!");
To ease your problems with asynchronous HTTP Request you should consider using the AFNetworking framework
I'm currently working with a PHP developer to set up some server-side code, however, I'm not sure how to send the server API information to be stored in a database. He has asked me to send it in a url like this: exampleserver.com/register?deviceToken=[deviceToken]&otherstuff[otherStuff]. I have no problem with creating the URL string, my issue is actually doing something with it. I know this is a pretty stupid question, but I'm pretty new to Objective-C let alone communicating with servers! I have pulled information from servers using NSURLRequest and AFJSONRequestOperation before. Is it the same idea or are we no longer doing Requests? I've seen the word Post around a couple of times, but I'm unsure if this is what I'm after. Any help clearing this up would be really appreciated. Also, whatever the solution, I need it to be asynchronous!
Thanks for the help,
Regards,
Mike
This works for me:
NSURL *aURL = [NSURL URLWithString:#"http://www.google.co.uk/search?hl=en&q=hello%20world"];
NSURLRequest *aURLRequest = [NSURLRequest requestWithURL:aURL];
[NSURLConnection sendAsynchronousRequest:aURLRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
NSLog(#"response=%#", response);
NSLog(#"data=%#", data);
NSLog(#"error=%#", error);
}];
The URL you show has data tacked onto the end of the URL, which is normally done with a http GET operation, the "normal" method. Just asking for the page at that URL is enough to send the data to the server. An http POST operation is typically used to send form data to a server, where the pairs like deviceToken=<deviceToken> are transferred in the body of the message rather than the URL. The advantage of that is typically that the body will be encrypted if the connection is https:, so the data stays secure. But for a simple insecure transaction, using a GET with the parameters in the URL is fine. There's a description of a POST transaction at iOS: how to perform a HTTP POST request?
NSURLRequest still works and is fine. If you want a more powerful library that handles post, get, put etc. and can work asynchronously and link directly to core data, I recommend RestKit (https://github.com/RestKit/RestKit).
For more on NSURL, see my answer here: NSURLConnection delegate method
I am wondering what the difference between Get and Post with asihttprequest library..
Is this a GET?
- (IBAction)sendHttpsRequest
{
//Set request address
NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:#"https://142.198.16.35"];
//call ASIHTTP delegates (Used to connect to database)
NSURL *url = [NSURL URLWithString:databaseURL];
//This sets up all other request
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
is a post when you try to set elements say within a php document? any examples would be awesome!
http://www.cs.tut.fi/~jkorpela/forms/methods.html
An HTTP GET is a request from the client to the server, asking for a resource.
An HTTP POST is an upload of data (form information, image data, whatever) from the client to the server.
What you have there is an HTTP POST.
-EDIT:
Per http://allseeing-i.com/ASIHTTPRequest/:
ASIFormDataRequest
A subclass of ASIHTTPRequest that handles x-www-form-urlencoded and multipart/form-data posts. It makes POSTing data and files easy, but you do not need to add this to your project if you want to manage POST data yourself or don’t need to POST data at all.
My bad, this one was a POST, not a GET. The rest of my answer was valid, though :)
That is a POST request, which is the default for ASIFormDataRequest. The difference is the same as it would be in a normal HTTP request. You can read about that here if you don't already know.
In general, if you are just downloading a web page and do not need to send any variables to the server, a GET request is sufficient. If you want to send variables in your request, often times a POST request is the way to go since it is a bit more secure and less transparent.
I am doing an application in which I am uploading the images to twitpic. It works fine the first time. But if I try to upload the next image within that minute itself, it shows a 401 error. If I try again after waiting for a minute, it gives a 200 response and works fine. Why is this happening? Can I send images continuously to twit pic without any interruption?
Well the documentation of TwitPic states that there is 500 call limit on the API.
And the 401 will happen only if you do supply the correct Auth header.
My guess is that there is something wrong with the auth header, it might be due to caching.
If you use NSURLConnection nochache paramter:
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];