httparty 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of httparty might be problematic. Click here for more details.

@@ -9,7 +9,7 @@ describe HTTParty::Response do
9
9
  @response_object.stub(:body => "{foo:'bar'}")
10
10
  @response_object['last-modified'] = @last_modified
11
11
  @response_object['content-length'] = @content_length
12
- @parsed_response = {"foo" => "bar"}
12
+ @parsed_response = lambda { {"foo" => "bar"} }
13
13
  @response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
14
14
  end
15
15
 
@@ -51,17 +51,42 @@ describe HTTParty::Response do
51
51
  end
52
52
 
53
53
  it "should send missing methods to delegate" do
54
- response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
54
+ response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
55
55
  response['foo'].should == 'bar'
56
56
  end
57
-
58
- it "should respond_to? methods it supports" do
59
- response = HTTParty::Response.new(@request_object, @response_object, {'foo' => 'bar'})
57
+
58
+ it "response to request" do
59
+ response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
60
+ response.respond_to?(:request).should be_true
61
+ end
62
+
63
+ it "responds to response" do
64
+ response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
65
+ response.respond_to?(:response).should be_true
66
+ end
67
+
68
+ it "responds to body" do
69
+ response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
70
+ response.respond_to?(:body).should be_true
71
+ end
72
+
73
+ it "responds to headers" do
74
+ response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
75
+ response.respond_to?(:headers).should be_true
76
+ end
77
+
78
+ it "responds to parsed_response" do
79
+ response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
60
80
  response.respond_to?(:parsed_response).should be_true
61
81
  end
62
82
 
83
+ it "responds to anything parsed_response responds to" do
84
+ response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
85
+ response.respond_to?(:[]).should be_true
86
+ end
87
+
63
88
  it "should be able to iterate if it is array" do
64
- response = HTTParty::Response.new(@request_object, @response_object, [{'foo' => 'bar'}, {'foo' => 'baz'}])
89
+ response = HTTParty::Response.new(@request_object, @response_object, lambda { [{'foo' => 'bar'}, {'foo' => 'baz'}] })
65
90
  response.size.should == 2
66
91
  expect {
67
92
  response.each { |item| }
@@ -89,22 +114,11 @@ describe HTTParty::Response do
89
114
  end
90
115
  end
91
116
 
92
- xit "should allow hashes to be accessed with dot notation" do
93
- response = HTTParty::Response.new(@request_object, {'foo' => 'bar'}, "{foo:'bar'}", 200, 'OK')
94
- response.foo.should == 'bar'
95
- end
96
-
97
- xit "should allow nested hashes to be accessed with dot notation" do
98
- response = HTTParty::Response.new(@request_object, {'foo' => {'bar' => 'baz'}}, "{foo: {bar:'baz'}}", 200, 'OK')
99
- response.foo.should == {'bar' => 'baz'}
100
- response.foo.bar.should == 'baz'
101
- end
102
-
103
117
  describe "semantic methods for response codes" do
104
118
  def response_mock(klass)
105
- r = klass.new('', '', '')
106
- r.stub(:body)
107
- r
119
+ response = klass.new('', '', '')
120
+ response.stub(:body)
121
+ response
108
122
  end
109
123
 
110
124
  context "major codes" do
@@ -190,4 +204,11 @@ describe HTTParty::Response do
190
204
  end
191
205
  end
192
206
  end
207
+
208
+ describe "headers" do
209
+ it "can initialize without headers" do
210
+ headers = HTTParty::Response::Headers.new
211
+ headers.should == {}
212
+ end
213
+ end
193
214
  end
@@ -3,18 +3,18 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
3
3
  describe HTTParty::Request do
4
4
  context "SSL certificate verification" do
5
5
  before do
6
- FakeWeb.allow_net_connect = true # enable network connections just for this test
6
+ FakeWeb.allow_net_connect = true
7
7
  end
8
8
 
9
9
  after do
10
- FakeWeb.allow_net_connect = false # Restore allow_net_connect value for testing
10
+ FakeWeb.allow_net_connect = false
11
11
  end
12
12
 
13
- it "should work with when no trusted CA list is specified" do
13
+ it "should work when no trusted CA list is specified" do
14
14
  ssl_verify_test(nil, nil, "selfsigned.crt").should == {'success' => true}
15
15
  end
16
16
 
17
- it "should work with when no trusted CA list is specified, even with a bogus hostname" do
17
+ it "should work when no trusted CA list is specified, even with a bogus hostname" do
18
18
  ssl_verify_test(nil, nil, "bogushost.crt").should == {'success' => true}
19
19
  end
20
20
 
@@ -25,8 +25,14 @@ describe HTTParty::Request do
25
25
  it "should work when using ssl_ca_file with a certificate authority" do
26
26
  ssl_verify_test(:ssl_ca_file, "ca.crt", "server.crt").should == {'success' => true}
27
27
  end
28
+
28
29
  it "should work when using ssl_ca_path with a certificate authority" do
29
- ssl_verify_test(:ssl_ca_path, ".", "server.crt").should == {'success' => true}
30
+ http = Net::HTTP.new('www.google.com', 443, nil, nil, nil, nil)
31
+ response = stub(Net::HTTPResponse, :[] => '', :body => '', :to_hash => {})
32
+ http.stub(:request).and_return(response)
33
+ Net::HTTP.should_receive(:new).with('www.google.com', 443, nil, nil, nil, nil).and_return(http)
34
+ http.should_receive(:ca_path=).with('/foo/bar')
35
+ HTTParty.get('https://www.google.com', :ssl_ca_path => '/foo/bar')
30
36
  end
31
37
 
32
38
  it "should fail when using ssl_ca_file and the server uses an unrecognized certificate authority" do
@@ -34,6 +40,7 @@ describe HTTParty::Request do
34
40
  ssl_verify_test(:ssl_ca_file, "ca.crt", "selfsigned.crt")
35
41
  end.should raise_error(OpenSSL::SSL::SSLError)
36
42
  end
43
+
37
44
  it "should fail when using ssl_ca_path and the server uses an unrecognized certificate authority" do
38
45
  lambda do
39
46
  ssl_verify_test(:ssl_ca_path, ".", "selfsigned.crt")
@@ -45,6 +52,7 @@ describe HTTParty::Request do
45
52
  ssl_verify_test(:ssl_ca_file, "ca.crt", "bogushost.crt")
46
53
  end.should raise_error(OpenSSL::SSL::SSLError)
47
54
  end
55
+
48
56
  it "should fail when using ssl_ca_path and the server uses a bogus hostname" do
49
57
  lambda do
50
58
  ssl_verify_test(:ssl_ca_path, ".", "bogushost.crt")
@@ -10,6 +10,7 @@ describe HTTParty do
10
10
  before do
11
11
  Kernel.stub(:warn)
12
12
  end
13
+
13
14
  it "warns with a deprecation message" do
14
15
  Kernel.should_receive(:warn).with("Deprecated: Use HTTParty::Parser::SupportedFormats")
15
16
  HTTParty::AllowedFormats
@@ -19,9 +20,8 @@ describe HTTParty do
19
20
  HTTParty::AllowedFormats.should == HTTParty::Parser::SupportedFormats
20
21
  end
21
22
  end
22
-
23
- describe "pem" do
24
23
 
24
+ describe "pem" do
25
25
  it 'should set the pem content' do
26
26
  @klass.pem 'PEM-CONTENT'
27
27
  @klass.default_options[:pem].should == 'PEM-CONTENT'
@@ -36,7 +36,29 @@ describe HTTParty do
36
36
  @klass.pem 'PEM-CONTENT', 'PASSWORD'
37
37
  @klass.default_options[:pem_password].should == 'PASSWORD'
38
38
  end
39
+ end
40
+
41
+ describe 'ssl_version' do
42
+ it 'should set the ssl_version content' do
43
+ @klass.ssl_version :SSLv3
44
+ @klass.default_options[:ssl_version].should == :SSLv3
45
+ end
46
+ end
47
+
48
+ describe 'http_proxy' do
49
+ it 'should set the address' do
50
+ @klass.http_proxy 'proxy.foo.com', 80
51
+ options = @klass.default_options
52
+ options[:http_proxyaddr].should == 'proxy.foo.com'
53
+ options[:http_proxyport].should == 80
54
+ end
39
55
 
56
+ it 'should set the proxy user and pass when they are provided' do
57
+ @klass.http_proxy 'proxy.foo.com', 80, 'user', 'pass'
58
+ options = @klass.default_options
59
+ options[:http_proxyuser].should == 'user'
60
+ options[:http_proxypass].should == 'pass'
61
+ end
40
62
  end
41
63
 
42
64
  describe "base uri" do
@@ -88,6 +110,11 @@ describe HTTParty do
88
110
  HTTParty.normalize_base_uri(uri)
89
111
  uri.should == 'http://api.foobar.com'
90
112
  end
113
+
114
+ it "should not treat uri's with a port of 4430 as ssl" do
115
+ uri = HTTParty.normalize_base_uri('http://api.foo.com:4430/v1')
116
+ uri.should == 'http://api.foo.com:4430/v1'
117
+ end
91
118
  end
92
119
 
93
120
  describe "headers" do
@@ -306,6 +333,38 @@ describe HTTParty do
306
333
  end
307
334
  end
308
335
 
336
+ describe "connection_adapter" do
337
+ let(:uri) { 'http://google.com/api.json' }
338
+ let(:connection_adapter) { mock('CustomConnectionAdapter') }
339
+
340
+ it "should set the connection_adapter" do
341
+ @klass.connection_adapter connection_adapter
342
+ @klass.default_options[:connection_adapter].should be connection_adapter
343
+ end
344
+
345
+ it "should set the connection_adapter_options when provided" do
346
+ options = {:foo => :bar}
347
+ @klass.connection_adapter connection_adapter, options
348
+ @klass.default_options[:connection_adapter_options].should be options
349
+ end
350
+
351
+ it "should not set the connection_adapter_options when not provided" do
352
+ @klass.connection_adapter connection_adapter
353
+ @klass.default_options[:connection_adapter_options].should be_nil
354
+ end
355
+
356
+ it "should process a request with a connection from the adapter" do
357
+ connection_adapter_options = {:foo => :bar}
358
+ connection_adapter.should_receive(:call) do |u,o|
359
+ o[:connection_adapter_options].should == connection_adapter_options
360
+ HTTParty::ConnectionAdapter.call(u,o)
361
+ end.with(URI.parse(uri), kind_of(Hash))
362
+ FakeWeb.register_uri(:get, uri, :body => 'stuff')
363
+ @klass.connection_adapter connection_adapter, connection_adapter_options
364
+ @klass.get(uri).should == 'stuff'
365
+ end
366
+ end
367
+
309
368
  describe "format" do
310
369
  it "should allow xml" do
311
370
  @klass.format :xml
@@ -417,6 +476,12 @@ describe HTTParty do
417
476
  end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
418
477
  end
419
478
 
479
+ it "should fail with redirected PATCH" do
480
+ lambda do
481
+ @klass.patch('/foo', :no_follow => true)
482
+ end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
483
+ end
484
+
420
485
  it "should fail with redirected DELETE" do
421
486
  lambda do
422
487
  @klass.delete('/foo', :no_follow => true)
@@ -505,6 +570,14 @@ describe HTTParty do
505
570
  @parent.default_options.should == {:basic_auth => {:username => 'user', :password => 'password'}}
506
571
  end
507
572
 
573
+ it "doesn't modify hashes in the parent's default options" do
574
+ @parent.headers 'Accept' => 'application/json'
575
+ @child1.headers 'Accept' => 'application/xml'
576
+
577
+ @parent.default_options[:headers].should == {'Accept' => 'application/json'}
578
+ @child1.default_options[:headers].should == {'Accept' => 'application/xml'}
579
+ end
580
+
508
581
  it "inherits default_cookies from the parent class" do
509
582
  @parent.cookies 'type' => 'chocolate_chip'
510
583
  @child1.default_cookies.should == {"type" => "chocolate_chip"}
@@ -546,6 +619,15 @@ describe HTTParty do
546
619
  HTTParty.get('http://www.google.com').should == file_fixture('google.html')
547
620
  end
548
621
 
622
+ it "should be able to get chunked html" do
623
+ chunks = ["Chunk1", "Chunk2", "Chunk3", "Chunk4"]
624
+ stub_chunked_http_response_with(chunks)
625
+
626
+ HTTParty.get('http://www.google.com') do |fragment|
627
+ chunks.should include(fragment)
628
+ end.should == chunks.join
629
+ end
630
+
549
631
  it "should be able parse response type json automatically" do
550
632
  stub_http_response_with('twitter.json')
551
633
  tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.json')
data/spec/spec.opts CHANGED
@@ -1,3 +1,2 @@
1
1
  --colour
2
- --format specdoc
3
2
  --backtrace
data/spec/spec_helper.rb CHANGED
@@ -13,10 +13,18 @@ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].e
13
13
  Spec::Runner.configure do |config|
14
14
  config.include HTTParty::StubResponse
15
15
  config.include HTTParty::SSLTestHelper
16
+
16
17
  config.before(:suite) do
17
18
  FakeWeb.allow_net_connect = false
18
19
  end
20
+
19
21
  config.after(:suite) do
20
22
  FakeWeb.allow_net_connect = true
21
23
  end
22
24
  end
25
+
26
+ Spec::Matchers.define :use_ssl do
27
+ match do |connection|
28
+ connection.use_ssl?
29
+ end
30
+ end
@@ -1,25 +1,47 @@
1
+ require 'pathname'
2
+
1
3
  module HTTParty
2
4
  module SSLTestHelper
3
5
  def ssl_verify_test(mode, ca_basename, server_cert_filename)
4
- test_server = nil
6
+ options = {
7
+ :format => :json,
8
+ :timeout => 30,
9
+ }
10
+
11
+ if mode
12
+ ca_path = File.expand_path("../../fixtures/ssl/generated/#{ca_basename}", __FILE__)
13
+ raise ArgumentError.new("#{ca_path} does not exist") unless File.exist?(ca_path)
14
+ options[mode] = ca_path
15
+ end
16
+
5
17
  begin
6
- # Start an HTTPS server
7
18
  test_server = SSLTestServer.new(
8
19
  :rsa_key => File.read(File.expand_path("../../fixtures/ssl/generated/server.key", __FILE__)),
9
- :cert => File.read(File.expand_path("../../fixtures/ssl/generated/#{server_cert_filename}", __FILE__)))
20
+ :cert => File.read(File.expand_path("../../fixtures/ssl/generated/#{server_cert_filename}", __FILE__)))
21
+
10
22
  test_server.start
11
23
 
12
- # Build a request
13
24
  if mode
14
25
  ca_path = File.expand_path("../../fixtures/ssl/generated/#{ca_basename}", __FILE__)
15
26
  raise ArgumentError.new("#{ca_path} does not exist") unless File.exist?(ca_path)
16
- return HTTParty.get("https://localhost:#{test_server.port}/", :format => :json, :timeout=>30, mode => ca_path)
27
+ return HTTParty.get("https://localhost:#{test_server.port}/", :format => :json, :timeout => 30, mode => ca_path)
17
28
  else
18
- return HTTParty.get("https://localhost:#{test_server.port}/", :format => :json, :timeout=>30)
29
+ return HTTParty.get("https://localhost:#{test_server.port}/", :format => :json, :timeout => 30)
19
30
  end
20
31
  ensure
21
32
  test_server.stop if test_server
22
33
  end
34
+
35
+ test_server = SSLTestServer.new({
36
+ :rsa_key => path.join('server.key').read,
37
+ :cert => path.join(server_cert_filename).read,
38
+ })
39
+
40
+ test_server.start
41
+
42
+ HTTParty.get("https://localhost:#{test_server.port}/", options)
43
+ ensure
44
+ test_server.stop if test_server
23
45
  end
24
46
  end
25
47
  end
@@ -10,26 +10,30 @@ class SSLTestServer
10
10
  attr_reader :port
11
11
 
12
12
  def initialize(options={})
13
- @ctx = OpenSSL::SSL::SSLContext.new
14
- @ctx.cert = OpenSSL::X509::Certificate.new(options[:cert])
15
- @ctx.key = OpenSSL::PKey::RSA.new(options[:rsa_key])
13
+ @ctx = OpenSSL::SSL::SSLContext.new
14
+ @ctx.cert = OpenSSL::X509::Certificate.new(options[:cert])
15
+ @ctx.key = OpenSSL::PKey::RSA.new(options[:rsa_key])
16
16
  @ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # Don't verify client certificate
17
- @port = options[:port] || 0
18
- @thread = nil
19
- @stopping_mutex = Mutex.new
20
- @stopping = false
17
+ @port = options[:port] || 0
18
+ @thread = nil
19
+ @stopping_mutex = Mutex.new
20
+ @stopping = false
21
21
  end
22
22
 
23
23
  def start
24
24
  @raw_server = TCPServer.new(@port)
25
+
25
26
  if @port == 0
26
27
  @port = Socket::getnameinfo(@raw_server.getsockname, Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV)[1].to_i
27
28
  end
29
+
28
30
  @ssl_server = OpenSSL::SSL::SSLServer.new(@raw_server, @ctx)
31
+
29
32
  @stopping_mutex.synchronize{
30
33
  return if @stopping
31
34
  @thread = Thread.new{ thread_main }
32
35
  }
36
+
33
37
  nil
34
38
  end
35
39
 
@@ -46,24 +50,31 @@ class SSLTestServer
46
50
  def thread_main
47
51
  until @stopping_mutex.synchronize{ @stopping }
48
52
  (rr,ww,ee) = select([@ssl_server.to_io], nil, nil, 0.1)
53
+
49
54
  next unless rr && rr.include?(@ssl_server.to_io)
55
+
50
56
  socket = @ssl_server.accept
57
+
51
58
  Thread.new{
52
59
  header = []
60
+
53
61
  until (line = socket.readline).rstrip.empty?
54
62
  header << line
55
63
  end
56
64
 
57
- socket.write <<'EOF'.gsub(/\r\n/n, "\n").gsub(/\n/n, "\r\n")
65
+ response =<<EOF
58
66
  HTTP/1.1 200 OK
59
67
  Connection: close
60
68
  Content-Type: application/json; charset=UTF-8
61
69
 
62
70
  {"success":true}
63
71
  EOF
72
+
73
+ socket.write(response.gsub(/\r\n/n, "\n").gsub(/\n/n, "\r\n"))
64
74
  socket.close
65
75
  }
66
76
  end
77
+
67
78
  @ssl_server.close
68
79
  end
69
80
  end
@@ -13,6 +13,19 @@ module HTTParty
13
13
  HTTParty::Request.should_receive(:new).and_return(http_request)
14
14
  end
15
15
 
16
+ def stub_chunked_http_response_with(chunks)
17
+ response = Net::HTTPResponse.new("1.1", 200, nil)
18
+ response.stub(:chunked_data).and_return(chunks)
19
+ def response.read_body(&block)
20
+ @body || chunked_data.each(&block)
21
+ end
22
+
23
+ http_request = HTTParty::Request.new(Net::HTTP::Get, 'http://localhost', :format => "html")
24
+ http_request.stub_chain(:http, :request).and_yield(response).and_return(response)
25
+
26
+ HTTParty::Request.should_receive(:new).and_return(http_request)
27
+ end
28
+
16
29
  def stub_response(body, code = 200)
17
30
  @request.options[:base_uri] ||= 'http://localhost'
18
31
  unless defined?(@http) && @http