Skip to content

Commit

Permalink
Lazy parsing of responses to allow for response code checking prior t…
Browse files Browse the repository at this point in the history
…o parsing.

Fixes #79
  • Loading branch information
jnunemaker committed Apr 22, 2012
1 parent c2d4615 commit 9fd5259
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 29 deletions.
2 changes: 1 addition & 1 deletion lib/httparty/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def handle_response(body)
perform
else
body = body || last_response.body
Response.new(self, last_response, parse_response(body), :body => body)
Response.new(self, last_response, lambda { parse_response(body) }, :body => body)
end
end

Expand Down
20 changes: 12 additions & 8 deletions lib/httparty/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ def self.underscore(string)
string.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
end

attr_reader :request, :response, :parsed_response, :body, :headers
attr_reader :request, :response, :body, :headers

def initialize(request, response, parsed_response, options={})
@request = request
@response = response
@body = response.body || options[:body]
@parsed_response = parsed_response
@headers = Headers.new(response.to_hash)
def initialize(request, response, parsed_block, options={})
@request = request
@response = response
@body = response.body || options[:body]
@parsed_block = parsed_block
@headers = Headers.new(response.to_hash)
end

def parsed_response
@parsed_response ||= @parsed_block.call
end

def class
Expand All @@ -24,7 +28,7 @@ def code

def inspect
inspect_id = "%x" % (object_id * 2)
%(#<#{self.class}:0x#{inspect_id} @parsed_response=#{parsed_response.inspect}, @response=#{response.inspect}, @headers=#{headers.inspect}>)
%(#<#{self.class}:0x#{inspect_id} parsed_response=#{parsed_response.inspect}, @response=#{response.inspect}, @headers=#{headers.inspect}>)
end

CODES_TO_OBJ = ::Net::HTTPResponse::CODE_CLASS_TO_OBJ.merge ::Net::HTTPResponse::CODE_TO_OBJ
Expand Down
10 changes: 10 additions & 0 deletions spec/httparty/request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,16 @@
resp.body.should == "<foo><bar>error</bar></foo>"
resp['foo']['bar'].should == "error"
end

it "parses response lazily so codes can be checked prior" do
stub_response 'not xml', 500
@request.options[:format] = :xml
lambda {
response = @request.perform
response.code.should == 500
response.body.should == 'not xml'
}.should_not raise_error
end
end
end

Expand Down
29 changes: 9 additions & 20 deletions spec/httparty/response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
@response_object.stub(:body => "{foo:'bar'}")
@response_object['last-modified'] = @last_modified
@response_object['content-length'] = @content_length
@parsed_response = {"foo" => "bar"}
@parsed_response = lambda { {"foo" => "bar"} }
@response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
end

Expand Down Expand Up @@ -51,42 +51,42 @@
end

it "should send missing methods to delegate" do
response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
response['foo'].should == 'bar'
end

it "response to request" do
response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
response.respond_to?(:request).should be_true
end

it "responds to response" do
response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
response.respond_to?(:response).should be_true
end

it "responds to body" do
response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
response.respond_to?(:body).should be_true
end

it "responds to headers" do
response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
response.respond_to?(:headers).should be_true
end

it "responds to parsed_response" do
response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
response.respond_to?(:parsed_response).should be_true
end

it "responds to anything parsed_response responds to" do
response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
response.respond_to?(:[]).should be_true
end

it "should be able to iterate if it is array" do
response = HTTParty::Response.new(@request_object, @response_object, [{'foo' => 'bar'}, {'foo' => 'baz'}])
response = HTTParty::Response.new(@request_object, @response_object, lambda { [{'foo' => 'bar'}, {'foo' => 'baz'}] })
response.size.should == 2
expect {
response.each { |item| }
Expand Down Expand Up @@ -114,17 +114,6 @@
end
end

xit "should allow hashes to be accessed with dot notation" do
response = HTTParty::Response.new(@request_object, {'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK')
response.foo.should == 'bar'
end

xit "should allow nested hashes to be accessed with dot notation" do
response = HTTParty::Response.new(@request_object, {'foo' => {'bar' => 'baz'}}, "{foo: {bar:'baz'}}", 200, 'OK')
response.foo.should == {'bar' => 'baz'}
response.foo.bar.should == 'baz'
end

describe "semantic methods for response codes" do
def response_mock(klass)
response = klass.new('', '', '')
Expand Down

0 comments on commit 9fd5259

Please sign in to comment.