httpi 2.0.0.rc1 → 2.0.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.
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+ require "integration/support/server"
3
+
4
+ describe HTTPI::Adapter::EmHttpRequest do
5
+
6
+ # em_http is not supported on ruby 1.8
7
+ unless RUBY_VERSION =~ /1\.8/
8
+ require "em-synchrony"
9
+
10
+ subject(:adapter) { :em_http }
11
+
12
+ around :each do |example|
13
+ EM.synchrony do
14
+ example.run
15
+ EM.stop
16
+ end
17
+ end
18
+
19
+ context "http requests" do
20
+ before :all do
21
+ # for some reason, these specs don't work with "localhost". [dh, 2012-12-15]
22
+ @server = IntegrationServer.run(:host => "127.0.0.1")
23
+ end
24
+
25
+ after :all do
26
+ @server.stop
27
+ end
28
+
29
+ it "sends and receives HTTP headers" do
30
+ request = HTTPI::Request.new(@server.url + "x-header")
31
+ request.headers["X-Header"] = "HTTPI"
32
+
33
+ response = HTTPI.get(request, adapter)
34
+ response.body.should include("HTTPI")
35
+ end
36
+
37
+ it "executes GET requests" do
38
+ response = HTTPI.get(@server.url, adapter)
39
+ response.body.should eq("get")
40
+ response.headers["Content-Type"].should eq("text/plain")
41
+ end
42
+
43
+ it "executes POST requests" do
44
+ response = HTTPI.post(@server.url, "<some>xml</some>", adapter)
45
+ response.body.should eq("post")
46
+ response.headers["Content-Type"].should eq("text/plain")
47
+ end
48
+
49
+ it "executes HEAD requests" do
50
+ response = HTTPI.head(@server.url, adapter)
51
+ response.code.should == 200
52
+ response.headers["Content-Type"].should eq("text/plain")
53
+ end
54
+
55
+ it "executes PUT requests" do
56
+ response = HTTPI.put(@server.url, "<some>xml</some>", adapter)
57
+ response.body.should eq("put")
58
+ response.headers["Content-Type"].should eq("text/plain")
59
+ end
60
+
61
+ it "executes DELETE requests" do
62
+ response = HTTPI.delete(@server.url, adapter)
63
+ response.body.should eq("delete")
64
+ response.headers["Content-Type"].should eq("text/plain")
65
+ end
66
+
67
+ it "supports basic authentication" do
68
+ request = HTTPI::Request.new(@server.url + "basic-auth")
69
+ request.auth.basic("admin", "secret")
70
+
71
+ response = HTTPI.get(request, adapter)
72
+ response.body.should eq("basic-auth")
73
+ end
74
+
75
+ # it does not support digest authentication
76
+ end
77
+
78
+ # it does not support ssl authentication
79
+
80
+ end
81
+ end
@@ -0,0 +1,94 @@
1
+ require "spec_helper"
2
+ require "integration/support/server"
3
+
4
+ describe HTTPI::Adapter::HTTPClient do
5
+
6
+ subject(:adapter) { :httpclient }
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 "executes GET requests" do
26
+ response = HTTPI.get(@server.url, adapter)
27
+ response.body.should eq("get")
28
+ response.headers["Content-Type"].should eq("text/plain")
29
+ end
30
+
31
+ it "executes POST requests" do
32
+ response = HTTPI.post(@server.url, "<some>xml</some>", adapter)
33
+ response.body.should eq("post")
34
+ response.headers["Content-Type"].should eq("text/plain")
35
+ end
36
+
37
+ it "executes HEAD requests" do
38
+ response = HTTPI.head(@server.url, adapter)
39
+ response.code.should == 200
40
+ response.headers["Content-Type"].should eq("text/plain")
41
+ end
42
+
43
+ it "executes PUT requests" do
44
+ response = HTTPI.put(@server.url, "<some>xml</some>", adapter)
45
+ response.body.should eq("put")
46
+ response.headers["Content-Type"].should eq("text/plain")
47
+ end
48
+
49
+ it "executes DELETE requests" do
50
+ response = HTTPI.delete(@server.url, adapter)
51
+ response.body.should eq("delete")
52
+ response.headers["Content-Type"].should eq("text/plain")
53
+ end
54
+
55
+ it "supports basic authentication" do
56
+ request = HTTPI::Request.new(@server.url + "basic-auth")
57
+ request.auth.basic("admin", "secret")
58
+
59
+ response = HTTPI.get(request, adapter)
60
+ response.body.should eq("basic-auth")
61
+ end
62
+
63
+ it "supports digest authentication" do
64
+ request = HTTPI::Request.new(@server.url + "digest-auth")
65
+ request.auth.digest("admin", "secret")
66
+
67
+ response = HTTPI.get(request, adapter)
68
+ response.body.should eq("digest-auth")
69
+ end
70
+ end
71
+
72
+ context "https requests" do
73
+ before :all do
74
+ @server = IntegrationServer.run(:ssl => true)
75
+ end
76
+
77
+ after :all do
78
+ @server.stop
79
+ end
80
+
81
+ it "raises when no certificate was set up" do
82
+ expect { HTTPI.post(@server.url, "", adapter) }.to raise_error(HTTPI::SSLError)
83
+ end
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")
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,86 @@
1
+ require "spec_helper"
2
+ require "integration/support/server"
3
+
4
+ describe HTTPI::Adapter::NetHTTP do
5
+
6
+ subject(:adapter) { :net_http }
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 "executes GET requests" do
26
+ response = HTTPI.get(@server.url, adapter)
27
+ response.body.should eq("get")
28
+ response.headers["Content-Type"].should eq("text/plain")
29
+ end
30
+
31
+ it "executes POST requests" do
32
+ response = HTTPI.post(@server.url, "<some>xml</some>", adapter)
33
+ response.body.should eq("post")
34
+ response.headers["Content-Type"].should eq("text/plain")
35
+ end
36
+
37
+ it "executes HEAD requests" do
38
+ response = HTTPI.head(@server.url, adapter)
39
+ response.code.should == 200
40
+ response.headers["Content-Type"].should eq("text/plain")
41
+ end
42
+
43
+ it "executes PUT requests" do
44
+ response = HTTPI.put(@server.url, "<some>xml</some>", adapter)
45
+ response.body.should eq("put")
46
+ response.headers["Content-Type"].should eq("text/plain")
47
+ end
48
+
49
+ it "executes DELETE requests" do
50
+ response = HTTPI.delete(@server.url, adapter)
51
+ response.body.should eq("delete")
52
+ response.headers["Content-Type"].should eq("text/plain")
53
+ end
54
+
55
+ it "supports basic authentication" do
56
+ request = HTTPI::Request.new(@server.url + "basic-auth")
57
+ request.auth.basic("admin", "secret")
58
+
59
+ response = HTTPI.get(request, adapter)
60
+ response.body.should eq("basic-auth")
61
+ end
62
+
63
+ # it does not support digest authentication
64
+ end
65
+
66
+ context "https requests" do
67
+ before :all do
68
+ @server = IntegrationServer.run(:ssl => true)
69
+ end
70
+
71
+ after :all do
72
+ @server.stop
73
+ end
74
+
75
+ # does not raise when no certificate was set up
76
+
77
+ it "works when set up properly" do
78
+ request = HTTPI::Request.new(@server.url)
79
+ request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
80
+
81
+ response = HTTPI.get(request, adapter)
82
+ expect(response.body).to eq("get")
83
+ end
84
+ end
85
+
86
+ end
@@ -0,0 +1,56 @@
1
+ require "rack/builder"
2
+
3
+ class IntegrationServer
4
+
5
+ def self.respond_with(body)
6
+ [200, { "Content-Type" => "text/plain", "Content-Length" => body.size.to_s }, [body]]
7
+ end
8
+
9
+ Application = Rack::Builder.new do
10
+
11
+ map "/" do
12
+ run lambda { |env|
13
+ IntegrationServer.respond_with env["REQUEST_METHOD"].downcase
14
+ }
15
+ end
16
+
17
+ map "/repeat" do
18
+ run lambda { |env|
19
+ IntegrationServer.respond_with :body => env["rack.input"].read
20
+ }
21
+ end
22
+
23
+ map "/x-header" do
24
+ run lambda { |env|
25
+ IntegrationServer.respond_with env["HTTP_X_HEADER"]
26
+ }
27
+ end
28
+
29
+ map "/basic-auth" do
30
+ use Rack::Auth::Basic, "basic-realm" do |username, password|
31
+ username == "admin" && password == "secret"
32
+ end
33
+
34
+ run lambda { |env|
35
+ IntegrationServer.respond_with "basic-auth"
36
+ }
37
+ end
38
+
39
+ map "/digest-auth" do
40
+ unprotected_app = lambda { |env|
41
+ IntegrationServer.respond_with "digest-auth"
42
+ }
43
+
44
+ realm = 'digest-realm'
45
+ app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
46
+ username == 'admin' ? Digest::MD5.hexdigest("admin:#{realm}:secret") : nil
47
+ end
48
+ app.realm = realm
49
+ app.opaque = 'this-should-be-secret'
50
+ app.passwords_hashed = true
51
+
52
+ run app
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,84 @@
1
+ require "puma"
2
+ require "puma/minissl"
3
+
4
+ require "integration/support/application"
5
+
6
+ class IntegrationServer
7
+
8
+ def self.run(options = {})
9
+ server = new(options)
10
+ server.run
11
+ server
12
+ end
13
+
14
+ def self.ssl_ca_file; integration_fixture("ca_all.pem") end
15
+ def self.ssl_key_file; integration_fixture("server.key") end
16
+ def self.ssl_cert_file; integration_fixture("server.cert") end
17
+
18
+ def self.integration_fixture(file)
19
+ file = File.expand_path("../../fixtures/#{file}", __FILE__)
20
+ raise "No such file '#{file}'" unless File.exist? file
21
+ file
22
+ end
23
+
24
+ def initialize(options = {})
25
+ @app = Application
26
+ @host = options.fetch(:host, "localhost")
27
+ @port = options.fetch(:port, 17172)
28
+ @ssl = options.fetch(:ssl, false)
29
+
30
+ @server = Puma::Server.new(app, events)
31
+
32
+ if ssl?
33
+ add_ssl_listener
34
+ else
35
+ add_tcp_listener
36
+ end
37
+ end
38
+
39
+ attr_reader :app, :host, :port, :server
40
+
41
+ def url(path = nil)
42
+ protocol = ssl? ? "https" : "http"
43
+ File.join "#{protocol}://#{host}:#{port}/", path.to_s
44
+ end
45
+
46
+ def ssl?
47
+ @ssl
48
+ end
49
+
50
+ def run
51
+ server.run
52
+ end
53
+
54
+ def stop
55
+ server.stop(true)
56
+ end
57
+
58
+ private
59
+
60
+ def events
61
+ Puma::Events.new($stdout, $stderr)
62
+ end
63
+
64
+ def add_tcp_listener
65
+ server.add_tcp_listener(host, port)
66
+ rescue Errno::EADDRINUSE
67
+ raise "Panther is already running at #{url}"
68
+ end
69
+
70
+ def add_ssl_listener
71
+ server.add_ssl_listener(host, port, ssl_context)
72
+ end
73
+
74
+ def ssl_context
75
+ context = Puma::MiniSSL::Context.new
76
+
77
+ context.key = IntegrationServer.ssl_key_file
78
+ context.cert = IntegrationServer.ssl_cert_file
79
+ context.verify_mode = Puma::MiniSSL::VERIFY_PEER
80
+
81
+ context
82
+ end
83
+
84
+ end
@@ -1,12 +1,16 @@
1
1
  require "bundler"
2
- Bundler.require :default, :development
2
+ Bundler.setup(:default, :development)
3
+
4
+ require "httpi"
5
+
6
+ require "rspec"
7
+ require "mocha/api"
3
8
 
4
9
  RSpec.configure do |config|
5
- config.include WebMock::API
6
10
  config.mock_with :mocha
7
11
  end
8
12
 
9
- HTTPI.log = false # disable for specs
13
+ HTTPI.log = false
10
14
 
11
15
  require "support/fixture"
12
16
  require "support/matchers"
@@ -0,0 +1,26 @@
1
+ module ErrorHelper
2
+
3
+ class Expectation
4
+
5
+ def initialize(error, spec)
6
+ @error = error
7
+ @spec = spec
8
+ end
9
+
10
+ def to(tag_error)
11
+ @spec.expect(@error).to @spec.be_a(tag_error)
12
+ end
13
+
14
+ end
15
+
16
+ def expect_error(error_to_raise, message)
17
+ fake_error(error_to_raise, message)
18
+ rescue => error
19
+ Expectation.new(error, self)
20
+ end
21
+
22
+ def be_tagged_with(tag_error)
23
+ tag_error
24
+ end
25
+
26
+ end