em-http-request 1.1.2 → 1.1.7
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 +2 -2
- 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 +7 -6
- 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 +10 -3
- 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 +114 -2
- 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/pipelining_spec.rb +4 -4
- data/spec/redirect_spec.rb +65 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/ssl_spec.rb +52 -1
- data/spec/stallion.rb +20 -5
- data/spec/stub_server.rb +6 -3
- metadata +39 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c7562e4d20c35c54a9319250e665a883c810546cb657d8f897591e113999ed3a
|
4
|
+
data.tar.gz: 643bf26ea7bfa2a85d6e4257a475295c16eca044ff0d04341537793f07d5bd04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d9d1f441081a034f29447cb99b26c73ef7767a989c31df007e1ecfc6ea8db1f4cbe00fb26c0f81b59108f53b54dfbccd51ea9140fd5286efaca6095b45943ad
|
7
|
+
data.tar.gz: 690dc944373085313c41c484edd25366036a3da46855b6a153aab65c19aed961d94d202de07cb3f5f8406585bb5c3a66998913debcba4d02796fb1c8f04be7c1
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
# EM-HTTP-Request
|
1
|
+
# EM-HTTP-Request
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/em-http-request.svg)](http://rubygems.org/gems/em-http-request) [![Build Status](https://travis-ci.org/igrigorik/em-http-request.svg)](https://travis-ci.org/igrigorik/em-http-request)
|
2
4
|
|
3
5
|
Async (EventMachine) HTTP client, with support for:
|
4
6
|
|
@@ -10,7 +12,7 @@ Async (EventMachine) HTTP client, with support for:
|
|
10
12
|
- Streaming file uploads
|
11
13
|
- HTTP proxy and SOCKS5 support
|
12
14
|
- Basic Auth & OAuth
|
13
|
-
- Connection-level &
|
15
|
+
- Connection-level & global middleware support
|
14
16
|
- HTTP parser via [http_parser.rb](https://github.com/tmm1/http_parser.rb)
|
15
17
|
- Works wherever EventMachine runs: Rubinius, JRuby, MRI
|
16
18
|
|
@@ -18,7 +20,7 @@ Async (EventMachine) HTTP client, with support for:
|
|
18
20
|
|
19
21
|
gem install em-http-request
|
20
22
|
|
21
|
-
- Introductory [screencast](http://everburning.com/news/eventmachine-screencast-em-http-request
|
23
|
+
- Introductory [screencast](http://everburning.com/news/eventmachine-screencast-em-http-request)
|
22
24
|
- [Issuing GET/POST/etc requests](https://github.com/igrigorik/em-http-request/wiki/Issuing-Requests)
|
23
25
|
- [Issuing parallel requests with Multi interface](https://github.com/igrigorik/em-http-request/wiki/Parallel-Requests)
|
24
26
|
- [Handling Redirects & Timeouts](https://github.com/igrigorik/em-http-request/wiki/Redirects-and-Timeouts)
|
@@ -54,7 +56,6 @@ Several higher-order Ruby projects have incorporated em-http and other Ruby HTTP
|
|
54
56
|
- [Firering](https://github.com/EmmanuelOga/firering) - Eventmachine powered Campfire API
|
55
57
|
- [RDaneel](https://github.com/hasmanydevelopers/RDaneel) - Ruby crawler which respects robots.txt
|
56
58
|
- [em-eventsource](https://github.com/AF83/em-eventsource) - EventSource client for EventMachine
|
57
|
-
- [sinatra-synchrony](https://github.com/kyledrake/sinatra-synchrony) - Sinatra plugin for synchronous use of EM
|
58
59
|
- and many others.. drop me a link if you want yours included!
|
59
60
|
|
60
61
|
### License
|
data/em-http-request.gemspec
CHANGED
@@ -16,14 +16,14 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.rubyforge_project = 'em-http-request'
|
17
17
|
|
18
18
|
s.add_dependency 'addressable', '>= 2.3.4'
|
19
|
-
s.add_dependency 'cookiejar'
|
19
|
+
s.add_dependency 'cookiejar', '!= 0.3.1'
|
20
20
|
s.add_dependency 'em-socksify', '>= 0.3'
|
21
21
|
s.add_dependency 'eventmachine', '>= 1.0.3'
|
22
22
|
s.add_dependency 'http_parser.rb', '>= 0.6.0'
|
23
23
|
|
24
24
|
s.add_development_dependency 'mongrel', '~> 1.2.0.pre2'
|
25
25
|
s.add_development_dependency 'multi_json'
|
26
|
-
s.add_development_dependency 'rack'
|
26
|
+
s.add_development_dependency 'rack', '< 2.0'
|
27
27
|
s.add_development_dependency 'rake'
|
28
28
|
s.add_development_dependency 'rspec'
|
29
29
|
|
data/lib/em-http.rb
CHANGED
data/lib/em-http/client.rb
CHANGED
@@ -21,7 +21,7 @@ module EventMachine
|
|
21
21
|
|
22
22
|
CRLF="\r\n"
|
23
23
|
|
24
|
-
attr_accessor :state, :response
|
24
|
+
attr_accessor :state, :response, :conn
|
25
25
|
attr_reader :response_header, :error, :content_charset, :req, :cookies
|
26
26
|
|
27
27
|
def initialize(conn, options)
|
@@ -100,14 +100,13 @@ module EventMachine
|
|
100
100
|
|
101
101
|
@cookies.clear
|
102
102
|
@cookies = @cookiejar.get(@response_header.location).map(&:to_s) if @req.pass_cookies
|
103
|
-
@req.set_uri(@response_header.location)
|
104
103
|
|
105
|
-
@conn.redirect(self)
|
104
|
+
@conn.redirect(self, @response_header.location)
|
106
105
|
else
|
107
106
|
succeed(self)
|
108
107
|
end
|
109
108
|
|
110
|
-
rescue
|
109
|
+
rescue => e
|
111
110
|
on_error(e.message)
|
112
111
|
end
|
113
112
|
else
|
@@ -156,11 +155,16 @@ module EventMachine
|
|
156
155
|
|
157
156
|
# Set the User-Agent if it hasn't been specified
|
158
157
|
if !head.key?('user-agent')
|
159
|
-
head['user-agent'] =
|
158
|
+
head['user-agent'] = 'EventMachine HttpClient'
|
160
159
|
elsif head['user-agent'].nil?
|
161
160
|
head.delete('user-agent')
|
162
161
|
end
|
163
162
|
|
163
|
+
# Set the Accept-Encoding header if none is provided
|
164
|
+
if !head.key?('accept-encoding') && req.compressed
|
165
|
+
head['accept-encoding'] = 'gzip, compressed'
|
166
|
+
end
|
167
|
+
|
164
168
|
# Set the auth from the URI if given
|
165
169
|
head['Authorization'] = @req.uri.userinfo.split(/:/, 2) if @req.uri.userinfo
|
166
170
|
|
@@ -178,7 +182,7 @@ module EventMachine
|
|
178
182
|
# Set the Content-Length if body is given,
|
179
183
|
# or we're doing an empty post or put
|
180
184
|
if body
|
181
|
-
head['content-length']
|
185
|
+
head['content-length'] ||= body.respond_to?(:bytesize) ? body.bytesize : body.size
|
182
186
|
elsif @req.method == 'POST' or @req.method == 'PUT'
|
183
187
|
# wont happen if body is set and we already set content-length above
|
184
188
|
head['content-length'] ||= 0
|
@@ -189,16 +193,13 @@ module EventMachine
|
|
189
193
|
head['content-type'] = 'application/x-www-form-urlencoded'
|
190
194
|
end
|
191
195
|
|
192
|
-
request_header ||= encode_request(@req.method, @req.uri, query, @conn.connopts
|
196
|
+
request_header ||= encode_request(@req.method, @req.uri, query, @conn.connopts)
|
193
197
|
request_header << encode_headers(head)
|
194
198
|
request_header << CRLF
|
195
199
|
@conn.send_data request_header
|
196
200
|
|
197
|
-
|
198
|
-
|
199
|
-
elsif @req.file
|
200
|
-
@conn.stream_file_data @req.file, :http_chunks => false
|
201
|
-
end
|
201
|
+
@req_body = body || (@req.file && Pathname.new(@req.file))
|
202
|
+
send_request_body unless @req.headers['expect'] == '100-continue'
|
202
203
|
end
|
203
204
|
|
204
205
|
def on_body_data(data)
|
@@ -222,6 +223,28 @@ module EventMachine
|
|
222
223
|
end
|
223
224
|
end
|
224
225
|
|
226
|
+
def request_body_pending?
|
227
|
+
!!@req_body
|
228
|
+
end
|
229
|
+
|
230
|
+
def send_request_body
|
231
|
+
return if @req_body.nil?
|
232
|
+
|
233
|
+
if @req_body.is_a?(String)
|
234
|
+
@conn.send_data @req_body
|
235
|
+
|
236
|
+
elsif @req_body.is_a?(Pathname)
|
237
|
+
@conn.stream_file_data @req_body.to_path, http_chunks: false
|
238
|
+
|
239
|
+
elsif @req_body.respond_to?(:read) && @req_body.respond_to?(:eof?) # IO or IO-like object
|
240
|
+
@conn.stream_data @req_body
|
241
|
+
|
242
|
+
else
|
243
|
+
raise "Don't know how to send request body: #{@req_body.inspect}"
|
244
|
+
end
|
245
|
+
@req_body = nil
|
246
|
+
end
|
247
|
+
|
225
248
|
def parse_response_header(header, version, status)
|
226
249
|
@response_header.raw = header
|
227
250
|
header.each do |key, val|
|
data/lib/em-http/decoders.rb
CHANGED
@@ -127,7 +127,6 @@ module EventMachine::HttpDecoders
|
|
127
127
|
|
128
128
|
def extract_stream(compressed)
|
129
129
|
@data << compressed
|
130
|
-
pos = @pos
|
131
130
|
|
132
131
|
while !eof? && !finished?
|
133
132
|
buffer = ""
|
@@ -208,7 +207,7 @@ module EventMachine::HttpDecoders
|
|
208
207
|
end
|
209
208
|
|
210
209
|
if finished?
|
211
|
-
compressed[(@pos -
|
210
|
+
compressed[(@pos - (@data.length - compressed.length))..-1]
|
212
211
|
else
|
213
212
|
""
|
214
213
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class HttpClientOptions
|
2
2
|
attr_reader :uri, :method, :host, :port
|
3
3
|
attr_reader :headers, :file, :body, :query, :path
|
4
|
-
attr_reader :keepalive, :pass_cookies, :decoding
|
4
|
+
attr_reader :keepalive, :pass_cookies, :decoding, :compressed
|
5
5
|
|
6
6
|
attr_accessor :followed, :redirects
|
7
7
|
|
@@ -12,31 +12,31 @@ class HttpClientOptions
|
|
12
12
|
|
13
13
|
@method = method.to_s.upcase
|
14
14
|
@headers = options[:head] || {}
|
15
|
-
@query = options[:query]
|
16
|
-
|
17
15
|
|
18
16
|
@file = options[:file]
|
19
17
|
@body = options[:body]
|
20
18
|
|
21
19
|
@pass_cookies = options.fetch(:pass_cookies, true) # pass cookies between redirects
|
22
20
|
@decoding = options.fetch(:decoding, true) # auto-decode compressed response
|
21
|
+
@compressed = options.fetch(:compressed, true) # auto-negotiated compressed response
|
23
22
|
|
24
|
-
set_uri(uri, options[:path])
|
23
|
+
set_uri(uri, options[:path], options[:query])
|
25
24
|
end
|
26
25
|
|
27
26
|
def follow_redirect?; @followed < @redirects; end
|
28
27
|
def ssl?; @uri.scheme == "https" || @uri.port == 443; end
|
29
28
|
def no_body?; @method == "HEAD"; end
|
30
29
|
|
31
|
-
def set_uri(uri, path = nil)
|
30
|
+
def set_uri(uri, path = nil, query = nil)
|
32
31
|
uri = uri.kind_of?(Addressable::URI) ? uri : Addressable::URI::parse(uri.to_s)
|
33
32
|
uri.path = path if path
|
34
33
|
uri.path = '/' if uri.path.empty?
|
35
34
|
|
36
35
|
@uri = uri
|
37
36
|
@path = uri.path
|
38
|
-
@host = uri.
|
37
|
+
@host = uri.hostname
|
39
38
|
@port = uri.port
|
39
|
+
@query = query
|
40
40
|
|
41
41
|
# Make sure the ports are set as Addressable::URI doesn't
|
42
42
|
# set the port if it isn't there
|
@@ -44,5 +44,6 @@ class HttpClientOptions
|
|
44
44
|
@port = @uri.scheme == "https" ? 443 : 80
|
45
45
|
end
|
46
46
|
|
47
|
+
uri
|
47
48
|
end
|
48
49
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'em/io_streamer'
|
2
|
+
|
1
3
|
module EventMachine
|
2
4
|
|
3
5
|
module HTTPMethods
|
@@ -20,7 +22,11 @@ module EventMachine
|
|
20
22
|
end
|
21
23
|
|
22
24
|
def receive_data(data)
|
23
|
-
|
25
|
+
begin
|
26
|
+
@parent.receive_data data
|
27
|
+
rescue EventMachine::Connectify::CONNECTError => e
|
28
|
+
@parent.close(e.message)
|
29
|
+
end
|
24
30
|
end
|
25
31
|
|
26
32
|
def connection_completed
|
@@ -30,6 +36,62 @@ module EventMachine
|
|
30
36
|
def unbind(reason=nil)
|
31
37
|
@parent.unbind(reason)
|
32
38
|
end
|
39
|
+
|
40
|
+
# TLS verification support, original implementation by Mislav Marohnić
|
41
|
+
# https://github.com/lostisland/faraday/blob/63cf47c95b573539f047c729bd9ad67560bc83ff/lib/faraday/adapter/em_http_ssl_patch.rb
|
42
|
+
def ssl_verify_peer(cert_string)
|
43
|
+
cert = nil
|
44
|
+
begin
|
45
|
+
cert = OpenSSL::X509::Certificate.new(cert_string)
|
46
|
+
rescue OpenSSL::X509::CertificateError
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
@last_seen_cert = cert
|
51
|
+
|
52
|
+
if certificate_store.verify(@last_seen_cert)
|
53
|
+
begin
|
54
|
+
certificate_store.add_cert(@last_seen_cert)
|
55
|
+
rescue OpenSSL::X509::StoreError => e
|
56
|
+
raise e unless e.message == 'cert already in hash table'
|
57
|
+
end
|
58
|
+
true
|
59
|
+
else
|
60
|
+
raise OpenSSL::SSL::SSLError.new(%(unable to verify the server certificate for "#{host}"))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def ssl_handshake_completed
|
65
|
+
unless verify_peer?
|
66
|
+
warn "[WARNING; em-http-request] TLS hostname validation is disabled (use 'tls: {verify_peer: true}'), see" +
|
67
|
+
" CVE-2020-13482 and https://github.com/igrigorik/em-http-request/issues/339 for details" unless parent.connopts.tls.has_key?(:verify_peer)
|
68
|
+
return true
|
69
|
+
end
|
70
|
+
|
71
|
+
unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host)
|
72
|
+
raise OpenSSL::SSL::SSLError.new(%(host "#{host}" does not match the server certificate))
|
73
|
+
else
|
74
|
+
true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def verify_peer?
|
79
|
+
parent.connopts.tls[:verify_peer]
|
80
|
+
end
|
81
|
+
|
82
|
+
def host
|
83
|
+
parent.connopts.host
|
84
|
+
end
|
85
|
+
|
86
|
+
def certificate_store
|
87
|
+
@certificate_store ||= begin
|
88
|
+
store = OpenSSL::X509::Store.new
|
89
|
+
store.set_default_paths
|
90
|
+
ca_file = parent.connopts.tls[:cert_chain_file]
|
91
|
+
store.add_file(ca_file) if ca_file
|
92
|
+
store
|
93
|
+
end
|
94
|
+
end
|
33
95
|
end
|
34
96
|
|
35
97
|
class HttpConnection
|
@@ -37,8 +99,8 @@ module EventMachine
|
|
37
99
|
include Socksify
|
38
100
|
include Connectify
|
39
101
|
|
40
|
-
attr_reader :deferred
|
41
|
-
attr_accessor :error, :connopts, :uri
|
102
|
+
attr_reader :deferred, :conn
|
103
|
+
attr_accessor :error, :connopts, :uri
|
42
104
|
|
43
105
|
def initialize
|
44
106
|
@deferred = true
|
@@ -97,7 +159,7 @@ module EventMachine
|
|
97
159
|
@conn.callback { c.connection_completed }
|
98
160
|
|
99
161
|
middleware.each do |m|
|
100
|
-
c.callback
|
162
|
+
c.callback(&m.method(:response)) if m.respond_to?(:response)
|
101
163
|
end
|
102
164
|
|
103
165
|
@clients.push c
|
@@ -114,8 +176,21 @@ module EventMachine
|
|
114
176
|
@p = Http::Parser.new
|
115
177
|
@p.header_value_type = :mixed
|
116
178
|
@p.on_headers_complete = proc do |h|
|
117
|
-
client
|
118
|
-
|
179
|
+
if client
|
180
|
+
if @p.status_code == 100
|
181
|
+
client.send_request_body
|
182
|
+
@p.reset!
|
183
|
+
else
|
184
|
+
client.parse_response_header(h, @p.http_version, @p.status_code)
|
185
|
+
:reset if client.req.no_body?
|
186
|
+
end
|
187
|
+
else
|
188
|
+
# if we receive unexpected data without a pending client request
|
189
|
+
# reset the parser to avoid firing any further callbacks and close
|
190
|
+
# the connection because we're processing invalid HTTP
|
191
|
+
@p.reset!
|
192
|
+
unbind
|
193
|
+
end
|
119
194
|
end
|
120
195
|
|
121
196
|
@p.on_body = proc do |b|
|
@@ -152,9 +227,9 @@ module EventMachine
|
|
152
227
|
@peer = @conn.get_peername
|
153
228
|
|
154
229
|
if @connopts.socks_proxy?
|
155
|
-
socksify(client.req.uri.
|
230
|
+
socksify(client.req.uri.hostname, client.req.uri.inferred_port, *@connopts.proxy[:authorization]) { start }
|
156
231
|
elsif @connopts.connect_proxy?
|
157
|
-
connectify(client.req.uri.
|
232
|
+
connectify(client.req.uri.hostname, client.req.uri.inferred_port, *@connopts.proxy[:authorization]) { start }
|
158
233
|
else
|
159
234
|
start
|
160
235
|
end
|
@@ -165,8 +240,33 @@ module EventMachine
|
|
165
240
|
@conn.succeed
|
166
241
|
end
|
167
242
|
|
168
|
-
def redirect(client)
|
169
|
-
|
243
|
+
def redirect(client, new_location)
|
244
|
+
old_location = client.req.uri
|
245
|
+
new_location = client.req.set_uri(new_location)
|
246
|
+
|
247
|
+
if client.req.keepalive
|
248
|
+
# Application requested a keep-alive connection but one of the requests
|
249
|
+
# hits a cross-origin redirect. We need to open a new connection and
|
250
|
+
# let both connections proceed simultaneously.
|
251
|
+
if old_location.origin != new_location.origin
|
252
|
+
conn = HttpConnection.new
|
253
|
+
client.conn = conn
|
254
|
+
conn.connopts = @connopts
|
255
|
+
conn.connopts.https = new_location.scheme == "https"
|
256
|
+
conn.uri = client.req.uri
|
257
|
+
conn.activate_connection(client)
|
258
|
+
|
259
|
+
# If the redirect is a same-origin redirect on a keep-alive request
|
260
|
+
# then immidiately dispatch the request over existing connection.
|
261
|
+
else
|
262
|
+
@clients.push client
|
263
|
+
client.connection_completed
|
264
|
+
end
|
265
|
+
else
|
266
|
+
# If connection is not keep-alive the unbind will fire and we'll
|
267
|
+
# reconnect using the same connection object.
|
268
|
+
@pending.push client
|
269
|
+
end
|
170
270
|
end
|
171
271
|
|
172
272
|
def unbind(reason = nil)
|
@@ -208,6 +308,10 @@ module EventMachine
|
|
208
308
|
@conn.stream_file_data filename, args
|
209
309
|
end
|
210
310
|
|
311
|
+
def stream_data(io, opts = {})
|
312
|
+
EventMachine::IOStreamer.new(self, io, opts)
|
313
|
+
end
|
314
|
+
|
211
315
|
private
|
212
316
|
|
213
317
|
def client
|
@@ -1,13 +1,13 @@
|
|
1
1
|
class HttpConnectionOptions
|
2
2
|
attr_reader :host, :port, :tls, :proxy, :bind, :bind_port
|
3
3
|
attr_reader :connect_timeout, :inactivity_timeout
|
4
|
+
attr_writer :https
|
4
5
|
|
5
6
|
def initialize(uri, options)
|
6
7
|
@connect_timeout = options[:connect_timeout] || 5 # default connection setup timeout
|
7
8
|
@inactivity_timeout = options[:inactivity_timeout] ||= 10 # default connection inactivity (post-setup) timeout
|
8
9
|
|
9
10
|
@tls = options[:tls] || options[:ssl] || {}
|
10
|
-
@proxy = options[:proxy]
|
11
11
|
|
12
12
|
if bind = options[:bind]
|
13
13
|
@bind = bind[:host] || '0.0.0.0'
|
@@ -20,12 +20,15 @@ class HttpConnectionOptions
|
|
20
20
|
uri = uri.kind_of?(Addressable::URI) ? uri : Addressable::URI::parse(uri.to_s)
|
21
21
|
@https = uri.scheme == "https"
|
22
22
|
uri.port ||= (@https ? 443 : 80)
|
23
|
+
@tls[:sni_hostname] = uri.hostname
|
23
24
|
|
24
|
-
|
25
|
+
@proxy = options[:proxy] || proxy_from_env
|
26
|
+
|
27
|
+
if proxy
|
25
28
|
@host = proxy[:host]
|
26
29
|
@port = proxy[:port]
|
27
30
|
else
|
28
|
-
@host = uri.
|
31
|
+
@host = uri.hostname
|
29
32
|
@port = uri.port
|
30
33
|
end
|
31
34
|
end
|
@@ -41,4 +44,27 @@ class HttpConnectionOptions
|
|
41
44
|
def socks_proxy?
|
42
45
|
@proxy && (@proxy[:type] == :socks5)
|
43
46
|
end
|
47
|
+
|
48
|
+
def proxy_from_env
|
49
|
+
# TODO: Add support for $http_no_proxy or $no_proxy ?
|
50
|
+
proxy_str = if @https
|
51
|
+
ENV['HTTPS_PROXY'] || ENV['https_proxy']
|
52
|
+
else
|
53
|
+
ENV['HTTP_PROXY'] || ENV['http_proxy']
|
54
|
+
|
55
|
+
# Fall-back to $ALL_PROXY if none of the above env-vars have values
|
56
|
+
end || ENV['ALL_PROXY']
|
57
|
+
|
58
|
+
# Addressable::URI::parse will return `nil` if given `nil` and an empty URL for an empty string
|
59
|
+
# so, let's short-circuit that:
|
60
|
+
return if !proxy_str || proxy_str.empty?
|
61
|
+
|
62
|
+
proxy_env_uri = Addressable::URI::parse(proxy_str)
|
63
|
+
{ :host => proxy_env_uri.host, :port => proxy_env_uri.port, :type => :http }
|
64
|
+
|
65
|
+
rescue Addressable::URI::InvalidURIError
|
66
|
+
# An invalid env-var shouldn't crash the config step, IMHO.
|
67
|
+
# We should somehow log / warn about this, perhaps...
|
68
|
+
return
|
69
|
+
end
|
44
70
|
end
|