httpi 2.0.0.rc1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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