em-http-request-samesite 1.1.7

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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +0 -0
  5. data/.travis.yml +7 -0
  6. data/Changelog.md +68 -0
  7. data/Gemfile +14 -0
  8. data/README.md +63 -0
  9. data/Rakefile +10 -0
  10. data/benchmarks/clients.rb +170 -0
  11. data/benchmarks/em-excon.rb +87 -0
  12. data/benchmarks/em-profile.gif +0 -0
  13. data/benchmarks/em-profile.txt +65 -0
  14. data/benchmarks/server.rb +48 -0
  15. data/em-http-request.gemspec +32 -0
  16. data/examples/.gitignore +1 -0
  17. data/examples/digest_auth/client.rb +25 -0
  18. data/examples/digest_auth/server.rb +28 -0
  19. data/examples/fetch.rb +30 -0
  20. data/examples/fibered-http.rb +51 -0
  21. data/examples/multi.rb +25 -0
  22. data/examples/oauth-tweet.rb +35 -0
  23. data/examples/socks5.rb +23 -0
  24. data/lib/em-http-request.rb +1 -0
  25. data/lib/em-http.rb +20 -0
  26. data/lib/em-http/client.rb +341 -0
  27. data/lib/em-http/core_ext/bytesize.rb +6 -0
  28. data/lib/em-http/decoders.rb +252 -0
  29. data/lib/em-http/http_client_options.rb +49 -0
  30. data/lib/em-http/http_connection.rb +321 -0
  31. data/lib/em-http/http_connection_options.rb +70 -0
  32. data/lib/em-http/http_encoding.rb +149 -0
  33. data/lib/em-http/http_header.rb +83 -0
  34. data/lib/em-http/http_status_codes.rb +57 -0
  35. data/lib/em-http/middleware/digest_auth.rb +112 -0
  36. data/lib/em-http/middleware/json_response.rb +15 -0
  37. data/lib/em-http/middleware/oauth.rb +40 -0
  38. data/lib/em-http/middleware/oauth2.rb +28 -0
  39. data/lib/em-http/multi.rb +57 -0
  40. data/lib/em-http/request.rb +23 -0
  41. data/lib/em-http/version.rb +5 -0
  42. data/lib/em/io_streamer.rb +49 -0
  43. data/spec/client_fiber_spec.rb +23 -0
  44. data/spec/client_spec.rb +1000 -0
  45. data/spec/digest_auth_spec.rb +48 -0
  46. data/spec/dns_spec.rb +41 -0
  47. data/spec/encoding_spec.rb +49 -0
  48. data/spec/external_spec.rb +150 -0
  49. data/spec/fixtures/google.ca +16 -0
  50. data/spec/fixtures/gzip-sample.gz +0 -0
  51. data/spec/gzip_spec.rb +91 -0
  52. data/spec/helper.rb +31 -0
  53. data/spec/http_proxy_spec.rb +268 -0
  54. data/spec/middleware/oauth2_spec.rb +15 -0
  55. data/spec/middleware_spec.rb +143 -0
  56. data/spec/multi_spec.rb +104 -0
  57. data/spec/pipelining_spec.rb +66 -0
  58. data/spec/redirect_spec.rb +430 -0
  59. data/spec/socksify_proxy_spec.rb +60 -0
  60. data/spec/spec_helper.rb +25 -0
  61. data/spec/ssl_spec.rb +71 -0
  62. data/spec/stallion.rb +334 -0
  63. data/spec/stub_server.rb +45 -0
  64. metadata +265 -0
@@ -0,0 +1,48 @@
1
+ require 'helper'
2
+
3
+ $: << 'lib' << '../lib'
4
+
5
+ require 'em-http/middleware/digest_auth'
6
+
7
+ describe 'Digest Auth Authentication header generation' do
8
+ before :each do
9
+ @reference_header = 'Digest username="digest_username", realm="DigestAuth_REALM", algorithm=MD5, uri="/", nonce="MDAxMzQzNzQwNjA2OmRjZjAyZDY3YWMyMWVkZGQ4OWE2Nzg3ZTY3YTNlMjg5", response="96829962ffc31fa2852f86dc7f9f609b", opaque="BzdNK3gsJ2ixTrBJ"'
10
+ end
11
+
12
+ it 'should generate the correct header' do
13
+ www_authenticate = 'Digest realm="DigestAuth_REALM", nonce="MDAxMzQzNzQwNjA2OmRjZjAyZDY3YWMyMWVkZGQ4OWE2Nzg3ZTY3YTNlMjg5", opaque="BzdNK3gsJ2ixTrBJ", stale=false, algorithm=MD5'
14
+
15
+ params = {
16
+ username: 'digest_username',
17
+ password: 'digest_password'
18
+ }
19
+
20
+ middleware = EM::Middleware::DigestAuth.new(www_authenticate, params)
21
+ middleware.build_auth_digest('GET', '/').should == @reference_header
22
+ end
23
+
24
+ it 'should not generate the same header for a different user' do
25
+ www_authenticate = 'Digest realm="DigestAuth_REALM", nonce="MDAxMzQzNzQwNjA2OmRjZjAyZDY3YWMyMWVkZGQ4OWE2Nzg3ZTY3YTNlMjg5", opaque="BzdNK3gsJ2ixTrBJ", stale=false, algorithm=MD5'
26
+
27
+ params = {
28
+ username: 'digest_username_2',
29
+ password: 'digest_password'
30
+ }
31
+
32
+ middleware = EM::Middleware::DigestAuth.new(www_authenticate, params)
33
+ middleware.build_auth_digest('GET', '/').should_not == @reference_header
34
+ end
35
+
36
+ it 'should not generate the same header if the nounce changes' do
37
+ www_authenticate = 'Digest realm="DigestAuth_REALM", nonce="MDAxMzQzNzQwNjA2OmRjZjAyZDY3YWMyMWVkZGQ4OWE2Nzg3ZTY3YTNlMjg6", opaque="BzdNK3gsJ2ixTrBJ", stale=false, algorithm=MD5'
38
+
39
+ params = {
40
+ username: 'digest_username_2',
41
+ password: 'digest_password'
42
+ }
43
+
44
+ middleware = EM::Middleware::DigestAuth.new(www_authenticate, params)
45
+ middleware.build_auth_digest('GET', '/').should_not == @reference_header
46
+ end
47
+
48
+ end
data/spec/dns_spec.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'helper'
2
+
3
+ describe EventMachine::HttpRequest do
4
+
5
+ it "should fail gracefully on an invalid host in Location header" do
6
+ EventMachine.run {
7
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/redirect/badhost', :connect_timeout => 0.1).get :redirects => 1
8
+ http.callback { failed(http) }
9
+ http.errback {
10
+ http.error.should match(/unable to resolve (server |)address/)
11
+ EventMachine.stop
12
+ }
13
+ }
14
+ end
15
+
16
+ it "should fail GET on DNS timeout" do
17
+ EventMachine.run {
18
+ EventMachine.heartbeat_interval = 0.1
19
+ http = EventMachine::HttpRequest.new('http://127.1.1.1/', :connect_timeout => 0.1).get
20
+ http.callback { failed(http) }
21
+ http.errback {
22
+ http.response_header.status.should == 0
23
+ EventMachine.stop
24
+ }
25
+ }
26
+ end
27
+
28
+ it "should fail GET on invalid host" do
29
+ EventMachine.run {
30
+ EventMachine.heartbeat_interval = 0.1
31
+ http = EventMachine::HttpRequest.new('http://somethinglocal/', :connect_timeout => 0.1).get
32
+ http.callback { failed(http) }
33
+ http.errback {
34
+ http.error.should match(/unable to resolve (server |)address/)
35
+ http.response_header.status.should == 0
36
+ EventMachine.stop
37
+ }
38
+ }
39
+ end
40
+
41
+ end
@@ -0,0 +1,49 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'helper'
4
+
5
+ describe EventMachine::HttpEncoding do
6
+ include EventMachine::HttpEncoding
7
+
8
+ it "should transform a basic hash into HTTP POST Params" do
9
+ form_encode_body({:a => "alpha", :b => "beta"}).should == "a=alpha&b=beta"
10
+ end
11
+
12
+ it "should transform a more complex hash into HTTP POST Params" do
13
+ form_encode_body({:a => "a", :b => ["c", "d", "e"]}).should == "a=a&b[0]=c&b[1]=d&b[2]=e"
14
+ end
15
+
16
+ it "should transform a very complex hash into HTTP POST Params" do
17
+ params = form_encode_body({:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]})
18
+ # 1.8.7 does not have ordered hashes.
19
+ params.split(/&/).sort.join('&').should == "a=a&b[0][c]=c&b[0][d]=d&b[1][e]=e&b[1][f]=f"
20
+ end
21
+
22
+ it "should escape values" do
23
+ params = form_encode_body({:stuff => 'string&string'})
24
+ params.should == "stuff=string%26string"
25
+ end
26
+
27
+ it "should escape keys" do
28
+ params = form_encode_body({'bad&str'=> {'key&key' => [:a, :b]}})
29
+ params.should == 'bad%26str[key%26key][0]=a&bad%26str[key%26key][1]=b'
30
+ end
31
+
32
+ it "should escape keys and values" do
33
+ params = form_encode_body({'bad&str'=> {'key&key' => ['bad+&stuff', '[test]']}})
34
+ params.should == "bad%26str[key%26key][0]=bad%2B%26stuff&bad%26str[key%26key][1]=%5Btest%5D"
35
+ end
36
+
37
+ it "should not issue warnings on non-ASCII encodings" do
38
+ # I don't know how to check for ruby warnings.
39
+ params = escape('valö')
40
+ params = escape('valö'.encode('ISO-8859-15'))
41
+ end
42
+
43
+ # xit "should be fast on long string escapes" do
44
+ # s = Time.now
45
+ # 5000.times { |n| form_encode_body({:a => "{a:'b', d:'f', g:['a','b']}"*50}) }
46
+ # (Time.now - s).should satisfy { |t| t < 1.5 }
47
+ # end
48
+
49
+ end
@@ -0,0 +1,150 @@
1
+ require 'helper'
2
+
3
+ requires_connection do
4
+
5
+ describe EventMachine::HttpRequest do
6
+
7
+ it "should follow redirects on HEAD method (external)" do
8
+ EventMachine.run {
9
+ http = EventMachine::HttpRequest.new('http://www.google.com/').head :redirects => 1
10
+ http.errback { failed(http) }
11
+ http.callback {
12
+ http.response_header.status.should == 200
13
+ EM.stop
14
+ }
15
+ }
16
+ end
17
+
18
+ it "should follow redirect to https and initiate the handshake" do
19
+ EventMachine.run {
20
+ http = EventMachine::HttpRequest.new('http://github.com/').get :redirects => 5
21
+
22
+ http.errback { failed(http) }
23
+ http.callback {
24
+ http.response_header.status.should == 200
25
+ EventMachine.stop
26
+ }
27
+ }
28
+ end
29
+
30
+ it "should perform a streaming GET" do
31
+ EventMachine.run {
32
+
33
+ # digg.com uses chunked encoding
34
+ http = EventMachine::HttpRequest.new('http://www.httpwatch.com/httpgallery/chunked/').get
35
+
36
+ http.errback { failed(http) }
37
+ http.callback {
38
+ http.response_header.status.should == 200
39
+ EventMachine.stop
40
+ }
41
+ }
42
+ end
43
+
44
+ it "should handle a 100 continue" do
45
+ EventMachine.run {
46
+ # 8.2.3 Use of the 100 (Continue) Status - http://www.ietf.org/rfc/rfc2616.txt
47
+ #
48
+ # An origin server SHOULD NOT send a 100 (Continue) response if
49
+ # the request message does not include an Expect request-header
50
+ # field with the "100-continue" expectation, and MUST NOT send a
51
+ # 100 (Continue) response if such a request comes from an HTTP/1.0
52
+ # (or earlier) client. There is an exception to this rule: for
53
+ # compatibility with RFC 2068, a server MAY send a 100 (Continue)
54
+ # status in response to an HTTP/1.1 PUT or POST request that does
55
+ # not include an Expect request-header field with the "100-
56
+ # continue" expectation. This exception, the purpose of which is
57
+ # to minimize any client processing delays associated with an
58
+ # undeclared wait for 100 (Continue) status, applies only to
59
+ # HTTP/1.1 requests, and not to requests with any other HTTP-
60
+ # version value.
61
+ #
62
+ # 10.1.1: 100 Continue - http://www.ietf.org/rfc/rfc2068.txt
63
+ # The client may continue with its request. This interim response is
64
+ # used to inform the client that the initial part of the request has
65
+ # been received and has not yet been rejected by the server. The client
66
+ # SHOULD continue by sending the remainder of the request or, if the
67
+ # request has already been completed, ignore this response. The server
68
+ # MUST send a final response after the request has been completed.
69
+
70
+ url = 'http://ws.serviceobjects.com/lv/LeadValidation.asmx/ValidateLead_V2'
71
+ http = EventMachine::HttpRequest.new(url).post :body => {:name => :test}
72
+
73
+ http.errback { failed(http) }
74
+ http.callback {
75
+ http.response_header.status.should == 500
76
+ http.response.should match('Missing')
77
+ EventMachine.stop
78
+ }
79
+ }
80
+ end
81
+
82
+ it "should detect deflate encoding" do
83
+ # pending "need an endpoint which supports deflate.. MSN is no longer"
84
+ EventMachine.run {
85
+
86
+ options = {:head => {"accept-encoding" => "deflate"}, :redirects => 5}
87
+ http = EventMachine::HttpRequest.new('http://www.libpng.org/').get options
88
+
89
+ http.errback { failed(http) }
90
+ http.callback {
91
+ http.response_header.status.should == 200
92
+ http.response_header["CONTENT_ENCODING"].should == "deflate"
93
+
94
+ EventMachine.stop
95
+ }
96
+ }
97
+ end
98
+
99
+ it "should stream chunked gzipped data" do
100
+ EventMachine.run {
101
+ options = {:head => {"accept-encoding" => "gzip"}}
102
+ # GitHub sends chunked gzip, time for a little Inception ;)
103
+ http = EventMachine::HttpRequest.new('https://github.com/igrigorik/em-http-request/commits/master').get options
104
+
105
+ http.errback { failed(http) }
106
+ http.callback {
107
+ http.response_header.status.should == 200
108
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
109
+ http.response.should == ''
110
+
111
+ EventMachine.stop
112
+ }
113
+
114
+ body = ''
115
+ http.stream do |chunk|
116
+ body << chunk
117
+ end
118
+ }
119
+ end
120
+
121
+ context "keepalive" do
122
+ it "should default to non-keepalive" do
123
+ EventMachine.run {
124
+ headers = {'If-Modified-Since' => 'Thu, 05 Aug 2010 22:54:44 GMT'}
125
+ http = EventMachine::HttpRequest.new('http://www.google.com/images/logos/ps_logo2.png').get :head => headers
126
+
127
+ http.errback { fail }
128
+ start = Time.now.to_i
129
+ http.callback {
130
+ (Time.now.to_i - start).should be_within(2).of(0)
131
+ EventMachine.stop
132
+ }
133
+ }
134
+ end
135
+
136
+ it "should work with keep-alive servers" do
137
+ EventMachine.run {
138
+ http = EventMachine::HttpRequest.new('https://github.com/igrigorik/em-http-request').get :keepalive => true
139
+
140
+ http.errback { failed(http) }
141
+ http.callback {
142
+ http.response_header.status.should == 200
143
+ EventMachine.stop
144
+ }
145
+ }
146
+ end
147
+ end
148
+
149
+ end
150
+ end
@@ -0,0 +1,16 @@
1
+ HTTP/1.1 301 Moved Permanently
2
+ Location: http://www.google.ca/
3
+ Content-Type: text/html; charset=UTF-8
4
+ Date: Sun, 09 Jan 2011 02:51:43 GMT
5
+ Expires: Tue, 08 Feb 2011 02:51:43 GMT
6
+ Cache-Control: public, max-age=2592000
7
+ Server: gws
8
+ Content-Length: 218
9
+ X-XSS-Protection: 1; mode=block
10
+
11
+ <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
12
+ <TITLE>301 Moved</TITLE></HEAD><BODY>
13
+ <H1>301 Moved</H1>
14
+ The document has moved
15
+ <A HREF="http://www.google.ca/">here</A>.
16
+ </BODY></HTML>
Binary file
data/spec/gzip_spec.rb ADDED
@@ -0,0 +1,91 @@
1
+ require 'helper'
2
+
3
+ describe EventMachine::HttpDecoders::GZip do
4
+
5
+ let(:compressed) {
6
+ compressed = ["1f8b08089668a6500003686900cbc8e402007a7a6fed03000000"].pack("H*")
7
+ }
8
+
9
+ it "should extract the stream of a vanilla gzip" do
10
+ header = EventMachine::HttpDecoders::GZipHeader.new
11
+ stream = header.extract_stream(compressed)
12
+
13
+ stream.unpack("H*")[0].should eq("cbc8e402007a7a6fed03000000")
14
+ end
15
+
16
+ it "should decompress a vanilla gzip" do
17
+ decompressed = ""
18
+
19
+ gz = EventMachine::HttpDecoders::GZip.new do |data|
20
+ decompressed << data
21
+ end
22
+
23
+ gz << compressed
24
+ gz.finalize!
25
+
26
+ decompressed.should eq("hi\n")
27
+ end
28
+
29
+ it "should decompress a vanilla gzip file byte by byte" do
30
+ decompressed = ""
31
+
32
+ gz = EventMachine::HttpDecoders::GZip.new do |data|
33
+ decompressed << data
34
+ end
35
+
36
+ compressed.each_char do |byte|
37
+ gz << byte
38
+ end
39
+
40
+ gz.finalize!
41
+
42
+ decompressed.should eq("hi\n")
43
+ end
44
+
45
+ it "should decompress a large file" do
46
+ decompressed = ""
47
+
48
+ gz = EventMachine::HttpDecoders::GZip.new do |data|
49
+ decompressed << data
50
+ end
51
+
52
+ gz << File.read(File.dirname(__FILE__) + "/fixtures/gzip-sample.gz")
53
+
54
+ gz.finalize!
55
+
56
+ decompressed.size.should eq(32907)
57
+ end
58
+
59
+ it "should not care how many chunks the file is split up into" do
60
+ examples = [
61
+ ["\x1F", "\x8B", "\b", "\x00", "\x00", "\x00", "\x00", "\x00", "\x00", "\x00", "\xF3", "\xCB", "/", "Q", "p\xCB/\xCDK\x01\x00M\x8Ct\xB1\t\x00\x00\x00"],
62
+ ["\x1F", "\x8B", "\b", "\x00", "\x00", "\x00", "\x00", "\x00\x00\x00\xF3\xCB/Qp\xCB/\xCDK\x01\x00M\x8Ct\xB1\t\x00\x00\x00"]
63
+ ]
64
+
65
+ examples.each do |example|
66
+ decompressed = ""
67
+
68
+ gz = EventMachine::HttpDecoders::GZip.new do |data|
69
+ decompressed << data
70
+ end
71
+
72
+ example.each do |bytes|
73
+ gz << bytes
74
+ end
75
+
76
+ gz.finalize!
77
+
78
+ decompressed.should eq("Not Found")
79
+ end
80
+ end
81
+
82
+ it "should fail with a DecoderError if not a gzip file" do
83
+ not_a_gzip = ["1f8c08089668a650000"].pack("H*")
84
+ header = EventMachine::HttpDecoders::GZipHeader.new
85
+
86
+ lambda {
87
+ header.extract_stream(not_a_gzip)
88
+ }.should raise_exception(EventMachine::HttpDecoders::DecoderError)
89
+ end
90
+
91
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+
5
+ require 'em-http'
6
+ require 'em-http/middleware/oauth2'
7
+ require 'multi_json'
8
+
9
+ require 'stallion'
10
+ require 'stub_server'
11
+
12
+ def failed(http = nil)
13
+ EventMachine.stop
14
+ http ? fail(http.error) : fail
15
+ end
16
+
17
+ def requires_connection(&blk)
18
+ blk.call if system('ping -t1 -c1 google.com 2>&1 > /dev/null')
19
+ end
20
+
21
+ def requires_port(port, &blk)
22
+ port_open = true
23
+ begin
24
+ s = TCPSocket.new('localhost', port)
25
+ s.close()
26
+ rescue
27
+ port_open = false
28
+ end
29
+
30
+ blk.call if port_open
31
+ end
@@ -0,0 +1,268 @@
1
+ require 'helper'
2
+
3
+ shared_examples "*_PROXY var (through proxy)" do
4
+ it "should use HTTP proxy" do
5
+ EventMachine.run {
6
+ http = EventMachine::HttpRequest.new("#{proxy_test_scheme}://127.0.0.1:8090/?q=test").get
7
+
8
+ http.errback { failed(http) }
9
+ http.callback {
10
+ http.response_header.status.should == 200
11
+ http.response_header.should_not include("X_PROXY_AUTH")
12
+ http.response.should match('test')
13
+ EventMachine.stop
14
+ }
15
+ }
16
+ end
17
+ end
18
+
19
+ shared_examples "*_PROXY var (testing var)" do
20
+ subject { HttpConnectionOptions.new("#{proxy_test_scheme}://example.com", {}) }
21
+ it { expect(subject.proxy_from_env).to eq({ :host => "127.0.0.1", :port => 8083, :type => :http }) }
22
+ it { expect(subject.host).to eq "127.0.0.1" }
23
+ it { expect(subject.port).to be 8083 }
24
+ it do
25
+ case proxy_test_scheme.to_sym
26
+ when :http
27
+ expect(subject.http_proxy?).to be_truthy
28
+ when :https
29
+ expect(subject.connect_proxy?).to be_truthy
30
+ end
31
+ end
32
+ end
33
+
34
+ describe EventMachine::HttpRequest do
35
+
36
+ context "connections via" do
37
+ context "without *_PROXY env" do
38
+ let(:proxy) { {:proxy => { :host => '127.0.0.1', :port => 8083 }} }
39
+ let(:authenticated_proxy) { {:proxy => { :host => '127.0.0.1', :port => 8083, :authorization => ["user", "name"] } } }
40
+
41
+ it "should use HTTP proxy" do
42
+ EventMachine.run {
43
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/?q=test', proxy).get
44
+
45
+ http.errback { failed(http) }
46
+ http.callback {
47
+ http.response_header.status.should == 200
48
+ http.response_header.should_not include("X_PROXY_AUTH")
49
+ http.response.should match('test')
50
+ EventMachine.stop
51
+ }
52
+ }
53
+ end
54
+
55
+ it "should use HTTP proxy with authentication" do
56
+ EventMachine.run {
57
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/proxyauth?q=test', authenticated_proxy).get
58
+
59
+ http.errback { failed(http) }
60
+ http.callback {
61
+ http.response_header.status.should == 200
62
+ http.response_header['X_PROXY_AUTH'].should == "Proxy-Authorization: Basic dXNlcjpuYW1l"
63
+ http.response.should match('test')
64
+ EventMachine.stop
65
+ }
66
+ }
67
+ end
68
+
69
+ it "should send absolute URIs to the proxy server" do
70
+ EventMachine.run {
71
+
72
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/?q=test', proxy).get
73
+
74
+ http.errback { failed(http) }
75
+ http.callback {
76
+ http.response_header.status.should == 200
77
+
78
+ # The test proxy server gives the requested uri back in this header
79
+ http.response_header['X_THE_REQUESTED_URI'].should == 'http://127.0.0.1:8090/?q=test'
80
+ http.response_header['X_THE_REQUESTED_URI'].should_not == '/?q=test'
81
+ http.response.should match('test')
82
+ EventMachine.stop
83
+ }
84
+ }
85
+ end
86
+
87
+ it "should strip basic auth from before the host in URI sent to proxy" do
88
+ EventMachine.run {
89
+
90
+ http = EventMachine::HttpRequest.new('http://user:pass@127.0.0.1:8090/echo_authorization_header', proxy).get
91
+
92
+ http.errback { failed(http) }
93
+ http.callback {
94
+ http.response_header.status.should == 200
95
+ # The test proxy server gives the requested uri back in this header
96
+ http.response_header['X_THE_REQUESTED_URI'].should == 'http://127.0.0.1:8090/echo_authorization_header'
97
+ # Ensure the basic auth was converted to a header correctly
98
+ http.response.should match('authorization:Basic dXNlcjpwYXNz')
99
+ EventMachine.stop
100
+ }
101
+ }
102
+ end
103
+
104
+ it "should include query parameters specified in the options" do
105
+ EventMachine.run {
106
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/', proxy).get :query => { 'q' => 'test' }
107
+
108
+ http.errback { failed(http) }
109
+ http.callback {
110
+ http.response_header.status.should == 200
111
+ http.response.should match('test')
112
+ EventMachine.stop
113
+ }
114
+ }
115
+ end
116
+
117
+ it "should use HTTP proxy while redirecting" do
118
+ EventMachine.run {
119
+ http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/redirect', proxy).get :redirects => 1
120
+
121
+ http.errback { failed(http) }
122
+ http.callback {
123
+ http.response_header.status.should == 200
124
+
125
+ http.response_header['X_THE_REQUESTED_URI'].should == 'http://127.0.0.1:8090/gzip'
126
+ http.response_header['X_THE_REQUESTED_URI'].should_not == '/redirect'
127
+
128
+ http.response_header["CONTENT_ENCODING"].should == "gzip"
129
+ http.response.should == "compressed"
130
+ http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/gzip'
131
+ http.redirects.should == 1
132
+
133
+ EventMachine.stop
134
+ }
135
+ }
136
+ end
137
+ end
138
+
139
+ context "when parsing *_PROXY var (through proxy)s" do
140
+ context "with $HTTP_PROXY env" do
141
+ let(:proxy_test_scheme) { :http }
142
+
143
+ before(:all) do
144
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
145
+ ENV['HTTP_PROXY'] = 'http://127.0.0.1:8083'
146
+ end
147
+
148
+ include_examples "*_PROXY var (through proxy)"
149
+ end
150
+
151
+ context "with $http_proxy env" do
152
+ let(:proxy_test_scheme) { :http }
153
+
154
+ before(:all) do
155
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
156
+ ENV['http_proxy'] = 'http://127.0.0.1:8083'
157
+ end
158
+
159
+ include_examples "*_PROXY var (through proxy)"
160
+ end
161
+
162
+ ## TODO: Use a Mongrel HTTP server that can handle SSL:
163
+ context "with $HTTPS_PROXY env", skip: "Mongrel isn't configured to handle HTTPS, currently" do
164
+ let(:proxy_test_scheme) { :https }
165
+
166
+ before(:all) do
167
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
168
+ ENV['HTTPS_PROXY'] = 'http://127.0.0.1:8083'
169
+ end
170
+
171
+ include_examples "*_PROXY var (through proxy)"
172
+ end
173
+
174
+ ## TODO: Use a Mongrel HTTP server that can handle SSL:
175
+ context "with $https_proxy env", skip: "Mongrel isn't configured to handle HTTPS, currently" do
176
+ let(:proxy_test_scheme) { :https }
177
+
178
+ before(:all) do
179
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
180
+ ENV['https_proxy'] = 'http://127.0.0.1:8083'
181
+ end
182
+
183
+ include_examples "*_PROXY var (through proxy)"
184
+ end
185
+
186
+ context "with $ALL_PROXY env" do
187
+ let(:proxy_test_scheme) { :http }
188
+
189
+ before(:all) do
190
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
191
+ ENV['ALL_PROXY'] = 'http://127.0.0.1:8083'
192
+ end
193
+
194
+ include_examples "*_PROXY var (through proxy)"
195
+ end
196
+ end
197
+ end
198
+
199
+ context "when parsing *_PROXY vars" do
200
+ context "without a *_PROXY var" do
201
+ before(:all) do
202
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
203
+ end
204
+
205
+ subject { HttpConnectionOptions.new("http://example.com", {}) }
206
+ it { expect(subject.proxy_from_env).to be_nil }
207
+ it { expect(subject.host).to eq "example.com" }
208
+ it { expect(subject.port).to be 80 }
209
+ it { expect(subject.http_proxy?).to be_falsey }
210
+ it { expect(subject.connect_proxy?).to be_falsey }
211
+ end
212
+
213
+ context "with $HTTP_PROXY env" do
214
+ let(:proxy_test_scheme) { :http }
215
+
216
+ before(:each) do
217
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
218
+ ENV['HTTP_PROXY'] = 'http://127.0.0.1:8083'
219
+ end
220
+
221
+ include_examples "*_PROXY var (testing var)"
222
+ end
223
+
224
+ context "with $http_proxy env" do
225
+ let(:proxy_test_scheme) { :http }
226
+
227
+ before(:each) do
228
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
229
+ ENV['http_proxy'] = 'http://127.0.0.1:8083'
230
+ end
231
+
232
+ include_examples "*_PROXY var (testing var)"
233
+ end
234
+
235
+ context "with $HTTPS_PROXY env" do
236
+ let(:proxy_test_scheme) { :https }
237
+
238
+ before(:each) do
239
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
240
+ ENV['HTTPS_PROXY'] = 'http://127.0.0.1:8083'
241
+ end
242
+
243
+ include_examples "*_PROXY var (testing var)"
244
+ end
245
+
246
+ context "with $https_proxy env" do
247
+ let(:proxy_test_scheme) { :https }
248
+
249
+ before(:each) do
250
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
251
+ ENV['https_proxy'] = 'http://127.0.0.1:8083'
252
+ end
253
+
254
+ include_examples "*_PROXY var (testing var)"
255
+ end
256
+
257
+ context "with $ALL_PROXY env" do
258
+ let(:proxy_test_scheme) { :https }
259
+
260
+ before(:each) do
261
+ PROXY_ENV_VARS.each {|k| ENV.delete k }
262
+ ENV['ALL_PROXY'] = 'http://127.0.0.1:8083'
263
+ end
264
+
265
+ include_examples "*_PROXY var (testing var)"
266
+ end
267
+ end
268
+ end