A quick question. I have the following code which gets the mod date of a file on a server:
- (void) sendRequestForLastModifiedHeaders
{
/* send a request for file modification date */
NSURLRequest *modReq = [NSURLRequest requestWithURL:[NSURL URLWithString:URLInput.text]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0f];
[[NSURLConnection alloc] initWithRequest:modReq delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
/* convert response into an NSHTTPURLResponse,
call the allHeaderFields property, then get the
Last-Modified key.
*/
NSHTTPURLResponse *foo = [(NSHTTPURLResponse *)response allHeaderFields];
NSString * last_modified = [NSString stringWithFormat:#"%#",
[[(NSHTTPURLResponse *)response allHeaderFields] objectForKey:#"Last-Modified"]];
NSLog(#"Last-Modified: %#", last_modified );
}
My main question is the following:
Does this call only send over the header? If the file is big I do not want the whole file being downloaded. That is why I'm checking the header.
+++++++++++++++++++++++++++++++++++++++
After the update this works...
Thanks now looks like:
NSMutableURLRequest *modReq = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: URLInput.text]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0f];
[modReq setHTTPMethod:#"HEAD"];
As you have it now, you're probably downloading the whole file. The key is the http method used for the http request. By default, it's a GET request. What you want is a HEAD request. You don't want the file, you just want the server to return the response that you would get if you did, right?
To do that, you want to use a NSMutableURLRequest and setHTTPMethod: to construct a request with a method of HEAD, instead of GET.
Related
I am trying to access protected resources on a Django site using NSURLConnection , OAuth2 Bearer token and HTTPS. I receive a token, which I then attach either to a GET parameter, POST parameter or header. I can access those URL:s which respond to GET parameter. But when I try to access urls using POST, the server returns me a 403 with a custom error message saying there is no header/post parameter containing the token. I have tried several solutions and HTTP libraries. This method uses AFNetworking, I tried it. We even changed the authorization to accept an alternative header due to warnings that apple does not like the modifying of "Authorization" header. My current code looks like this: (scheme == #"https")
-(void) logOut {
NSString *pget = #"/api/logout/";
NSString *path = [pget stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *absolutePath = [NSString stringWithFormat:#"%#://%#%#", scheme, host, path];
NSURL *url = [NSURL URLWithString:absolutePath];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
NSString *authValue = [NSString stringWithFormat:#"Bearer %#", accessToken];
[urlRequest setValue:authValue forHTTPHeaderField:#"Authorization_Extra"];
[urlRequest setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"content-type"];
[urlRequest setHTTPMethod: #"POST"];
/*
NSString *post = [NSString stringWithFormat:#"access_token_extra=%#", accessToken];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
[urlRequest setValue:postLength forHTTPHeaderField:#"Content-Length"];
[urlRequest setHTTPBody:postData];
*/
NSDictionary* headers = [urlRequest allHTTPHeaderFields];
NSLog(#"headers: %#",headers);
_originalRequest = urlRequest;
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:NO];
[connection start];
}
#pragma mark NSURLConnection Delegate Methods
- (NSURLRequest *)connection: (NSURLConnection *)connection
willSendRequest: (NSURLRequest *)request
redirectResponse: (NSURLResponse *)redirectResponse;
{
if (redirectResponse) {
// we don't use the new request built for us, except for the URL
NSURL *newURL = [request URL];
NSMutableURLRequest *newRequest = [_originalRequest mutableCopy];
[newRequest setURL: newURL];
NSLog(#"New Request headers: %#", [newRequest allHTTPHeaderFields]);
return newRequest;
} else {
return request;
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response {
NSLog(#"Received response statuscode: %ld", (long)[response statusCode]);
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"connection finished:");
[_delegate handleData:responseData];
}
The _Delegate handleData parses the response, and the custom response is always that I am lacking either the header or post parameter needed for the Bearer token.
It seems that even though I am replacing the request with a mutable copy of the original on every redirect, the headers/parameters still get stripped by NSURLConnection. But why, and how, since I'm sending a copy of the original request every time and I verify by logging that they are there?
I have a little Mac application which should be able to post Data to my web server which saves the data in a database. Now that's the Code I have now:
NSData *postData = [urlString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://..."]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) NSLog(#"Done");
And it works fine. But now I want to check whether the data was correct (and stored in the database) or something (like eMail) is wrong. The PHP file prints e.g. "email incorrect" out if the E-Mail is not correct.
But how can I fetch this data (which PHP prints out) in Xcode that the App knows whether it was successful or not?
Thanks for answers!
You need to implement the NSURLConnectionDelegate methods connection:didReceiveData: and connectionDidFinishLoading:
According to the docs didReceiveData: may be called multiple times per NSURLRequest (i.e. the response will not always arrive all at once) so the recommended method is to append the incoming data to buffer during connection:didReceiveData: and then do any processing on the data in connectionDidFinishLoading:.
You could create a property on your class like this:
#property (nonatomic, strong) NSMutableData *dataBuffer;
And instantiate your buffer during viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataBuffer = [[NSMutableData alloc] init];
// do any other setup your class requires...
}
And then implement the delegate methods:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// clear the buffer in case it has been used previously
[self.dataBuffer setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.dataBuffer appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
NSString *response = [NSString stringWithUTF8String:[self.dataBuffer bytes]]);
NSLog(#"response from HTTP request=>%#", response);
}
This can all also be done using a third-party networking library like ASIHTTPRequest (which is no longer under active develoment) or AFNetworking, but sometimes those can be overkill depending upon what you are trying to accomplish
Implement the delegate method for the NSURLConnection,
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response.
This method is called by the app when the request finishes. You can access response data using the 'response' parameter.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
Then just convert the 'data' parameter into a string using:
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Then you can search the response for whatever string you want, e.g., "email incorrect".
PS: I generally don't use NSURLConnection/NSURLRequest for HTTP requests, I'd recommend you check out ASIHTTPRequest for really simple HTTP requests/connections.
Hope this helps.
I am trying to write an iPhone app in Objective-C. I need to POST data using NSURLConnection. Every example I can find deals with JSON; I do not need to use JSON. All I need to do is POST the data and get a simple 1 or 0 (succeed or fail) from a PHP script. Nothing more.
I came across this code but I am not sure how to use it or modify it to not use JSON:
- (void)performRequest {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://someplace.com/"]];
[request setValue:#"Some Value" forHTTPHeaderField:#"Some-Header"];
[request setHTTPBody:#"{\"add_json\":\"here\"}"];
[request setHTTPMethod:#"POST"];
[NSURLConnection connectionWithRequest:[request autorelease] delegate:self];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// Fail..
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// Request performed.
}
Here's how to create an ordinary post.
First create a request of the right type:
NSURL *URL = [NSURL URLWithString:#"http://example.com/somepath"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
request.HTTPMethod = #"POST";
Now format your post data as a URL-encoded string, like this:
NSString *params = #"param1=value1¶m2=value2&etc...";
Remember to encode the individual parameters using percent encoding. You can't entirely rely on the NSString stringByAddingPercentEscapesUsingEncoding method for this (google to find out why) but it's a good start.
Now we add the post data to your request:
NSData *data = [params dataUsingEncoding:NSUTF8StringEncoding];
[request addValue:#"8bit" forHTTPHeaderField:#"Content-Transfer-Encoding"];
[request addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request addValue:[NSString stringWithFormat:#"%i", [data length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:data];
And that's it, now just send your request as normal using NSURLConnection (or whatever).
To interpret the response that comes back, see Maudicus's answer.
You can use the following NSURLConnection method if you target ios 2.0 - 4.3 (It seems to be deprecated in ios 5)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSString * string = [[NSString alloc] initWithData:data encoding:
NSASCIIStringEncoding];
if (string.intValue == 1) {
} else {
}
}
I've a very similar situation to whitebreadb. I'm not disagreeing with the answers submitted and accepted but would like to post my own as the code provided here didn't work for me (my PHP script reported the submitted parameter as a zero-length string) but I did find this question that helped.
I used this to perform a posting to my PHP script:
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"http://www.myphpscriptlocation.net/index.php?userID=%#",self.userID_field.stringValue]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
request.HTTPMethod = #"POST";
NSURLConnection *c = [NSURLConnection connectionWithRequest:request delegate:self];
I have a php file on my server that takes two argument and register my users.Can any one tell me the easiest way to send request to that gile and get response?
**My php file returns integer value like 1 for successful registration.2 For User exists.
You can use the NSURLConnection with NSMutableURLRequest or NSURLRequest
The class that you make the request in should implement this code.
-(void)yourMethod
{
// assume your append is a string of format ?key1=value1&key2=value2
NSString * urlString = [NSString stringWithFormat:#"https://www.stackoverflow.com/myPhpFile.php%#", append];
urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
urlConnection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
[urlRequest release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSString * string = [[NSString alloc] initWithData:data encoding:
NSASCIIStringEncoding];
// check string for successful registration
[string release];
}
You don't need to use https if your site does not have an SSL certificate.
I'm a novice in iOS developing, and have some problems with understanding web service organization. I want to send a Get query to the URL. And I do it so:
-(BOOL) sendLoginRequest{
NSString *getAction = [NSString stringWithFormat:#"action=%#&username=%password=%#",#"login",self.log.text, self.pass.text];
NSString *getUserName = [NSString stringWithFormat:#"username=%#",self.log.text];
NSString *getPassword = [NSString stringWithFormat:#"username=%#",self.pass.text];
NSData *getDataAction = [getAction dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *getLengthAction = [NSString stringWithFormat:#"%d", [getDataAction length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:#"http:http://www.site.fi/api/"]];
[request setHTTPMethod:#"GET"];
[request setValue:getLengthAction forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:getLengthAction];
self.urlConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
NSAssert(self.urlConnection != nil, #"Failure to create URL connection.");
// show in the status bar that network activity is starting
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
the answer may be "true" or "false"
but how can I take this answer?
You should define next methods to get answer:
Start connection: [self.urlConnection start];
Check server response:
- (void)connection:(NSURLConnection *)theConnection didReceiveResponse:(NSURLResponse *)response
Collect data that servers sends you:
- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data
Be sure to manage errors:
- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error
Check received data:
- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
To be more sure that you correctly understood me check NSURLConnection Class Reference
Send [self.urlConnection start]; and implement the NSURLConnectionDelegate methods to receive the response. Alternatively use ASIHTTPRequest and the block handlers, which to my way of thinking are much easier to write for beginners, provided you don't need to run on iOS pre-4.1.
You will gather the data returned as NSData; just convert that to a string, and either call boolValue on the string (check the docs for its rather strange tests), or use a specific set of your own tests.