How to pass additional parameters to ASIHTTPRequest didFinishSelector selector - objective-c

Im building api for our rest api using ASIHTTPRequest.
Api wraps all requests to its own methods.
- (void) foo:(id)caller
andSuccessCallback:(SEL)successCallback
andFailureCallback:(SEL)failureCallback {
_currentCaller=caller;
_currentSuccessCallback=successCallback;
_currentFailureCallback=failureCallback;
NSString *urlString = #"http://localhost/foo";
NSURL *url= [NSURL URLWithString: urlString];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request setDidFinishSelector:#selector(fooSuccess:)];
[request startAsynchronous];
}
- (void) fooSuccess:(ASIHTTPRequest *)request {
if (statusCode >=400) {
if ([_currentCaller respondsToSelector:_currentFailureCallback])
[_currentCaller performSelector:_currentFailureCallback withObject:statusCode withObject:message];
} else {
if ([_currentCaller respondsToSelector:_currentSuccessCallback])
[_currentCaller performSelector:_currentSuccessCallback];
}
[request release];
}
Currently to pass callback selector I use class private variables _currentCaller _currentSuccessCallback _currentFailureCallback=failureCallback
Can i pass them to fooSuccess callback directly?

You can pass objects by populating a NSDictionary and setting it as the request's userInfo property.

Related

Cocoa: POST headers/parameters lost when accessing protected resources in a Django site using NSURLConnection

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?

NSURLConnection GET and POST not working

I am not getting the correct output from the server. The response I get back everytime is:
Gone
/prod/bwckgens.p_proc_term_datehas been permanently removed from this server.
This is usually recieved when you just direct the web browser to the page here instead of going through this page first. This makes me come to the conclusion that a cookie isn't being saved, but I read in the documentation that this is all handled by the NSURLConnection object. Is there something I am doing wrong here?
#import "PCFViewController.h"
#interface PCFViewController ()
#end
NSMutableData *mutData;
#implementation PCFViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)queryServer {
NSURL *url = [NSURL URLWithString:#"https://selfservice.mypurdue.purdue.edu/prod/bwckschd.p_disp_dyn_sched"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:3.0];
//the reason I perform a GET here is just to get a cookie and communicate like a normal web browser, since directly doing a POST to the proper address isn't working
[request setHTTPMethod:#"GET"];
[request setValue:#"text/html; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) {
mutData = [NSMutableData data];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[mutData length]);
NSString *str = [[NSString alloc] initWithData:mutData encoding:NSUTF8StringEncoding];
//just to see the contents(for debugging)
NSLog(#"%#", str);
[self handleConnection:connection];
}
-(void)handleConnection:(NSURLConnection *)connection
{
//this is the first step
if ([#"/prod/bwckschd.p_disp_dyn_sched" isEqualToString:[[[connection originalRequest] URL] path]]) {
//first request
//POST
NSURL *url = [NSURL URLWithString:#"https://selfservice.mypurdue.purdue.edu/prod/bwckgens.p_proc_term_date"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:3.0];
[request setHTTPMethod:#"POST"];
NSString *args = #"p_calling_proc=bwckschd.p_disp_dyn_sched&p_term=201320";
NSData *requestBody = [args dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:requestBody];
connection = [connection initWithRequest:request delegate:self];
[connection start];
if (connection) {
mutData = [NSMutableData data];
}
//second step. Here I send the list of classes(COMPUTER SCIENCE) I want to display as well as the term SPRING2013
}else if([#"/prod/bwckgens.p_proc_term_date" isEqualToString:[[[connection currentRequest] URL] path]]) {
NSURL *url = [NSURL URLWithString:#"https://selfservice.mypurdue.purdue.edu/prod/bwckschd.p_get_crse_unsec"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed
timeoutInterval:3.0];
[request setHTTPMethod:#"POST"];
NSString *args = #"term_in=201320&sel_subj=dummy&sel_day=dummy&sel_schd=dummy&sel_insm=dummy&sel_camp=dummy&sel_levl=dummy&sel_sess=dummy&sel_instr=dummy&sel_ptrm=dummy&sel_attr=dummy&sel_subj=CS&sel_crse=dummy&sel_title=dummy&sel_schd=%25&sel_from_cred=&sel_to_cred=&sel_camp=%25&sel_ptrm=%25&sel_instr=%25&sel_sess=%25&sel_attr=%25&begin_hh=0&begin_mi=0&begin_ap=a&end_hh=0&end_mi=0&end_ap=a";
NSData *requestBody = [args dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:requestBody];
connection = [connection initWithRequest:request delegate:self];
[connection start];
if (connection) {
mutData = [NSMutableData data];
}
//the courses should be shown now I have to parse the data
}else if([#"/prod/bwckschd.p_get_crse_unsec" isEqualToString:[[[connection currentRequest] URL] path]]) {
}
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"%#\n", error.description);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[mutData setLength:0];
NSLog(#"%#\n", response.description);
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mutData appendData:data];
}
#end
You cannot change the Request Object with the same URL Connection once it is started. Read the documentation of NSURLConnection. it says:
The URL request to load. The request object is deep-copied as part of
the initialization process. Changes made to request after this method
returns do not affect the request that is used for the loading
process.
So if you want to hit another URL, you have to create a new URLRequest and new URLConnection object. regarding your question about saving cookies. you can set the cache policy of the URLRequest using the following method
- (void)setCachePolicy:(NSURLRequestCachePolicy)policy

Updating UI from callback function

I'm performing asynchronous request with ASI HTTP Request and I want to update Textbox with new information from the request, so I'm updating it from callback function.
Here is my code so far:
Second Class
- (void)Login {
NSLog(#"Login");
NSURL *url = [NSURL URLWithString:#"http://ts5.travian.sk/login.php"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request setDidFinishSelector:#selector(loginRequestFinished:)];
[request setDidFailSelector:#selector(loginRequestFailed:)];
[request startAsynchronous];
}
- (void)loginRequestFinished:(ASIHTTPRequest *)request
{
NSLog(#"Completed!");
NSString *response = [request responseString];
AppController *ac = [AppController getInstance];
[ac.textbox performSelectorOnMainThread:#selector(setStringValue:) withObject:response waitUntilDone:NO];
}
AppController is a main class. Setting text from there is working. But this code isnt doing anything. It just wrote 2 log lines to debug window.
Am I missing something?

Loading stringWithContentsofURL that requires credentials

I am trying to parse an HTML page, but the page requires a username/password to access the data.
How do I pass the credentials to the server so I can load the webpage into my NSData object?
UPDATE for Comments Below
Normally if you are using a web browser, it will pop up a login window for you to type in the credentials. When I execute it in iOS, it doesn't give me anything.
Thanks a lot!
Alan
You can use ASIFormDataRequest. Take a look at it here
NSURL *tempUrl = [NSURL URLWithString:#"http://www.yoursitetoparse.com"];
ASIFormDataRequest *request = [[ASIFormDataRequest alloc] init];
request = [ASIFormDataRequest requestWithURL:tempUrl];
[request setDelegate:self];
[request setRequestMethod:#"POST"];
[request setUsername:#"username"]; //Username
[request setPassword:#"password"]; //Password
[request startAsynchronous];
And it's delegate methods:
-(void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
NSLog(#"Failed %# with code %d and with userInfo %#",[error domain],[error code],[error userInfo]);
}
-(void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"Finished : %#",[theRequest responseString]);
}

Request timeout with Facebook API on iOS

I have a bunch of URL requests that are sent out in batch and then a 'catcher' class that recieves the results. I'm doing this through facebook's graph API SDK so I don't have control of the actual NSURL. My problem is that I don't trigger the next result protocol until all requests have come back, but sometimes, especially over 3G, they don't always come back (especially when you have a few hundred). What's a good way to 'give up' on a given request? The way the actual request works, for those who aren't familiar with the FB api, is you initialize a facebook object and then request data from it, and you specify a return delegate. So, for each individual request I have a returnDelegate (the catcher), which I can initialize specific to each request.
UPDATE: Some code from FB-API
- (FBRequest*)requestWithMethodName:(NSString *)methodName
andParams:(NSMutableDictionary *)params
andHttpMethod:(NSString *)httpMethod
andDelegate:(id <FBRequestDelegate>)delegate {
NSString * fullURL = [kRestserverBaseURL stringByAppendingString:methodName];
return [self openUrl:fullURL
params:params
httpMethod:httpMethod
delegate:delegate];
}
- (FBRequest*)openUrl:(NSString *)url
params:(NSMutableDictionary *)params
httpMethod:(NSString *)httpMethod
delegate:(id<FBRequestDelegate>)delegate {
[params setValue:#"json" forKey:#"format"];
[params setValue:kSDK forKey:#"sdk"];
[params setValue:kSDKVersion forKey:#"sdk_version"];
if ([self isSessionValid]) {
[params setValue:self.accessToken forKey:#"access_token"];
}
[self extendAccessTokenIfNeeded];
FBRequest* _request = [FBRequest getRequestWithParams:params
httpMethod:httpMethod
delegate:delegate
requestURL:url];
[_requests addObject:_request];
[_request addObserver:self forKeyPath:requestFinishedKeyPath options:0 context:finishedContext];
[_request connect];
return _request;
}
- (void)connect {
if ([_delegate respondsToSelector:#selector(requestLoading:)]) {
[_delegate requestLoading:self];
}
NSString* url = [[self class] serializeURL:_url params:_params httpMethod:_httpMethod];
NSMutableURLRequest* request =
[NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:kTimeoutInterval];
[request setValue:kUserAgent forHTTPHeaderField:#"User-Agent"];
[request setHTTPMethod:self.httpMethod];
if ([self.httpMethod isEqualToString: #"POST"]) {
NSString* contentType = [NSString
stringWithFormat:#"multipart/form-data; boundary=%#", kStringBoundary];
[request setValue:contentType forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[self generatePostBody]];
}
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
self.state = kFBRequestStateLoading;
self.sessionDidExpire = NO;
}
As discussed above, you can implement your own timeout by instantiating an NSTimer which will signal a delegate object when a certain amount of time elapses.