[MacRuby-devel] [hotcocoa] http wrapper, what do you think?

Brian Chapados chapbr at gmail.com
Mon Mar 30 14:46:25 PDT 2009


Seems like a good idea that would be useful even outside of HotCocoa.
Especially for simple cases, I think if Obj-C had blocks, this would
be a good place to use them. For more control, the delegate pattern
actually works really well.  It's good that you have a way to do both.
Does the delegate object also receive messages that would be sent to
an NSURLDownload?  That might be a nice way to allow easy integration
in cases where an object that responds to the delegate methods is
defined in Obj-C.

Also, regarding multi-threading, couldn't you just use NSURLDownload
(which you're probably already using underneath) +
NSOperation/NSOperationQueue. Since your #download method already
wraps the underlying process, you could should able to generate
NSOperations to perform the downloads and add them to a queue.  Those
classes handle creating threads (which have their own runloops) and
performing a task on the thread. That said, maybe this approach would
not work with the current IO implementation?

Brian

2009/3/30 Matt Aimonetti <mattaimonetti at gmail.com>:
> In my free time, I've been working on a http://lighthouseapp.com client app
> which mixes API calls with webkit views (I'll release the source code later
> on).
> The app is 100% HotCocoa (meaning that I didn't use any nib/xibs).
> For people who are not used to work with delegation, having to deal with
> file download, URL queries can be a bit challenging if you want to start
> using the underlying obj-c methods.
>
> That's why I wrote a small HTTP wrapper to clean up my code and make
> download/queries easier.
> The library is divided in 2 major parts, a helper and the Query/Response
> classes.
>
> Here is how the helper looks like so far:
>
>  Download helper making file download trivial
>  Pass an url, and a block or a delegator
>  A block takes precedence over a delegator, meaning that you can't
>  pass a delegator and use a block, you have to choose which approach
>  to pick.
>
>  ==== Parameters
>  url<String>:: url of the resource to download
>  options<Hash>:: optional options used for the query
>  &block<block>:: block which is called when the file is downloaded
>
>  ==== Options
>  :method<String, Symbol>:: An optional value which represents the HTTP
> method to use
>  :payload<String>::    - data to pass to a POST, PUT, DELETE query.
>  :delegation<Object>:: - class or instance to call when the file is
> downloaded.
>                          the handle_query_response method will be called on
> the
>                          passed object
>  :save_to<String>::    - path to save the response to
>  :credential<Hash>::   - should contains the :user key and :password key
>                          By default the credential will be saved for the
> entire session
>
>  TODO
>  :progress <Proc>::    Proc to call everytime the downloader makes some
> progress
>  :cache_storage
>  :custom headers
>  Error handling
>
>  ==== Examples
>
>     download("http://www.macruby.org/files/MacRuby%200.4.zip", {:save_to =>
> '~/tmp/macruby.zip'.stringByStandardizingPath}) do |macruby|
>       NSLog("file downloaded!")
>     end
>
>    download "http://macruby.org" do |mr|
>      # The response object has 3 accessors: status_code, headers and body
>      NSLog("status: #{mr.status_code}, Headers: #{mr.headers.inspect}")
>    end
>
>    path = File.expand_path('~/macruby_tmp.html')
>    window :frame => [100, 100, 500, 500], :title => "HotCocoa" do |win|
>      download("http://macruby.org", {:save_to => path}) do |homepage|
>        win << label(:text => "status code: #{homepage.status_code}", :layout
> => {:start => false})
>        win << label(:text => "Headers: #{homepage.headers.inspect}", :layout
> => {:start => false})
>      end
>    end
>
>    download "http://macruby.org/users/matt", :delegation =>
> @downloaded_file, :method => 'PUT', :payload => {:name => 'matt aimonetti'}
>
>    download "http://macruby.org/roadmap.xml", :delegation => self
>
>    download "http://localhost:5984/couchrest-test/", :method => 'POST',
> :payload => '{"user":"mattaimonetti at gmail.com","zip":92129}', :delegation =>
> self
>
>    download("http://mysite.com/login", {:credential => {:user => 'me',
> :password => 's3krit'}}) do |test|
>      NSLog("response received: #{test.headers} #{test.status_code}")
>    end
>
>
> As you can see from the example list, the method name download isn't always
> appropriate and maybe I should give it the http_query alias. What do you
> think?
> What's nice with this approach, is that on top of being simple, the query
> and the response handling are async so the rest of your code can be run and
> you get notified only when the response comes back.
>
> The underlying API looks like that:  MacRubyHTTP::Query.new( url,
> http_method='GET', options={} )
> Queries don't run in a custom runloop yet but that's something I want to
> look at once IO work on the experimental branch will be done.
>
>
> So, here is my question, do you guys think that this is something that
> should be part of HotCocoa or it's better if it stays its own separate lib?
> Also, what do you think about having a default vendor folder for hotcocoa
> apps and autoload the vendor files if available?
>
> - Matt
>
>
> _______________________________________________
> MacRuby-devel mailing list
> MacRuby-devel at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
>
>


More information about the MacRuby-devel mailing list