em-http-request 1.1.1 → 1.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +7 -0
- data/README.md +5 -4
- data/em-http-request.gemspec +4 -3
- data/lib/em-http.rb +1 -0
- data/lib/em-http/client.rb +35 -12
- data/lib/em-http/decoders.rb +1 -2
- data/lib/em-http/http_client_options.rb +10 -12
- data/lib/em-http/http_connection.rb +114 -10
- data/lib/em-http/http_connection_options.rb +29 -3
- data/lib/em-http/http_encoding.rb +11 -4
- data/lib/em-http/http_header.rb +5 -5
- data/lib/em-http/middleware/json_response.rb +1 -1
- data/lib/em-http/version.rb +1 -1
- data/lib/em/io_streamer.rb +49 -0
- data/spec/client_spec.rb +115 -3
- data/spec/dns_spec.rb +2 -2
- data/spec/external_spec.rb +3 -3
- data/spec/gzip_spec.rb +23 -0
- data/spec/helper.rb +1 -0
- data/spec/http_proxy_spec.rb +241 -63
- data/spec/multi_spec.rb +2 -2
- data/spec/pipelining_spec.rb +4 -4
- data/spec/redirect_spec.rb +109 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/stallion.rb +36 -5
- data/spec/stub_server.rb +6 -3
- metadata +40 -37
@@ -39,19 +39,26 @@ module EventMachine
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def encode_host
|
42
|
-
if @req.uri.port == 80 || @req.uri.port == 443
|
42
|
+
if @req.uri.port.nil? || @req.uri.port == 80 || @req.uri.port == 443
|
43
43
|
return @req.uri.host
|
44
44
|
else
|
45
45
|
@req.uri.host + ":#{@req.uri.port}"
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
def encode_request(method, uri, query,
|
49
|
+
def encode_request(method, uri, query, connopts)
|
50
50
|
query = encode_query(uri, query)
|
51
51
|
|
52
52
|
# Non CONNECT proxies require that you provide the full request
|
53
53
|
# uri in request header, as opposed to a relative path.
|
54
|
-
|
54
|
+
# Don't modify the header with CONNECT proxies. It's unneeded and will
|
55
|
+
# cause 400 Bad Request errors with many standard setups.
|
56
|
+
if connopts.proxy && !connopts.connect_proxy?
|
57
|
+
query = uri.join(query)
|
58
|
+
# Drop the userinfo, it's been converted to a header and won't be
|
59
|
+
# accepted by the proxy
|
60
|
+
query.userinfo = nil
|
61
|
+
end
|
55
62
|
|
56
63
|
HTTP_REQUEST_HEADER % [method.to_s.upcase, query]
|
57
64
|
end
|
@@ -112,7 +119,7 @@ module EventMachine
|
|
112
119
|
# String - custom auth string (OAuth, etc)
|
113
120
|
def encode_auth(k,v)
|
114
121
|
if v.is_a? Array
|
115
|
-
FIELD_ENCODING % [k, ["Basic", Base64.
|
122
|
+
FIELD_ENCODING % [k, ["Basic", Base64.strict_encode64(v.join(":")).split.join].join(" ")]
|
116
123
|
else
|
117
124
|
encode_field(k,v)
|
118
125
|
end
|
data/lib/em-http/http_header.rb
CHANGED
@@ -2,13 +2,13 @@ module EventMachine
|
|
2
2
|
# A simple hash is returned for each request made by HttpClient with the
|
3
3
|
# headers that were given by the server for that request.
|
4
4
|
class HttpResponseHeader < Hash
|
5
|
-
# The reason returned in the http response ("OK"
|
5
|
+
# The reason returned in the http response (string - e.g. "OK")
|
6
6
|
attr_accessor :http_reason
|
7
7
|
|
8
|
-
# The HTTP version returned.
|
8
|
+
# The HTTP version returned (string - e.g. "1.1")
|
9
9
|
attr_accessor :http_version
|
10
10
|
|
11
|
-
# The status code (
|
11
|
+
# The status code (integer - e.g. 200)
|
12
12
|
attr_accessor :http_status
|
13
13
|
|
14
14
|
# Raw headers
|
@@ -23,9 +23,9 @@ module EventMachine
|
|
23
23
|
self[HttpClient::LAST_MODIFIED]
|
24
24
|
end
|
25
25
|
|
26
|
-
# HTTP response status
|
26
|
+
# HTTP response status
|
27
27
|
def status
|
28
|
-
|
28
|
+
Integer(http_status) rescue 0
|
29
29
|
end
|
30
30
|
|
31
31
|
# Length of content as an integer, or nil if chunked/unspecified
|
data/lib/em-http/version.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'em/streamer'
|
2
|
+
|
3
|
+
# similar to EventMachine::FileStreamer, but for any IO object
|
4
|
+
module EventMachine
|
5
|
+
class IOStreamer
|
6
|
+
include Deferrable
|
7
|
+
CHUNK_SIZE = 16384
|
8
|
+
|
9
|
+
# @param [EventMachine::Connection] connection
|
10
|
+
# @param [IO] io Data source
|
11
|
+
# @param [Integer] Data size
|
12
|
+
#
|
13
|
+
# @option opts [Boolean] :http_chunks (false) Use HTTP 1.1 style chunked-encoding semantics.
|
14
|
+
def initialize(connection, io, opts = {})
|
15
|
+
@connection = connection
|
16
|
+
@io = io
|
17
|
+
@http_chunks = opts[:http_chunks]
|
18
|
+
|
19
|
+
@buff = String.new
|
20
|
+
@io.binmode if @io.respond_to?(:binmode)
|
21
|
+
stream_one_chunk
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Used internally to stream one chunk at a time over multiple reactor ticks
|
27
|
+
# @private
|
28
|
+
def stream_one_chunk
|
29
|
+
loop do
|
30
|
+
if @io.eof?
|
31
|
+
@connection.send_data "0\r\n\r\n" if @http_chunks
|
32
|
+
succeed
|
33
|
+
break
|
34
|
+
end
|
35
|
+
|
36
|
+
if @connection.respond_to?(:get_outbound_data_size) && (@connection.get_outbound_data_size > FileStreamer::BackpressureLevel)
|
37
|
+
EventMachine::next_tick { stream_one_chunk }
|
38
|
+
break
|
39
|
+
end
|
40
|
+
|
41
|
+
if @io.read(CHUNK_SIZE, @buff)
|
42
|
+
@connection.send_data("#{@buff.length.to_s(16)}\r\n") if @http_chunks
|
43
|
+
@connection.send_data(@buff)
|
44
|
+
@connection.send_data("\r\n") if @http_chunks
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/client_spec.rb
CHANGED
@@ -42,7 +42,7 @@ describe EventMachine::HttpRequest do
|
|
42
42
|
http.response.should match(/Hello/)
|
43
43
|
EventMachine.stop
|
44
44
|
}
|
45
|
-
}.should_not raise_error
|
45
|
+
}.should_not raise_error
|
46
46
|
|
47
47
|
}
|
48
48
|
end
|
@@ -51,7 +51,7 @@ describe EventMachine::HttpRequest do
|
|
51
51
|
EventMachine.run {
|
52
52
|
lambda {
|
53
53
|
EventMachine::HttpRequest.new('random?text').get
|
54
|
-
}.should raise_error
|
54
|
+
}.should raise_error(Addressable::URI::InvalidURIError)
|
55
55
|
|
56
56
|
EM.stop
|
57
57
|
}
|
@@ -256,6 +256,19 @@ describe EventMachine::HttpRequest do
|
|
256
256
|
}
|
257
257
|
end
|
258
258
|
|
259
|
+
xit "should support expect-continue header" do
|
260
|
+
EventMachine.run {
|
261
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090').post :body => "data", :head => { 'expect' => '100-continue' }
|
262
|
+
|
263
|
+
http.errback { failed(http) }
|
264
|
+
http.callback {
|
265
|
+
http.response_header.status.should == 200
|
266
|
+
http.response.should == "data"
|
267
|
+
EventMachine.stop
|
268
|
+
}
|
269
|
+
}
|
270
|
+
end
|
271
|
+
|
259
272
|
it "should perform successful GET with custom header" do
|
260
273
|
EventMachine.run {
|
261
274
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').get :head => {'if-none-match' => 'evar!'}
|
@@ -386,7 +399,7 @@ describe EventMachine::HttpRequest do
|
|
386
399
|
}
|
387
400
|
end
|
388
401
|
|
389
|
-
it "should detect gzip encoding" do
|
402
|
+
it "should auto-detect and decode gzip encoding" do
|
390
403
|
EventMachine.run {
|
391
404
|
|
392
405
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/gzip').get :head => {"accept-encoding" => "gzip, compressed"}
|
@@ -446,6 +459,36 @@ describe EventMachine::HttpRequest do
|
|
446
459
|
}
|
447
460
|
end
|
448
461
|
|
462
|
+
it "should default to requesting compressed response" do
|
463
|
+
EventMachine.run {
|
464
|
+
|
465
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_accept_encoding').get
|
466
|
+
|
467
|
+
http.errback { failed(http) }
|
468
|
+
http.callback {
|
469
|
+
http.response_header.status.should == 200
|
470
|
+
http.response.should == "gzip, compressed"
|
471
|
+
|
472
|
+
EventMachine.stop
|
473
|
+
}
|
474
|
+
}
|
475
|
+
end
|
476
|
+
|
477
|
+
it "should default to requesting compressed response" do
|
478
|
+
EventMachine.run {
|
479
|
+
|
480
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/echo_accept_encoding').get :compressed => false
|
481
|
+
|
482
|
+
http.errback { failed(http) }
|
483
|
+
http.callback {
|
484
|
+
http.response_header.status.should == 200
|
485
|
+
http.response.should == ""
|
486
|
+
|
487
|
+
EventMachine.stop
|
488
|
+
}
|
489
|
+
}
|
490
|
+
end
|
491
|
+
|
449
492
|
it "should timeout after 0.1 seconds of inactivity" do
|
450
493
|
EventMachine.run {
|
451
494
|
t = Time.now.to_i
|
@@ -759,6 +802,28 @@ describe EventMachine::HttpRequest do
|
|
759
802
|
}
|
760
803
|
end
|
761
804
|
|
805
|
+
it "streams POST request from disk via Pathname" do
|
806
|
+
EventMachine.run {
|
807
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :body => Pathname.new('spec/fixtures/google.ca')
|
808
|
+
http.errback { failed(http) }
|
809
|
+
http.callback {
|
810
|
+
http.response.should match('google')
|
811
|
+
EventMachine.stop
|
812
|
+
}
|
813
|
+
}
|
814
|
+
end
|
815
|
+
|
816
|
+
it "streams POST request from IO object" do
|
817
|
+
EventMachine.run {
|
818
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/').post :body => StringIO.new(File.read('spec/fixtures/google.ca'))
|
819
|
+
http.errback { failed(http) }
|
820
|
+
http.callback {
|
821
|
+
http.response.should match('google')
|
822
|
+
EventMachine.stop
|
823
|
+
}
|
824
|
+
}
|
825
|
+
end
|
826
|
+
|
762
827
|
it "should reconnect if connection was closed between requests" do
|
763
828
|
EventMachine.run {
|
764
829
|
conn = EM::HttpRequest.new('http://127.0.0.1:8090/')
|
@@ -848,6 +913,33 @@ describe EventMachine::HttpRequest do
|
|
848
913
|
}
|
849
914
|
end
|
850
915
|
|
916
|
+
it "should close connection on invalid HTTP response" do
|
917
|
+
EventMachine.run {
|
918
|
+
response =<<-HTTP.gsub(/^ +/, '').strip
|
919
|
+
HTTP/1.1 403 Forbidden
|
920
|
+
Content-Type: text/plain
|
921
|
+
Content-Length: 13
|
922
|
+
|
923
|
+
Access Denied
|
924
|
+
|
925
|
+
HTTP/1.1 403 Forbidden
|
926
|
+
Content-Type: text/plain
|
927
|
+
Content-Length: 13
|
928
|
+
|
929
|
+
Access Denied
|
930
|
+
HTTP
|
931
|
+
|
932
|
+
@s = StubServer.new(response)
|
933
|
+
lambda {
|
934
|
+
conn = EventMachine::HttpRequest.new('http://127.0.0.1:8081/')
|
935
|
+
req = conn.get
|
936
|
+
req.errback { failed(http) }
|
937
|
+
req.callback { EM.stop }
|
938
|
+
}.should_not raise_error
|
939
|
+
|
940
|
+
}
|
941
|
+
end
|
942
|
+
|
851
943
|
context "User-Agent" do
|
852
944
|
it 'should default to "EventMachine HttpClient"' do
|
853
945
|
EventMachine.run {
|
@@ -885,4 +977,24 @@ describe EventMachine::HttpRequest do
|
|
885
977
|
}
|
886
978
|
end
|
887
979
|
end
|
980
|
+
|
981
|
+
context "IPv6" do
|
982
|
+
it "should perform successful GET" do
|
983
|
+
EventMachine.run {
|
984
|
+
@s = StubServer.new({
|
985
|
+
response: "HTTP/1.1 200 OK\r\n\r\nHello IPv6",
|
986
|
+
port: 8091,
|
987
|
+
host: '::1',
|
988
|
+
})
|
989
|
+
http = EventMachine::HttpRequest.new('http://[::1]:8091/').get
|
990
|
+
|
991
|
+
http.errback { failed(http) }
|
992
|
+
http.callback {
|
993
|
+
http.response_header.status.should == 200
|
994
|
+
http.response.should match(/Hello IPv6/)
|
995
|
+
EventMachine.stop
|
996
|
+
}
|
997
|
+
}
|
998
|
+
end
|
999
|
+
end
|
888
1000
|
end
|
data/spec/dns_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe EventMachine::HttpRequest do
|
|
7
7
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/redirect/badhost', :connect_timeout => 0.1).get :redirects => 1
|
8
8
|
http.callback { failed(http) }
|
9
9
|
http.errback {
|
10
|
-
http.error.should match(
|
10
|
+
http.error.should match(/unable to resolve (server |)address/)
|
11
11
|
EventMachine.stop
|
12
12
|
}
|
13
13
|
}
|
@@ -31,7 +31,7 @@ describe EventMachine::HttpRequest do
|
|
31
31
|
http = EventMachine::HttpRequest.new('http://somethinglocal/', :connect_timeout => 0.1).get
|
32
32
|
http.callback { failed(http) }
|
33
33
|
http.errback {
|
34
|
-
http.error.should match(/unable to resolve server address/)
|
34
|
+
http.error.should match(/unable to resolve (server |)address/)
|
35
35
|
http.response_header.status.should == 0
|
36
36
|
EventMachine.stop
|
37
37
|
}
|
data/spec/external_spec.rb
CHANGED
@@ -80,11 +80,11 @@ requires_connection do
|
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should detect deflate encoding" do
|
83
|
-
pending "need an endpoint which supports deflate.. MSN is no longer"
|
83
|
+
# pending "need an endpoint which supports deflate.. MSN is no longer"
|
84
84
|
EventMachine.run {
|
85
85
|
|
86
86
|
options = {:head => {"accept-encoding" => "deflate"}, :redirects => 5}
|
87
|
-
http = EventMachine::HttpRequest.new('http://www.
|
87
|
+
http = EventMachine::HttpRequest.new('http://www.libpng.org/').get options
|
88
88
|
|
89
89
|
http.errback { failed(http) }
|
90
90
|
http.callback {
|
@@ -135,7 +135,7 @@ requires_connection do
|
|
135
135
|
|
136
136
|
it "should work with keep-alive servers" do
|
137
137
|
EventMachine.run {
|
138
|
-
http = EventMachine::HttpRequest.new('
|
138
|
+
http = EventMachine::HttpRequest.new('https://github.com/igrigorik/em-http-request').get :keepalive => true
|
139
139
|
|
140
140
|
http.errback { failed(http) }
|
141
141
|
http.callback {
|
data/spec/gzip_spec.rb
CHANGED
@@ -56,6 +56,29 @@ describe EventMachine::HttpDecoders::GZip do
|
|
56
56
|
decompressed.size.should eq(32907)
|
57
57
|
end
|
58
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
|
+
|
59
82
|
it "should fail with a DecoderError if not a gzip file" do
|
60
83
|
not_a_gzip = ["1f8c08089668a650000"].pack("H*")
|
61
84
|
header = EventMachine::HttpDecoders::GZipHeader.new
|
data/spec/helper.rb
CHANGED
data/spec/http_proxy_spec.rb
CHANGED
@@ -1,90 +1,268 @@
|
|
1
1
|
require 'helper'
|
2
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
|
+
|
3
34
|
describe EventMachine::HttpRequest do
|
4
35
|
|
5
36
|
context "connections via" do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
http.
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
+
}
|
19
52
|
}
|
20
|
-
|
21
|
-
end
|
53
|
+
end
|
22
54
|
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
26
58
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
+
}
|
33
66
|
}
|
34
|
-
|
35
|
-
end
|
67
|
+
end
|
36
68
|
|
37
|
-
|
38
|
-
|
69
|
+
it "should send absolute URIs to the proxy server" do
|
70
|
+
EventMachine.run {
|
39
71
|
|
40
|
-
|
72
|
+
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/?q=test', proxy).get
|
41
73
|
|
42
|
-
|
43
|
-
|
44
|
-
|
74
|
+
http.errback { failed(http) }
|
75
|
+
http.callback {
|
76
|
+
http.response_header.status.should == 200
|
45
77
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
+
}
|
51
84
|
}
|
52
|
-
|
53
|
-
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should strip basic auth from before the host in URI sent to proxy" do
|
88
|
+
EventMachine.run {
|
54
89
|
|
55
|
-
|
56
|
-
EventMachine.run {
|
57
|
-
http = EventMachine::HttpRequest.new('http://127.0.0.1:8090/', proxy).get :query => { 'q' => 'test' }
|
90
|
+
http = EventMachine::HttpRequest.new('http://user:pass@127.0.0.1:8090/echo_authorization_header', proxy).get
|
58
91
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
+
}
|
64
101
|
}
|
65
|
-
|
66
|
-
end
|
102
|
+
end
|
67
103
|
|
68
|
-
|
69
|
-
|
70
|
-
|
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' }
|
71
107
|
|
72
|
-
|
73
|
-
|
74
|
-
|
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
|
75
120
|
|
76
|
-
http.
|
77
|
-
http.
|
121
|
+
http.errback { failed(http) }
|
122
|
+
http.callback {
|
123
|
+
http.response_header.status.should == 200
|
78
124
|
|
79
|
-
|
80
|
-
|
81
|
-
http.last_effective_url.to_s.should == 'http://127.0.0.1:8090/gzip'
|
82
|
-
http.redirects.should == 1
|
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'
|
83
127
|
|
84
|
-
|
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
|
+
}
|
85
135
|
}
|
86
|
-
|
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
|
87
196
|
end
|
88
197
|
end
|
89
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
|
90
268
|
end
|