httpi 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -132,4 +132,32 @@ describe HTTPI::Auth::Config do
132
132
  end
133
133
  end
134
134
 
135
+ describe "#ntlm" do
136
+ it "lets you specify the ntlm auth credentials" do
137
+ auth.ntlm "username", "password"
138
+ auth.ntlm.should == ["username", "password"]
139
+ end
140
+
141
+ it "also accepts an Array of credentials" do
142
+ auth.ntlm ["username", "password"]
143
+ auth.ntlm.should == ["username", "password"]
144
+ end
145
+
146
+ it "sets the authentication type to :ntlm" do
147
+ auth.ntlm "username", "password"
148
+ auth.type.should == :ntlm
149
+ end
150
+ end
151
+
152
+ describe "#ntlm?" do
153
+ it "defaults to return false" do
154
+ auth.should_not be_ntlm
155
+ end
156
+
157
+ it "returns true for HTTP ntlm auth" do
158
+ auth.ntlm "username", "password"
159
+ auth.should be_ntlm
160
+ end
161
+ end
162
+
135
163
  end
@@ -1,6 +1,10 @@
1
1
  require "spec_helper"
2
+ require "integration/support/server"
2
3
 
3
4
  # find out why httpi doesn't load these automatically. [dh, 2012-12-15]
5
+ require "excon"
6
+ require "net/http/persistent"
7
+
4
8
  unless RUBY_VERSION < "1.9"
5
9
  require "em-synchrony"
6
10
  require "em-http-request"
@@ -13,6 +17,15 @@ describe HTTPI do
13
17
  let(:client) { HTTPI }
14
18
  let(:httpclient) { HTTPI::Adapter.load(:httpclient) }
15
19
  let(:net_http) { HTTPI::Adapter.load(:net_http) }
20
+ let(:net_http_persistent) { HTTPI::Adapter.load(:net_http_persistent) }
21
+
22
+ before(:all) do
23
+ HTTPI::Adapter::Rack.mount('example.com', IntegrationServer::Application)
24
+ end
25
+
26
+ after(:all) do
27
+ HTTPI::Adapter::Rack.unmount('example.com')
28
+ end
16
29
 
17
30
  describe ".adapter=" do
18
31
  it "sets the default adapter to use" do
@@ -204,7 +217,10 @@ describe HTTPI do
204
217
  :httpclient => lambda { HTTPClient },
205
218
  :curb => lambda { Curl::Easy },
206
219
  :net_http => lambda { Net::HTTP },
207
- :em_http => lambda { EventMachine::HttpConnection }
220
+ :net_http_persistent => lambda { Net::HTTP::Persistent },
221
+ :em_http => lambda { EventMachine::HttpConnection },
222
+ :rack => lambda { Rack::MockRequest },
223
+ :excon => lambda { Excon::Connection }
208
224
  }
209
225
 
210
226
  context "using #{adapter}" do
@@ -78,6 +78,18 @@ describe HTTPI::Adapter::Curb do
78
78
  response = HTTPI.get(request, adapter)
79
79
  response.body.should eq("digest-auth")
80
80
  end
81
+
82
+ it "supports chunked response" do
83
+ request = HTTPI::Request.new(@server.url)
84
+ res = ""
85
+ request.on_body do |body|
86
+ res += body
87
+ end
88
+ response = HTTPI.post(request, adapter)
89
+ res.should eq("post")
90
+ response.body.should eq("")
91
+ end
92
+
81
93
  end
82
94
 
83
95
  context "https requests" do
@@ -81,6 +81,8 @@ describe HTTPI::Adapter::EmHttpRequest do
81
81
  end
82
82
 
83
83
  # it does not support digest authentication
84
+
85
+ # it does not support chunked response
84
86
  end
85
87
 
86
88
  # it does not support ssl authentication
@@ -75,27 +75,41 @@ describe HTTPI::Adapter::HTTPClient do
75
75
  response = HTTPI.get(request, adapter)
76
76
  response.body.should eq("digest-auth")
77
77
  end
78
- end
79
-
80
- context "https requests" do
81
- before :all do
82
- @server = IntegrationServer.run(:ssl => true)
83
- end
84
78
 
85
- after :all do
86
- @server.stop
87
- end
88
-
89
- it "raises when no certificate was set up" do
90
- expect { HTTPI.post(@server.url, "", adapter) }.to raise_error(HTTPI::SSLError)
91
- end
92
-
93
- it "works when set up properly" do
79
+ it "supports chunked response" do
94
80
  request = HTTPI::Request.new(@server.url)
95
- request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
81
+ res = ""
82
+ request.on_body do |body|
83
+ res += body
84
+ end
85
+ response = HTTPI.post(request, adapter)
86
+ res.should eq("post")
87
+ response.body.should eq("")
88
+ end
89
+ end
96
90
 
97
- response = HTTPI.get(request, adapter)
98
- expect(response.body).to eq("get")
91
+ if RUBY_PLATFORM =~ /java/
92
+ pending "Puma Server complains: SSL not supported on JRuby"
93
+ else
94
+ context "https requests" do
95
+ before :all do
96
+ @server = IntegrationServer.run(:ssl => true)
97
+ end
98
+ after :all do
99
+ @server.stop
100
+ end
101
+
102
+ it "raises when no certificate was set up" do
103
+ expect { HTTPI.post(@server.url, "", adapter) }.to raise_error(HTTPI::SSLError)
104
+ end
105
+
106
+ it "works when set up properly" do
107
+ request = HTTPI::Request.new(@server.url)
108
+ request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
109
+
110
+ response = HTTPI.get(request, adapter)
111
+ expect(response.body).to eq("get")
112
+ end
99
113
  end
100
114
  end
101
115
 
@@ -0,0 +1,139 @@
1
+ require "spec_helper"
2
+ require "integration/support/server"
3
+
4
+ describe HTTPI::Adapter::NetHTTP do
5
+
6
+ subject(:adapter) { :net_http_persistent }
7
+
8
+ context "http requests" do
9
+ before :all do
10
+ @server = IntegrationServer.run
11
+ end
12
+
13
+ after :all do
14
+ @server.stop
15
+ end
16
+
17
+ it "sends and receives HTTP headers" do
18
+ request = HTTPI::Request.new(@server.url + "x-header")
19
+ request.headers["X-Header"] = "HTTPI"
20
+
21
+ response = HTTPI.get(request, adapter)
22
+ response.body.should include("HTTPI")
23
+ end
24
+
25
+ it "it supports headers with multiple values" do
26
+ request = HTTPI::Request.new(@server.url + "cookies")
27
+
28
+ response = HTTPI.get(request, adapter)
29
+ cookies = ["cookie1=chip1; path=/", "cookie2=chip2; path=/"]
30
+ response.headers["Set-Cookie"].should eq(cookies)
31
+ end
32
+
33
+ it "executes GET requests" do
34
+ response = HTTPI.get(@server.url, adapter)
35
+ response.body.should eq("get")
36
+ response.headers["Content-Type"].should eq("text/plain")
37
+ end
38
+
39
+ it "executes POST requests" do
40
+ response = HTTPI.post(@server.url, "<some>xml</some>", adapter)
41
+ response.body.should eq("post")
42
+ response.headers["Content-Type"].should eq("text/plain")
43
+ end
44
+
45
+ it "executes HEAD requests" do
46
+ response = HTTPI.head(@server.url, adapter)
47
+ response.code.should == 200
48
+ response.headers["Content-Type"].should eq("text/plain")
49
+ end
50
+
51
+ it "executes PUT requests" do
52
+ response = HTTPI.put(@server.url, "<some>xml</some>", adapter)
53
+ response.body.should eq("put")
54
+ response.headers["Content-Type"].should eq("text/plain")
55
+ end
56
+
57
+ it "executes DELETE requests" do
58
+ response = HTTPI.delete(@server.url, adapter)
59
+ response.body.should eq("delete")
60
+ response.headers["Content-Type"].should eq("text/plain")
61
+ end
62
+
63
+ it "supports basic authentication" do
64
+ request = HTTPI::Request.new(@server.url + "basic-auth")
65
+ request.auth.basic("admin", "secret")
66
+
67
+ response = HTTPI.get(request, adapter)
68
+ response.body.should eq("basic-auth")
69
+ end
70
+
71
+ # it does not support digest authentication
72
+
73
+ it "supports chunked response" do
74
+ request = HTTPI::Request.new(@server.url)
75
+ res = ""
76
+ request.on_body do |body|
77
+ res += body
78
+ end
79
+ response = HTTPI.post(request, adapter)
80
+ res.should eq("post")
81
+ response.body.to_s.should eq("")
82
+ end
83
+ end
84
+
85
+ if RUBY_PLATFORM =~ /java/
86
+ pending "Puma Server complains: SSL not supported on JRuby"
87
+ else
88
+ context "https requests" do
89
+ before :all do
90
+ @server = IntegrationServer.run(:ssl => true)
91
+ end
92
+ after :all do
93
+ @server.stop
94
+ end
95
+
96
+ # does not raise when no certificate was set up
97
+ it "works when set up properly" do
98
+ request = HTTPI::Request.new(@server.url)
99
+ request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
100
+
101
+ response = HTTPI.get(request, adapter)
102
+ expect(response.body).to eq("get")
103
+ end
104
+ end
105
+ end
106
+
107
+ # The built-in Rack IntegrationServer and specs support a basic simulated NTLM exchange
108
+ # that does not require anything outside of the normal gem test infrastructure.
109
+ # (see spec/httpi/adapter/net_http_spec.rb: it "supports ntlm authentication"
110
+ # and spec/integration/support/application.rb: map "/ntlm-auth")
111
+ # But since that simulated exchange is based on recorded traffic, you may wish to
112
+ # run the following integration test against a real external NTLM server from time to time.
113
+ #
114
+ # This test must be specially enabled because it requires an external
115
+ # Windows 2012 Server configured according to the instructions found here:
116
+ # https://github.com/savonrb/httpi/wiki/NTLM-Integration-Test-Plan
117
+ #
118
+ # Once you have that server running as instructed, you can include this test by setting
119
+ # NTLM=external via the command line, e.g.:
120
+ # $ NTLM=external bundle exec rspec
121
+ #
122
+ if ENV["NTLM"]=="external"
123
+ context "http request via NTLM" do
124
+ it "works with NTLM connections" do
125
+ user = "tester"
126
+ pass = "vReqSoafRe5O"
127
+ request = HTTPI::Request.new("http://ntlmtest/")
128
+ request.auth.ntlm(user,pass)
129
+ response = HTTPI.get(request, adapter)
130
+ expect(response.code).to eq(200)
131
+ response.body.should match(/iis-8\.png/)
132
+
133
+ puts "EXTERNAL NTLM INTEGRATION TEST, response body:"
134
+ puts response.body
135
+ end
136
+ end
137
+ end
138
+
139
+ end
@@ -69,25 +69,70 @@ describe HTTPI::Adapter::NetHTTP do
69
69
  end
70
70
 
71
71
  # it does not support digest authentication
72
- end
73
72
 
74
- context "https requests" do
75
- before :all do
76
- @server = IntegrationServer.run(:ssl => true)
73
+ it "supports chunked response" do
74
+ request = HTTPI::Request.new(@server.url)
75
+ res = ""
76
+ request.on_body do |body|
77
+ res += body
78
+ end
79
+ response = HTTPI.post(request, adapter)
80
+ res.should eq("post")
81
+ response.body.to_s.should eq("")
77
82
  end
83
+ end
78
84
 
79
- after :all do
80
- @server.stop
85
+ if RUBY_PLATFORM =~ /java/
86
+ pending "Puma Server complains: SSL not supported on JRuby"
87
+ else
88
+ context "https requests" do
89
+ before :all do
90
+ @server = IntegrationServer.run(:ssl => true)
91
+ end
92
+ after :all do
93
+ @server.stop
94
+ end
95
+
96
+ # does not raise when no certificate was set up
97
+ it "works when set up properly" do
98
+ request = HTTPI::Request.new(@server.url)
99
+ request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
100
+
101
+ response = HTTPI.get(request, adapter)
102
+ expect(response.body).to eq("get")
103
+ end
81
104
  end
105
+ end
82
106
 
83
- # does not raise when no certificate was set up
84
-
85
- it "works when set up properly" do
86
- request = HTTPI::Request.new(@server.url)
87
- request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
88
-
89
- response = HTTPI.get(request, adapter)
90
- expect(response.body).to eq("get")
107
+ # The built-in Rack IntegrationServer and specs support a basic simulated NTLM exchange
108
+ # that does not require anything outside of the normal gem test infrastructure.
109
+ # (see spec/httpi/adapter/net_http_spec.rb: it "supports ntlm authentication"
110
+ # and spec/integration/support/application.rb: map "/ntlm-auth")
111
+ # But since that simulated exchange is based on recorded traffic, you may wish to
112
+ # run the following integration test against a real external NTLM server from time to time.
113
+ #
114
+ # This test must be specially enabled because it requires an external
115
+ # Windows 2012 Server configured according to the instructions found here:
116
+ # https://github.com/savonrb/httpi/wiki/NTLM-Integration-Test-Plan
117
+ #
118
+ # Once you have that server running as instructed, you can include this test by setting
119
+ # NTLM=external via the command line, e.g.:
120
+ # $ NTLM=external bundle exec rspec
121
+ #
122
+ if ENV["NTLM"]=="external"
123
+ context "http request via NTLM" do
124
+ it "works with NTLM connections" do
125
+ user = "tester"
126
+ pass = "vReqSoafRe5O"
127
+ request = HTTPI::Request.new("http://ntlmtest/")
128
+ request.auth.ntlm(user,pass)
129
+ response = HTTPI.get(request, adapter)
130
+ expect(response.code).to eq(200)
131
+ response.body.should match(/iis-8\.png/)
132
+
133
+ puts "EXTERNAL NTLM INTEGRATION TEST, response body:"
134
+ puts response.body
135
+ end
91
136
  end
92
137
  end
93
138
 
@@ -47,6 +47,34 @@ class IntegrationServer
47
47
  }
48
48
  end
49
49
 
50
+ map "/ntlm-auth" do
51
+ run lambda { |env|
52
+ resp = [401, {"WWW-Authenticate" => "NTLM\r\nNegotiate"}, []]
53
+ # head request 1: challenge & response (from actual server)
54
+ if env["HTTP_AUTHORIZATION"] =~ /(NTLM|Negotiate) TlRMTVNTUAABAAAAB4IIAA/
55
+ resp = [401, {
56
+ "Content-Type" => "text/html; charset=us-ascii",
57
+ "Server" => "Microsoft-HTTPAPI/2.0",
58
+ "WWW-Authenticate" => "#{$1} TlRMTVNTUAACAAAAEAAQADgAAAAFgooCj/AvDazHhQsAAAAAAAAAAGAAYABIAAAABgLwIwAAAA9OAFQATABNAFQARQBTAFQAAgAQAE4AVABMAE0AVABFAFMAVAABABAATgBUAEwATQBUAEUAUwBUAAQAEABuAHQAbABtAHQAZQBzAHQAAwAQAG4AdABsAG0AdABlAHMAdAAHAAgAfzQp037nzQEAAAAA",
59
+ "Date" => "Mon, 31 Dec 2012 17:46:55 GMT",
60
+ "Content-Length" => "341"
61
+ }, []]
62
+ elsif env["HTTP_AUTHORIZATION"] =~ /(NTLM|Negotiate) (.+)/
63
+ # request 2: serve content
64
+ resp = IntegrationServer.respond_with "ntlm-auth"
65
+ else
66
+ resp = [401, {
67
+ "Content-Type" => "text/html; charset=us-ascii",
68
+ "WWW-Authenticate" => "NTLM\r\nNegotiate",
69
+ "Server" => "Microsoft-HTTPAPI/2.0",
70
+ "Date" => "Mon, 31 Dec 2012 17:46:55 GMT",
71
+ "Content-Length" => "341"
72
+ }, []]
73
+ end
74
+ resp
75
+ }
76
+ end
77
+
50
78
  map "/digest-auth" do
51
79
  unprotected_app = lambda { |env|
52
80
  IntegrationServer.respond_with "digest-auth"
data/spec/spec_helper.rb CHANGED
@@ -1,16 +1,25 @@
1
- require "bundler"
1
+ require 'bundler'
2
2
  Bundler.setup(:default, :development)
3
3
 
4
- require "httpi"
4
+ unless RUBY_PLATFORM =~ /java/
5
+ require 'simplecov'
6
+ require 'coveralls'
5
7
 
6
- require "rspec"
7
- require "mocha/api"
8
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
9
+ SimpleCov.start do
10
+ add_filter 'spec'
11
+ end
12
+ end
13
+
14
+ require 'httpi'
15
+ require 'rspec'
8
16
 
9
17
  RSpec.configure do |config|
10
18
  config.mock_with :mocha
19
+ config.order = 'random'
11
20
  end
12
21
 
13
22
  HTTPI.log = false
14
23
 
15
- require "support/fixture"
16
- require "support/matchers"
24
+ require 'support/fixture'
25
+ require 'support/matchers'