开发者

Sending a POST form from Cocoa

Hey all! I read an arti开发者_StackOverflow中文版cle from http://deusty.blogspot.com/2006/11/sending-http-get-and-post-from-cocoa.html , but I quite didn't get some things. I tried to establish NSURLConnection with it and some how it won't receive data at all? If you are interested here is the site I am trying to login www.lockerz.com .

http://pastebin.com/8fP9TX8q . Fix the links as I can't post more than 1.

It actually says connection failed and I have no idea why...


Problem #1

Something that immediately strikes me as wrong are the first two lines:

NSString *post = @"email-email=test@email.com&password-password=testpassword";
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

When submitting POST forms (and GET parameters in the URL), only the keys and the values should be URL encoded. Here you're not only encoding the keys and the values, but also the = and &, which is just plain wrong. I usually do something like this:

NSMutableDictionary * parameters = [NSMutableDictionary dictionary];
[parameters setObject:@"test@email.com" forKey:@"email-email"];
[parameters setObject:@"testpassword" forKey:@"password-password"];

NSMutableArray * encodedParameters = [NSMutableArray array];
for (NSString * key in parameters) {
  NSString * value = [parameters objectForKey:key];
  NSString * encoded = [NSString stringWithFormat:@"%@=%@", [key stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding], [value stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
  [encodedParameters addObject:encoded];
}

NSString * post = [encodedParameters componentsJoinedByString:@"&"];
NSData * postData = [post dataUsingEncoding:NSASCIIStringEncoding];

You may also run into problems using stringByAddingPercentEscapesUsingEncoding:. I wrote an NSString category on how to URL encode strings here.

Problem #2

You're never waiting for the connection to send. NSURLConnection, in the way that you're using it, is an asynchronous API. Thus, the following will fail:

NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (theConnection) {
  NSLog(@"Connection succeeded!");
}

What you're testing there is not the successful completion of the connection, but the successful instantiation of a connection object. That's a very very different thing. The connection itself may not actually finish for several spins of the run loop. If you want the connection to be synchronous (ie, the connection is done before the next line of code is executed), then you need to use NSURLConnection's synchronous API.

Problem #3

These lines are full of fail:

receivedData = [[NSMutableData data] retain];
NSString *text = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];

[NSMutableData data] returns an empty data object. It contains nothing. So if you create an empty data object, and then create a string out of the data, then (surprise surprise) you're going to get an empty string.

Plus you're leaking the data object (since you retain it [which is unnecessary], but never release it).

Edit since I'm feeling generous....

The following works properly (although I just hardcoded the HTTPBody string instead of building it as recommended above):

NSURL * url = [NSURL URLWithString:@"http://www.lockerz.com/auth/login/"];
NSMutableURLRequest * r = [[NSMutableURLRequest alloc] initWithURL:url];
[r setHTTPMethod:@"POST"];
[r setHTTPBody:[@"email%2Demail=test%40email%2Ecom&password%2Dpassword=testpassword" dataUsingEncoding:NSASCIIStringEncoding]];
[r setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

NSHTTPURLResponse * response = nil;
NSError * error = nil;
NSData * responseData = [NSURLConnection sendSynchronousRequest:r returningResponse:&response error:&error];
NSString * responseString = [[[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding] autorelease];
NSLog(@"%@", responseString);
[r release];

This correctly executes, and the responseString logs some HTML which describes an error page. This, however, is unsurprising, since the URL itself (http://www.lockerz.com/auth/login) produces an error when attempting to use the credentials provided in the original question.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜