diff --git a/bin/httparty b/bin/httparty index dbbfd0a..75fc18a 100755 --- a/bin/httparty +++ b/bin/httparty @@ -18,7 +18,7 @@ OptionParser.new do |o| o.on("-f", "--format [FORMAT]", "Output format to use instead of pretty-print ruby: " + - "plain, json or xml") do |f| + "plain, csv, json or xml") do |f| opts[:output_format] = f.downcase.to_sym end @@ -107,6 +107,9 @@ else require 'rexml/document' REXML::Document.new(response.body).write(STDOUT, 2) puts + when :csv + require 'csv' + puts CSV.parse(response.body).map{|row| row.to_s } else puts response end diff --git a/features/handles_multiple_formats.feature b/features/handles_multiple_formats.feature index 2f53844..05c5553 100644 --- a/features/handles_multiple_formats.feature +++ b/features/handles_multiple_formats.feature @@ -14,6 +14,21 @@ Feature: Handles Multiple Formats Then it should return a String And the return value should match '

Some HTML

' + Scenario: A CSV service + Given a remote service that returns + '"Last Name","Name" + "jennings","waylon" + "cash","johnny"' + And that service is accessed at the path '/service.csv' + And the response from the service has a Content-Type of 'application/csv' + When I call HTTParty#get with '/service.csv' + Then it should return a multidimensional array equaling: + [ + ["Last Name","Name"], + ["jennings","waylon"], + ["cash","johnny"] + ] + Scenario: A JSON service Given a remote service that returns '{ "jennings": "waylon", "cash": "johnny" }' And that service is accessed at the path '/service.json' diff --git a/lib/httparty.rb b/lib/httparty.rb index 932290c..4123048 100644 --- a/lib/httparty.rb +++ b/lib/httparty.rb @@ -5,6 +5,7 @@ require 'uri' require 'zlib' require 'multi_xml' require 'json' +require 'csv' require 'httparty/module_inheritable_attributes' require 'httparty/cookie_hash' diff --git a/lib/httparty/parser.rb b/lib/httparty/parser.rb index b91ff46..8e611cb 100644 --- a/lib/httparty/parser.rb +++ b/lib/httparty/parser.rb @@ -1,5 +1,5 @@ module HTTParty - # The default parser used by HTTParty, supports xml, json, html, and + # The default parser used by HTTParty, supports xml, json, html, csv and # plain text. # # == Custom Parsers @@ -45,7 +45,10 @@ module HTTParty 'application/javascript' => :plain, 'text/javascript' => :plain, 'text/html' => :html, - 'text/plain' => :plain + 'text/plain' => :plain, + 'text/csv' => :csv, + 'application/csv' => :csv, + 'text/comma-separated-values' => :csv } # The response body of the request @@ -113,6 +116,10 @@ module HTTParty JSON.load(body, nil) end + def csv + CSV.parse(body) + end + def html body end diff --git a/spec/httparty/parser_spec.rb b/spec/httparty/parser_spec.rb index 23f5770..fae4c23 100644 --- a/spec/httparty/parser_spec.rb +++ b/spec/httparty/parser_spec.rb @@ -156,5 +156,10 @@ describe HTTParty::Parser do it "parses plain text by simply returning the body" do subject.send(:plain).should == 'body' end + + it "parses csv with CSV" do + CSV.should_receive(:parse).with('body') + subject.send(:csv) + end end end diff --git a/spec/httparty/request_spec.rb b/spec/httparty/request_spec.rb index aaab6fe..e86d7e9 100644 --- a/spec/httparty/request_spec.rb +++ b/spec/httparty/request_spec.rb @@ -202,6 +202,24 @@ describe HTTParty::Request do end end + it 'should handle text/csv' do + ["text/csv", "text/csv; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :csv + end + end + + it 'should handle application/csv' do + ["application/csv", "application/csv; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :csv + end + end + + it 'should handle text/comma-separated-values' do + ["text/comma-separated-values", "text/comma-separated-values; charset=iso8859-1"].each do |ct| + @request.send(:format_from_mimetype, ct).should == :csv + end + end + it 'should handle text/javascript' do ["text/javascript", "text/javascript; charset=iso8859-1"].each do |ct| @request.send(:format_from_mimetype, ct).should == :plain @@ -231,6 +249,12 @@ describe HTTParty::Request do @request.send(:parse_response, xml).should == {'books' => {'book' => {'id' => '1234', 'name' => 'Foo Bar!'}}} end + it 'should handle csv automatically' do + csv=[%q["id","Name"],%q["1234","Foo Bar!"]].join("\n") + @request.options[:format] = :csv + @request.send(:parse_response, csv).should == [["id","Name"],["1234","Foo Bar!"]] + end + it 'should handle json automatically' do json = %q[{"books": {"book": {"name": "Foo Bar!", "id": "1234"}}}] @request.options[:format] = :json diff --git a/spec/httparty_spec.rb b/spec/httparty_spec.rb index 6d5d4ed..efb41ae 100644 --- a/spec/httparty_spec.rb +++ b/spec/httparty_spec.rb @@ -391,6 +391,11 @@ describe HTTParty do @klass.default_options[:format].should == :xml end + it "should allow csv" do + @klass.format :csv + @klass.default_options[:format].should == :csv + end + it "should allow json" do @klass.format :json @klass.default_options[:format].should == :json @@ -410,7 +415,7 @@ describe HTTParty do it 'should only print each format once with an exception' do lambda do @klass.format :foobar - end.should raise_error(HTTParty::UnsupportedFormat, "':foobar' Must be one of: html, json, plain, xml") + end.should raise_error(HTTParty::UnsupportedFormat, "':foobar' Must be one of: csv, html, json, plain, xml") end it 'sets the default parser' do @@ -703,6 +708,14 @@ describe HTTParty do } end + it "should be able parse response type csv automatically" do + stub_http_response_with('twitter.csv') + profile = HTTParty.get('http://twitter.com/statuses/profile.csv') + profile.size.should == 2 + profile[0].should == ["name","url","id","description","protected","screen_name","followers_count","profile_image_url","location"] + profile[1].should == ["Magic 8 Bot",nil,"17656026","ask me a question","false","magic8bot","90","http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",nil] + end + it "should not get undefined method add_node for nil class for the following xml" do stub_http_response_with('undefined_method_add_node_for_nil.xml') result = HTTParty.get('http://foobar.com')