views:

32

answers:

1

Hi All

I have been working using openFrameworks, on a problem that is posted on the forum: www.openframeworks.cc/forum/viewtopic.php?f=8&t=4765

Essentially, I have used an an set of files, ofxHttpUtils, which uses poco to post to web forms. The example code I have used is at: github.com/arturoc/ofxHttpUtils/blob/gh-pages/example/src/testApp.cpp

I want to POST to a login page, a username and password, and then I am aiming to scrape text off the response... that's the aim, via an iPhone app.

The problem I am having is cookies. The ofxHttpUtils addon does not have any method for remembering the cookie from a POST, so the response I get back is just the login page. I have searched for methods to try and capture the cookie, and there seems to be something in Objective C here, from another post to Stack Overflow:

NSHTTPURLResponse   * response;
NSError             * error;
NSMutableURLRequest * request;
request = [[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://temp/gomh/authenticate.py?setCookie=1"]
                                        cachePolicy:NSURLRequestReloadIgnoringCacheData 
                                    timeoutInterval:60] autorelease];

[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];    
NSLog(@"RESPONSE HEADERS: \n%@", [response allHeaderFields]);

// If you want to get all of the cookies:
NSArray * all = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:[NSURL URLWithString:@"http://temp"]];
NSLog(@"How many Cookies: %d", all.count);
// Store the cookies:
// NSHTTPCookieStorage is a Singleton.
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:all forURL:[NSURL URLWithString:@"http://temp"] mainDocumentURL:nil];

// Now we can print all of the cookies we have:
for (NSHTTPCookie *cookie in all)
    NSLog(@"Name: %@ : Value: %@, Expires: %@", cookie.name, cookie.value, cookie.expiresDate); 


// Now lets go back the other way.  We want the server to know we have some cookies available:
// this availableCookies array is going to be the same as the 'all' array above.  We could 
// have just used the 'all' array, but this shows you how to get the cookies back from the singleton.
NSArray * availableCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:@"http://temp"]];
NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:availableCookies];

// we are just recycling the original request
[request setAllHTTPHeaderFields:headers];

request.URL = [NSURL URLWithString:@"http://temp/gomh/authenticate.py"];
error       = nil;
response    = nil;

NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(@"The server saw:\n%@", [[[NSString alloc] initWithData:data encoding: NSASCIIStringEncoding] autorelease]);

I am not sure how/where to implement this, so that I can integrate with my my ofxHttpUtils code so that the cookie is remembered and served in calls to the password protected site. Can anyone help? I know this request is a little unspecific... I hope you can see what I'm trying to do...

A: 

Since you're already using OF, it would likely be simpler to stick with that. You're going to have to extend ofxHttpUtils to handle cookies, either by making it smarter so it handles cookies intelligently, or by leaving it dumb while letting you grab and set cookies as needed. Poco::Net, which ofxHttpUtils is based on, has no problem with cookies - it includes functions like HTTPResponse::getCookies().

The most straightforward approach is the dumb one:

  • add ofxHttpForm::setCookies() so you can pass cookies into the module and getCookies() so the module can access them
  • modify ofxHttpUtils::doPostForm() to pull cookies from the ofxHttpForm and set them on the Poco HTTPRequest
  • modify the ofxHttpRequest constructor to pull the cookies from the Poco HTTPResponse and provide a way for your code to get at them

Your code would then grab the cookies sent back after the log-in POST and set them on all future requests.

Jeremy W. Sherman
Hi Jeremy thanks for the answer. That had been my thought- but I wasn't sure how to go about it. I think it would involve writing a function within the ofxHttpUtils as you say. But I'm not certain I have the knowledge to do that! But I do agree that mixing the two types of code above is probably not the right thing to do. Do you have any pointers to get me started? Thanks again
sacculi
@sacculi I've edited my original answer to provide an outline of the straightforward approach, which basically just routes the cookies back and forth through the ofxHttpUtils layer.
Jeremy W. Sherman
Thanks Jeremy. The steps are really useful, thanks so much. I have tried various ways of implementing them but struggle. Like, passing cookies into the new function (step 1), I guess I need to pass in the HTTPResponse from the postForm function, but I can't get that right. There are some conceptual gaps there, you see, on my part. I was also intrigued by http://stackoverflow.com/questions/1499086/poco-c-net-ssl-how-to-post-https-request which seemed to have the same code as the ofxHttpUtils I have been working with. I wondered about using that somehow, like:
sacculi
std::vector<Poco::Net::HTTPCookie> cookies; res.getCookies( cookies );
sacculi
and then after that, req.getCookies( cookies ); after the HTTPRequest for the URL (not the formpost function). But like I said above, I lack some conceptual stuff at this level- I mostly do simple media arts projects! But I shall keep you in touch with my progress, thanks SO much
sacculi