Which NSURLConnection wrapper handles GET and POST equally well? - objective-c

Which NSURLConnection wrapper handles GET and POST equally well ?
For GET method, I prefer google's GTMHTTPFetcher over ASIHTTPRequest. ASIHTTPRequest uses delegate, which probably the idea you will come up with normally. But that's the exactly reason I chose not to use it because when you have several connections(many connections in my case), then each connection has its own delegate and you end up with too many object. Or you can have just 1 delegate but you have find a way to find out which response is for which connection.
GTMHTTPFetcher handle this way much better in my opinion. It uses 1 SEL for 1 connection, sorta like target-action model. The code is much cleaner than delegate model.
But for POST method, ASIHTTPRequest has ASIFormDataRequest. I did not find an easy way to do POST with GTMHTTPFetcher. It does have setPostData method to set post data. But you have to set post body and those mime parameters by yourselves(from what I have see) And that's the headache. I find it has another class called GTMHTTPUploadFetcher. But I can't really figure out how to use it (I keep getting the NSAssert "need upload location hdr").
So for POST, I guess ASIHTTPRequest is easier.
I did not get a chance to use facebook-ios-sdk. And would like to hear other opinion about it.
So is there NSURLConnection wrapper handle both GET and POST well ? And any idea how to use GTMHTTPUploadFetcher?

The GTMMIMEDocument class is used to create a stream for uploading via GTMHTTPFetcher (or via anything else that takes an NSInputStream.) An example is here.
GTMMIMEDocument keeps a sparse list of the data parts to be uploaded, avoiding duplicating the data in memory.

Related

OmniPay manually "create" a response class?

So I'm using https://github.com/thephpleague/omnipay-mollie and I've decided to use webhooks instead of the example they have on their readme. I've got all that working but when it comes time to process the webhook, I was hoping to have access to the helper functions such as isPending, isRefunded, etc...
However, because this hasn't been put into the AbstractResponse class, they aren't available. Usually, OmniPay lets you use a method called acceptNotification() that parses the request and puts it into an AbstractResponse class so that you can use these helper methods.
Problem is, for whatever reason, omnipay-mollie doesn't allow you to use this function. So I'm stuck trying to find a way to manually force my webhook request into this AbstractClass so that I can use these helper functions. I've dug around the entire OmniPay and OmniPay-Mollie source code and cannot find any sort of way to instantiate the class or anything like that.
Hopefully someone with more experience can lend a hand.

Best way to write to file a large HTTP response

I'm looking for ways of writing to file the results of a web request. In languages based on the JVM or the CLR there are appropriate Stream-based techniques I'm familiar with, however I'm clueless on how could that be done in Objective-C.
What I need is essentially a way to send an HTTP request (with a custom header set) and write the HTTP response content as I receive it (due to memory constraints I can't afford to get the whole file or even a large portion of it before persisting the contents).
Ideas/suggestions/snippets?
Thanks in advance!
P.S.: I'm developing for Mac OS and I'm already using ASIHTTPRequest, if that can be of help.
Edit: I should specify that I don't want to write all of the contents returned by the server to disk unless I can write them directly at a certain offset of a file (which I'll then be able to manipulate), so anything that dumps straight to a new file or to the beginning of a file won't work for me.
There a few ways of doing it, depends on how you want to handle the responds
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:#"/Users/Test/Desktop/cool.html"];
with setDownloadDestinationPath: set, it'll save into temporary path, and when it finished, it'll move it to your downloadDestinationPath you set.
Or you can implement request:didReceiveData: delegate (see ASIHTTPRequestDelegate.h), and handle it yourself. This is similar to stream.
PS. I only ever use ASIHTTPRequest on iOS, not Mac OS, so I'm not entirely sure if it will work for you.

simultaneous NSURLConnection by using unique delegates for each NSURLConnection

I am try to handle multiple NSURLConnection at the same time by using a different delegate for each connection, for each NSURLConnection I create, I create a new delegate object, but for some reason only one NSURLConnection works at a time, any NSURLConnection I try to start whilst one is already running simply do not start, my delegate does not receive any of the method calls connection:didReceiveResponse:, connection:didReceiveData:, connectionDidFinishLoading: or connection:didFailWithError:. Am I misunderstanding something about how NSURLConnection and its delegate works. Reading other posts most people seem to have a single delegate for all there connections and then use some kind of dictionary to get the right object to handle the right connection. Is that the way you have to do it.
What you are describing should work fine. You can have multiple NSURLConnections in flight at once, each with its own delegate.
If you want to know why your case isn't working, you'll probably need to show your code in your question.
I hope that at least answers the general question.

How can I avoid data corruption with multiple instances of NSUrlConnection

I have written an iOS app that calls NSUrlConnection multiple times to download image data from the web. Sometimes, one NSUrlConnection has not finished before the other starts. I am seeing corrupt jpeg data and I think it is because my didReceiveData delegate is saving data from two separate NSUrlConnections and munging the two jpeg data streams together into one data variable, hence causing the corruption.
My question is: what is the best way to avoid this? There doesn't seem to be a way to make each NSUrlConnection instance save to a separate data variable, or make each instance wait until the previous instance is done before saving.
My code basically follows Apple's example here except I call a loadData function multiple times which creates the NSURLRequest and NSURLConnection. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
Thanks in advance for any help.
When your delegate's connection:didReceiveData: method is called, you'll have the connection instance as the first parameter. So you'll need to use that to keep track of which connection just received data.
Apple's sample maintains one instance of NSMutableData. Your code will require several instances, one for each active connection.
Or, of course, you could have a separate delegate object (an individual instance) for each connection. That may be easier.

Atomic, asynchronous HTTP file POST with sensible feedback?

I've just started development on Macs and have found Cocoa to be a useful and thoughtful framework, but its HTTP functionality has me puzzled.
I have an NSURLConnection object to download a file from my webserver using the HTTP GET method. NSURLConnect's asynchronous connection is great, I get plenty of feedback, I get each chunk received as a new NSData object that I can use to atomically rebuild the file on the client end and, importantly, provide the user with a progress report: [myData length].
Uploads, however, are nowhere near as neat. You can either stick a synchronous request in its own thread or call an asynchronous request (which I believe spawns its own thread), but neither provide you with any useful feedback. There's no delegates to request data or even let me know when data is being sent. Presumably this limits me to files smaller than available memory.
My question is, therefore, is there a simple and elegant solution to HTTP POST file uploads using Cocoa that provides a good deal of feedback and the ability to read files part-by-part, rather than all at once? Or should I write my own class from low-level networking functionality?
Thanks!
You may want to look at the ASIHTTPRequest framework. I haven't used it for uploading but it looks like it has more feedback and the usage is pretty straightforward.
I decided to go with CFNetwork functions instead of NSURLConnection. There appears to be a bit more flexibility in async notifications and in specific features (authentication for instance). Unfortunately it's a bit more complicated (run loops for instance blow my mind) so I recommend you read the CFNetwork reference guide if you go this route:
http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/Introduction/Introduction.html
Here's a snippet of code from my POST routine, FWIW:
// Create our URL
CFStringRef url = CFSTR("Submit");
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, baseUrl);
// Create the message request (POST)
CFStringRef requestMethod = CFSTR("POST");
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
// Connect the read socket to the HTTP request stream
CFReadStreamRef myReadStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, myRequest, readStream);
// TODO: why does this have to be done?
succ &= CFReadStreamSetClient(myReadStream,
kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered,
(CFReadStreamClientCallBack) &MyReadCallBack, &myClientContext);
CFReadStreamScheduleWithRunLoop(myReadStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
succ &= CFReadStreamOpen(myReadStream);
ASIHTTPRequest was originally designed just for this purpose (tracking POST progress), since in the 2.x API, this isn't possible with NSURLConnection. It will definitely be easier to integrate than rolling your own with CFNetwork, and you get lots of other stuff for free (e.g. progress tracking across multiple requests, resuming downloads etc). :)
If the files you are uploading are large, be sure to look at the options for streaming directly from disk, so you don't have to hold the data in memory.
Unfortunately, you're quite correct that NSURLConnection is weak here. The most flexible approach that I would recommend is CocoaAsyncSocket. It means rolling your own HTTP, which is unfortunate, but in most cases not that difficult. CocoaHTTPServer demonstrates how to build a full HTTP server on top of CocoaAsyncSocket, and may have a lot of useful code for your problem. I've found both of these very useful.
Another approach that may be worth investigating is WebKit. Create an invisible WebView, and loadRequest: a POST. I haven't dug into whether the estimatedChange notification system includes the time to upload or only the time to download, but it's worth a try.
You can take a look at the HTTPMessage section of my toolkit repository on github for a simple ObjC wrapper around CFHTTPMessageRef; among other things it'll hand you an NSInputStream object, which saves you thinking about plain-C callback functions.
Depending on what you're reading, you may want to take a look at the StreamingXMLParser section of the same repository for an XML (and HTML) parser which will parse data directly from said NSInputStream on your behalf.